Atari Explorer Online: 16-Oct-93 Programmers' Journal #2

From: Bruce D. Nelson (aa789@cleveland.Freenet.Edu)
Date: 10/29/93-11:38:48 PM Z


From: aa789@cleveland.Freenet.Edu (Bruce D. Nelson)
Subject: Atari Explorer Online: 16-Oct-93 Programmers' Journal #2
Date: Fri Oct 29 23:38:48 1993


/***********************************************************************
    Title:          AEOPJ2.TXT

    Created:        August 13, 1993
    Last Modified:  October 16, 1993

    Purpose:        Second installment of AEO Programmers' Journal

    Editor:         Albert Dayes

    Legal Notes:    Copyright ; 1993 Subspace Publishers

***********************************************************************/

Publisher = Michael Lindsay                               [GE: EXPLORER]
Managing Editor = Travis Guy                               [GE: AEO.MAG]
Editor = Albert Dayes                      [GE: AEO.1] [CIS: 70007,3615]
Technical Editor = Carl Barron           [GE: CBARRON] [CIS: 75066,3204]
GFA BASIC columnist = Eric Goodman                           [GE: AEO.6]
OBJECT::ATARI columnist = Warwick Allison      [In: warwick@cs.uq.oz.au]
68K columnist = Damien M. Jones                                [GE: DMJ]

Contributing:

Laurent Chemla                        [ In: laurent@brasil.frmug.fr.net]
Loic Duval                                          [ CIS: 100015,3044 ]
                                                    [ GE: ATARI-FRANCE ]
                                        [ In: loic@brasil.frmug.fr.net ]
Kris Gasteiger                                       [ CIS: 73637,2004 ]
Alexandre Lemaresquier                  [ In: alex@brasil.frmug.fr.net ]
Raphael Lemoine                      [ In: raphael@brasil.frmug.fr.net ]
Daniel Verite                         [ In: daniel@brasil.frmug.fr.net ]
Ron Whittam                                            [ GE: R.WHITTAM ]

/***********************************************************************/

Table of Contents:

* Editorial
* Meet the Authors ............. short biographical notes on the authors
* What is in this issue of AEO-PJ
* A note from the IAAD .............. They want to help Atari Developers
* 68K Column ................. Some Assembly Required by Damien M. Jones
* C Column ....................... First steps to learning C programming
* Advanced Computing ..... Carl Barron explores a practical side to Flex
* Hard Core .... Interview with Charles Smeton author of STraight Fax! 2
* Dabbling in PASCAL ......... Kris Gasteiger explains Pascal and Sherry
* Practical DSP .................... Programming the 56001 by BrainStorm
* LIB [ new file(s) ] ................. X11R5 and GNU CD-ROM disc review
* Periodicals ......... The Atari Compendium reviewed by Damien M. Jones
* OBJECT::ATARI ............... Warwick Allison examines C++ and GEM VDI
* In the Trenches ............ Solving "real-world" programming problems
* Language Watch ................... Current versions of developer tools
* Bad Example ........................... Do you really want to do that?
* On the Networks ...................... Interactive programming on-line
* Network Sign-up Information
* User View ............................................. by Ron Whittam
* Brain Stem rotator ..................... A true programming challenge?
* Glossary of Terms
* ATARI DEVELOPER INFORMATION ..... Where to get the official Atari Docs
* Sources of Information ..................... References for this issue
* Post Increment ................... What is coming up in the next issue
* LEGAL NOTES

-------------------------------------------------------------------------
     Editorial:  "Real-Time Error Correction & Car Dealers"
                     By: Albert Dayes
-------------------------------------------------------------------------

The on-line networks provide users with a amount of interaction. The
type of interaction includes writing/reading messages, file transfers
and real-time conferences and something more study groups.

On Compuserve, programming related study groups were pioneered by
Richard Cohen in the Computer Language Forum (GO CLMFORUM)
approximately four years ago. Basically the group chooses a
programming book and then reads a chapter or two per week. As one
completes the chapter one can post his/her comments in the forum.
This produces a long running discussion that continues until that
particular book is completed. Then another book is chosen and the
cycle repeats itself. The current book that is currently being
discussed is Code Complete - A practical handbook of software
construction by Steve McConnell (publisher: Microsoft Press: ISBN
1-55615-484-4).

This would be something very useful to do in the Atari world as well.
We could choose a programming book on C for example or use a more
Atari platform specific book like C-manship Complete by Clayton
Walnum. I am just using C as an example since they could apply to many
different languages and/or programming topics. It is also possible
that many study groups could run concurrently as well. There are
several advantages that I can see currently:

A) "Real-Time" Error Correction of each other and the book.
B) Discussion of many important side issues in addition to the main
   topic.
C) New ideas/techniques for solving a particular problem.
D) Working code fragments (very important).
E) Get more people involved in discussing programming in general.

And there are many more...

Speaking of error correction one thing to always look at when
purchasing development tools is how the developer resolves disputes.
Its the same thing when one goes to purchase a car or anything else.
You are not interested in those who have perfectly working vehicles at
all. You are interested in one thing and one thing only. How was the
difference of opinion also known as a dispute resolved? Was it
resolved constructively?  Was it acted upon in good faith? If it's not
to the advantage of the car dealer how did he/she handle it? Did any
other car owners have similar problems?  Were the problems solved?
Were they solved to both the car owners' and the car dealer's
satisfaction? How does the car dealer talk about other car dealers in
the area? Is it positive and constructive? Does it give you the
impression that his/her opinion about other car dealers is a honest
accessment? If a car dealer has a dispute with another car dealer how
was it handled? Are the points of argument legitimate ones? Did both
car dealers act in good faith to solve the problem at hand? Was it
ever solved? And if it was solved was it done in a positive,
constructive and diplomatic manner?

These are similar to the type of things I always take careful
consideration of when I make a software development tool purchase. On
an online service it is much easier to get a very good indication of
how disputes are resolved as many of you already know.

Many of you have sent e-mail or posted in public forums on the various
on-line services on our first issue. EVERY MESSAGE IS GREATLY
APPRECIATED so keep sending your questions and comments! Some of you
talked about problems with understanding the terms used throughout the
first issue as well.

The early part of learning programming involves learning new terms and
what they mean. This can be very frustrating when one does not
understand the meaning of the terms. PLEASE ASK QUESTIONS, send
EMail, post in public forums, etc. Some people worry about "stupid"
questions.... there is no such thing as a stupid question!!! Every
question is useful and helps everyone. Many times the so called
"simple" questions are some of the hardest ones to answer. So send
EMail, post in public forums and ask questions since discussion of
programming related problems will help everyone learn something new.
We welcome all feedback both positive and negative so feel free to
write anytime. Feedback is not just related to the current issue but
anything that one wishes to discuss. Sometimes we can assume that
everyone is coming from the same direction but that is not always the
case. We want to be sure that you are working on solving your problem
(the fun part) and not fighting with the syntax of the programming
language.

-- Albert

CIS: 70007,3615
GE:  AEO.1
In:  70007.3615@Compuserve.com

/**********************************************************************/
                      Meet the Authors
/**********************************************************************/

Brainstorm is a 4-person company writing development tools, system and
DSP programs, as well as high-end algorithm software. They are known
for their Atari products such as Adebug/Assemble (an assembly
development package including a low and source level debugger), the
official Atari DSP Debugger and their JPEG and MPEG decoders.

Brainstorm is composed of:

Laurent Chemla (communication - hardware link - system development)
Alexandre Lemaresquier (manager - GEM development - system development)
Raphael Lemoine (graphics programming - DSP programming - system
                 development)
Daniel Verite (image recognition - parallel programming - system
               development)

//// Loic Duval

Loic is the Product Manager & Developer Support Manager of Atari
France. He bought his first ST in September 1985 and was one of the
first registered French developers. He joined Atari France in October
1991. Previously he was a journalist at ST Magazine and other French
computer magazines then chief editor of Atari Magazine.


//// Kris Gasteiger

I received my first computer, an Atari 520ST for Christmas of 1986.
Before then, I was a mild techno-phobe. The ease of use and
programmability caught me, and I've been dabbling ever since.

I taught myself ST BASIC, graduated to LDW BASIC, got discouraged by
the environment of GFA BASIC, and finally decided I liked ICD/OSS
Personal Pascal enough to stop my search for a "decent" programming
language. (I'd also over spent my budget on software about then). I
may have gone on to learn C, but Personal Pascal seems adequate to my
needs.

I commented on the lack of information on Pascal programming in this,
journal, and was invited to fill that gap. My article(s) will be
pointed towards the beginner, with the hope that feedback will help me
find a direction for future exploration.

I moved to N. Billerica, MA a year ago, quitting my job in a state
park in upstate New York to be with my lady. I worked as a temp for a
short time, and am currently working full time for a health-care
supplier as a packer (big come down in pay, but what the heck, love
will mess your mind, no how).


//// Damien M. Jones (DMJ)

Damien M. Jones started programming on the Atari ST in 1988, before he
even owned one. He bought one so he could program in GFA BASIC, and
has learned continually over the past five years, learning C,
assembly, and various other languages. In the past two years he has
written Sound Lab, DMJ GIF, Spc Thumb, ReNameIt! (with Tom Hayslett),
and has recently released his first commercial product, View II.

His "real" job involves writing C code for Windows, but he still
prefers the Atari ST/Falcon line.


//// Ron Whittam

OCCUPATION: "Computer Operations Technical Support" in a large bank
holding company's MAINFRAME COMPUTER CENTER. My job title denotes
"computer operations" in deference to "PC/LAN operations". The
"technical" refers to ANY technical, hardware, software, or logistics
problem encountered. The "support" refers to help and assistance,
(this differs depending on the type and extent of the problem). My
primary focus is to help the end user communicate with the programmer.
I look for possible problems and take steps (or write procedures) to
avoid them. When a problem is reported I determine the possible causes
(human error, code error, communication error, hardware malfunction,
logistic or distribution error, etc.) and then coordinate the
resolution. I work with the Bank's customers to insure their data is
transmitted to or from the bank properly via modem, data-line,
magnetic tape, pc disk media, etc. I also test, evaluate, install, and
maintain software; and train the computer operators in its use. My
responsibilities include Disaster Contingency and Business Resumption
planning. I have no formal Computer training. My training has been "on
the job" for the past 6 years.

HOME COMPUTERS: I bought a TI-99/4A computer in 1983. I bought my
first Atari 1040 ST in 1987 and my second Atari 1040 ST in 1993. I
also own an HP CS laptop (NEC-30 CPU) and a Intel386SX IBM clone with
a ROM Drive, hand scanner, and sound board. I have installed (and
removed) PC-ditto II in the Atari, installed TOS 1.4, installed
Xtra-RAM Deluxe (4megs). I enjoy programming (my WINNER11.LZH program
was on the STI's August DOM). However my basic use of the ATARI is
writing. I use PROTEXT, but plan to buy AW soon. I also use MasterPlan
for my financial work.

COMMUNITY: I am the president of the "Atari Boise Users Group" and
have been for 3 years. We meet monthly. I was an assistant SYSOP on a
local BBS until the SYSOP closed the board. I occasionally teach Adult
community education classes in DOS, Windows, or LOTUS. I consult,
teach and tutor, and offer basic help to anyone who has any type of
computer. I have helped media buyers, florists, homemakers,
copywriters, advertizing agents, farmers, etc. with their home and
business computers.

NON-COMPUTER: I have been a pastor (youth director) at Parkview Bible
Fellowship for 4 years. I spend a lot of time helping junior and
senior high youth. I teach Bible classes and plan activities with the
youth. It's fun but it's also rewarding as I help the kids "grow up".

MARRIED: Yes. 10 years. (KIDS: No -- PETS: Yes).


/**********************************************************************/
      What is in this issue of AEO-PJ and new in the Atari market
      By: Albert Dayes
/**********************************************************************/

//// Special Thanks

This issue we have a special treat from Atari France and BrainStorm.
They will be providing a series of articles on programming the
FALCON030's digital signal processor (DSP). Special thanks to Loic
Duval of Atari France for initiating and putting this deal together!

We also have some special guests and new columnists in this is as
well. We would like to thank Kris Gasteiger, Damien M. Jones, Charles
Smeton, and Ron Whittam for their contributions to this issue. And of
course all our regular writers and columnists deserve credit as well.
We regret that Eric Goodman (our GFA BASIC columnist) was not able to
complete his article due to some hardware problems. Look for it in the
next issue of AEO-PJ. Be sure to send everyone some feedback too!

//// Ditch Digging

Also this issue will debut a new column called "In the Trenches." The
inspiration for this column is from Skin Diver magazine. In Skin Diver
magazine they had a diver column that spoke about "stupid" things
people did and what they learned from it. One tells of a scuba diver
who went into a cave without a light and got lost. Another tells of
diving under the ice without a rope to guide his way back. Not all of
the stories are this bad but one gets the general idea.

This column will not deal specifically with the "stupid" mistakes as
such, but with the entire process of problem solving. Solving
programming related problems is always a learning experience - and
sharing programming experiences is what this is all about. The goal is
to have a different programmer/developer write this column for every
issue.

//// User View?

In the last issue some thought that the user view was to discuss User
Interfaces (UI). It was not designed to discuss User Interfaces in
general or specifically. This entire column is designated for USERS
ONLY. Basically it is designed for users to help remind programmers/
developers what they like or do not like in the software they use.
Actually it does not have to be software specific it can be on
anything computing related. The goal is to have a different person
write a column for each issue.

//// Library and Periodicals

The PERIODICALS section is designed for anyone who wants to write a
book, magazine or other programming related periodical review. The
LIBRARY is designed for anyone who wants to write a review/report of
any new programming tool or programming language library. This can
include CLIs, programming editors, c/basic/fortran/pascal libraries,
new compilers, new languages, new updated development tools, etc, etc.

//// New Products

Also there is some interesting new products for Atari Programmers. On
the documentation side, there is the new Atari Compendium by SDS. This
book is the new Programmers' Reference Guide for Atari computers. It
will also be included with Atari's own developer documentation as
well. It was reviewed by several at Atari so it should be highly
accurate. It covers GEM GUI guidelines, Cookie Jar, GEM/TOS (AES, VDI,
XBIOS, GEMDOS, BIOS... and what TOS version supports them), Memory
Map (system boot variables; 680x0 exception vectors; auto-vector
interrupts; trap, 68881, 68851 exception vectors; MFP, SCC, System
vectors; System variables; Processor Save area; System Ram; MMU;
Video; DMA, ASCI, SCSI, floppy; PSG; DMA sound; BLiTTER; Keyboard;
Midi; etc.), Speedo Fonts, XCONTROL, FALCON030 Digital Signal
Processor (DSP)/DMA, Mint/Multi-TOS, error codes, File Formats (GEM,
IMG, FNT, RSC), 680x0 cpu, 68881 floating point co-processor, Drag &
Drop protocol and more. See the review in this issue for more details.

SDS Publishing
996 Redondo Ave #404
Long Beach, CA 90804
USA

GE: S.SANDERS2
IN: S.SANDERS2@genie.geis.com

Atari Compendium
ISBN: 0-9638331-0-3

On the software side is Gribnif's Geneva software. This is a
multi-tasking program manager with no limits on desk accessories
(which can be loaded or removed dynamically). It allows up to 256
windows open at the same time compared to seven. This multi-tasking is
similar to Apple's multi-finder or Microsoft's Windows software. All
tasks get equal amount of time, etc. The amount of memory to run
Geneva is not that large and works on all Atari machines. Programmers
will enjoy the last 50 pages of the manual which is dedicated to
programming Geneva. In addition upgrades are planned to make it work
with Multi-TOS/MiNT and other multi-tasking kernels.

Gribnif Software
PO BOX 779
Northampton, MA 01061
USA
(413) 247-5620 (voice)
(413) 247-5622 (fax)

GE: GRIBNIF
CIS: 75300,1131
In: 75300,1131@compuserve.com

GENEVA v1.x


/**********************************************************************/
       A message from the IAAD
/**********************************************************************/

=-=-=-=-=-=-=-=-=-=-=-=-=
Developers, Please Note!
=-=-=-=-=-=-=-=-=-=-=-=-=

The Independent Association of Atari Developers (IAAD) provides peer
support to commercial Atari developers. The IAAD can help you find a
shrinkwrap machine, weigh the benefits of different kinds of
packaging, reach potential customers, tackle programming dilemmas,
locate distributors for your products - in short, our members offer
each other information on virtually every aspect of commercial
software development and marketing. Membership is open to registered
Atari developers who have a commercial product currently shipping or
about to launch. To apply, please send a note to PERMIT$ on GEnie.


/**********************************************************************/
       68K Column - Some Assembly Required
          By: Damien M. Jones
/**********************************************************************/

An Introduction to 68000 Assembly Language Programming on the ST/TT/Falcon

-- Part 1: But I don't WANT to learn assembly! --

Sure you do. 68000 programming isn't like assembly programming for a
lot of other chips. You may have heard horror stories about
programming in assembly for PCs (or you may have some of your own); I
can tell you they're all true. But every Atarian knows how messed up
PCs are, right? (smile) Atari made an incredibly good move when they
chose the 68000 as the CPU for the ST; unlike the 80x86 series, which
by all indications was either designed by an idiot or someone who
wanted to make programmers' lives miserable. The 680x0 series was
designed intelligently from the start. I could go on for quite some
time about the differences between 80x86 and 680x0 processors, but I
won't.

The practical upshot of all this is that writing for a 680x0 processor
is SO much simpler than most other assembly languages, it can be
learned very quickly. No horror stories. Just smooth coding.

So who should learn assembly? Anyone who:

    *  Wants to write fast subroutines to replace slow ones.
    *  Wants to create very small programs (like AUTO programs).
    *  Wants to do efficient interrupt programming.

Of these, the most important is the first one - writing fast
subroutines. When I started writing Sound Lab (my digital sample
editor) all the sample processing routines were written in GFA BASIC,
as was the rest of the program. When it took a couple of minutes to
process 500K of data, I decided something had to be done. So I
rewrote some of the processing routines in assembly, to see how much
of a speed improvement I could get... and I was able to do that same
500K processing job in about two seconds.

It wasn't until much later that the other two reasons became more
important to me, but they are also valid reasons for using assembly
rather than a high-level language. I'll be getting into them later in
this series.

Still with me? Good. In this article I'll go over some material you'll
need to get started with assembly. First I recommend a good
assembler/debugger package; I personally use HiSoft's Devpac 3
(available here in the US from Oregon Research Associates). I will try
to avoid too much Devpac-specific material here, though.

I will assume throughout this series that you already know a
high-level language, preferably C or a structured BASIC. I will not be
explaining programming in general; I'll be covering assembly
programming specifically, and how it differs from high-level language
programming. Assembly is NOT a good first language, as it's too easy
to get into bad programming habits (like unstructured code).

Now, on with the introduction!

REGISTERS

Inside the 68000 are a number of "registers". These are nothing more
than memory locations inside the 68000; because they're inside the
CPU, they can be accessed MUCH faster than locations in RAM can.
Almost every assembly language instruction will refer to at least one
register, so knowing how to use registers is absolutely vital to
writing assembly programs.

There are sixteen general-purpose registers inside the 68000, divided
into two general categories, "address registers" and "data registers".
There are eight of each, numbered 0 through 7; registers are named by
specifying "a" or "d" and following it with a number, like this: "a0".
All of these registers are 32-bit, which means they can contain a
number from -2,147,483,648 to 2,147,483,647. More on this in a bit.

Address registers are used mainly for memory addresses, and there are
some special ways of using them that make them most useful when used
in that capacity. Data registers are used for just about everything
else, and include special data processing capabilities. Both kinds of
registers allow you to do simple math with them (adding and
subtracting) so for many things, the decision on whether to use a data
or address register is up to you. The large number of registers makes
it very convenient to do complicated data manipulations.

There are some other registers in the 68000. One of them is the
program counter (pc) which tells the CPU where the next instruction
is. Another is the stack pointer - although this is really a7. That
might be hard to get used to for a while--address register 7 is used
by the 68000 as the stack pointer. It's nice, though, because you can
do anything with the stack pointer that you can do with any of the
other address registers. Most assemblers will allow you to use either
"a7" or "sp" to refer to the stack pointer. There are more registers,
but they are not important right now.

As mentioned above, each register is 32 bits in size, but often you
will not want or need to use the entire 32-bit size. Fortunately, you
can access (and manipulate) the low 8 or 16 bits of data registers
without affecting the rest, and you can also do this with the low 16
bits of address registers as well.

Perhaps an example will make this clearer. Let's say you put
$12345678 (that's a hexadecimal number) into d0. The entire d0
register can be referred to as d0.l ("l" for Long), so d0.l would be
$12345678. d0.w ("w" for Word), which refers to the lower 16 bits of
d0, is just $5678. d0.b ("b" for Byte) is just the low 8 bits of d0,
so it is just $78. Remember, these are just referring to different
parts of the same register. Address registers work similarly, except
that you cannot use "b" for address registers.

Here's where it gets a bit confusing. The size extensions (.l, .w,
and .b) do not normally appear on the registers themselves. They
appear on the instructions. I'll explain, as it's time now to talk
about the instructions.

//// Instructions

Most instructions are a three- or four-letter "mnemonic". That just
means they're a short bunch of letters that replace a more complete
word. For example, "sub" is the instruction for "subtract".

In an assembly language program, each instruction is listed on a
separate line. At the very beginning of a line there might be a
"label"; this is just a name for where that line's instruction is in
memory. Usually the label is followed by some space, and then the
instruction mnemonic; some more space, and the "source" data for the
instruction, a comma, and the "destination". (Some instructions do not
need a source or a destination.) More space follows this, and then an
optional comment provided by the programmer explains what the
instruction does. Here's an example:

loop     move.l d0,d1        ; Copy d0 into d1.

"loop" is the label for this instruction - you'd use this sort of name
to indicate the beginning of some sort of loop. Labels are NOT
required on every instruction, and you shouldn't put them there unless
you need them. Some assemblers require you to put a colon (:) after a
label, but many do not.

"move.l" is the instruction. "move" is the mnemonic, which in this
case means just that - move. It moves data around without changing it,
and is probably the most often-used instruction. The ".l" size
extension just specifies how much data is to be moved - in this case,
"long" data, or 32 bits, the full size of the registers. For several
instructions, the size is implied by the instruction itself, so it is
often left out. Where a choice of sizes is offered, I will always
explicitly show the size, rather than let the assembler provide the
default; this makes for clearer code!

"d0" is the source of the data. Since the size of the move is .l, the
entire contents of d0 (d0.l) will be used.

Similarly, "d1" is the destination, and because .l was specified, the
entire contents of d1 (d1.l) will be overwritten with new data.

The comment, "; Copy d0 into d1.", doesn't seem too helpful. But this
statement was taken out of context, so it's hard to decipher meaning
from it. Each assembly instruction does just one thing, so it's hard
to determine what one instruction, by itself, might be doing. This is
why comments are so important - they help the programmer piece together
the whole from the parts.

There aren't really that many instructions for the 68000; what makes
it powerful is that most of those instructions can be used with most
of the registers, instead of being limited in arcane and often
arbitrary ways. I'll go over most of the important instructions next
time, along with addressing modes.

SUMMARY

This time, I covered the following basic concepts:

    *  Why assembly is useful.
    *  What registers are.
    *  What instructions look like.

Next time I'll cover more material, and actually do a "Hello World!"
program in assembly.


/***********************************************************************/
                    C Programming Column
                      By: Albert Dayes
/***********************************************************************/

In the programming language C, one has a basic building block called a
function. With a large group of different functions, one can build
programs much faster than having to write the program from scratch
each and every time.

What is a function? One way to think of a function is like a dam
holding back a river which then forms a lake. The function can have
outputs which is similar to releasing water from the behind the dam.
It can also have inputs which could be one or more rivers coming into
the lake.

A function can have inputs only, outputs only or inputs and outputs.
Below is a simple comparison chart.


================================================================
      Nature                  |       C   Programming
================================================================
A lake of water behind a dam  |           Function
River(s) going into the lake  |     input(s) into the function
Water released from the dam   |     output(s) from the function
================================================================

Within the functions themselves are additional building blocks called
variables. A variable can be thought of as a cup or glass. Each
variable is of a specific type such as int, float, char, etc. This can
be thought as a special cup or glass. For example a wine glass, a tea
cup, and a coffee mug.

================================================================
    Drink Containers          |      Variable Type
================================================================
  wine glass                  |    float (floating point)
  tea cup                     |    int   (integer)
  coffee mug                  |    char  (character)
================================================================

Here is a short example...

#include <stdio.h>

/* AEO-PJ - C program #2 */  <--- a comment statement which is ignored
                                  by the C compiler.

main()
  {
   int tea_cups;      <---- declaring a variable : note it's a
                            meaningful variable name

   tea_cups = 23;     <---- assigning a value to the variable

   printf( "%d", cups );  <--- displaying the contents of the variable
                               to the screen. To do this we call the
                               function printf. The function printf
                               displays formatted output to the
                               screen. In this case it displays a
                               single integer.

  } /* main() */

After one has written the preceding in a text editor the compiler is
run. What does the compiler do? It parses the source file (the code -
which is the ASCII file we just saved) and converts it to tokens.
Finally it is converted to object code. Then the linker resolves all
unresolved references, links in the correct libraries and then the
executable program is created.

If this does not make sense, we will think of this in a different
manner. Suppose that someone writes you a check and then you take the
check to the bank to cash or deposit it. You can think of your check
as the ASCII source file.

The first thing the bank teller does is make sure all of the
information on the check is valid.  Does the printed amount of the
check equal the amount written on the check?

    +-------------------------------------------------+
    |                                                 |
    |                                   $95.00        |
    |                                                 |
    |     Pay to: AEO-Programmers' Journal            |
    |                                                 |
    |     Ninety five dollars and xx/100 cents        |
    |                                                 |
    |                       virtual C++ signature     |
    +-------------------------------------------------+

Yes it does in this case. The bank teller checks for a valid signature
on the front and then turns the check over. Oops, you forget to endorse
the back of the check. This error is similar to the syntax error that
a C compiler gives you when a mistake is found.

In the source code above the syntax error would be...

   printf( "%d", cups );   <--- variable cups is not declared/defined

This is true since the variable cups should really be the variable
tea_cups.

   printf( "%d", tea_cups );

So after editing the file, fixing the error, and saving the file its
time to recompile the program. This would also be similar to what
happens in the bank after you endorse the check and hand it back to
the bank teller.

Now it is time to resolve unresolved references. Since you want your
check to be cashed the teller checks to make sure that there is money
in the account. This is just like the linker which searches the
libraries looking for references that are not defined in your program.
After the bank teller discovers that there is enough money in the
account he/she gives you the cash.  When the linker is done the
executable program will be given to you to run. This is also known as
the development cycle (which is as follows EDIT->COMPILE->LINK->RUN )
which repeats itself over and over again.

So the final program as it stands...

#include <stdio.h>

main()
  {
   int tea_cups;

   tea_cups = 23;

   printf( "%d", tea_cups );

  } /* main() */

Now to solve other problems between ANSI C and K&R C. We need to
define a constant that inform the C compiler to use or not use
function prototypes. And how do we do this?

We just define it of course

#define AEOPJ_ANSI 1

What we just did was the define the constant AEOPJ_ANSI and set its
value equal to one.

Anything that begins with # is handled very carefully by the C
compiler. For example...

#include <stdio.h>

This tells the compiler to include (read the contents of) the file
stdio.h into the program. The file stdio means standard input/output
in which are defined functions and constants dealing with standard
input/output. The #define AEOPJ_ANSI 0 is going to be used as an
on/off switch to the C compiler. If the switch is a 1 (ON), ANSI
function prototypes will be used. When the switch is a 0 (OFF), K&R
style functions will be used.

This will allow conditional compiling of our program. Basically it
will only compile areas of the source code that are in the "ON" state.
There are also #if and #else and #endif which make creating control
blocks very simple.

#include <stdio.h>

#define AEOPJ_ANSI 0

#if AEOPJ_ANSI > 0
  main(void)
#else
  main()
#endif
  {
   int tea_cups;

   tea_cups = 23;

   printf( "%d", tea_cups );

#if AEOPJ_ANSI > 0
   return(0);
#endif

  } /* main() */

This way one can use one source file for both K&R and ANSI C
compilers. With this switch at the top of the file one can control
many things within the file very easily. This can be used for error
control, using different commands dependent on TOS versions, etc.

For the C compiler it examines each expression as and if it's TRUE than
that block becomes an "ON" block and is compiled. If the expression is
FALSE then the C compiler ignores that block of code.

#if AEOPJ_ANSI > 0

< do all these commands/instructions >

#else

< do these alternate commands/instructions >

#endif

For all of the K&R C compilers...

Mark Williams C
Heat & Serve C
SOBOZON C
Megamax C
Laser C
Hippo C
Aztec C

#define AEOPJ_ANSI 0

For all of the ANSI C compilers...

GNU C
Prospero C
Pure C
Turbo C
Lattice C

#define AEOPJ_ANSI 1

If one does move source code between different computer platforms one
will often find similar type of conditionals in the source code. Such
as the following...

#ifdef UNIX
#endif

#ifdef ATARI
#endif

#ifdef MSDOS
#endif

#ifdef CRAY
#endif

The #ifdef is similar to the #if except that the condition is true
only if the constant has been defined. So if one created the following
definition at the top of the C source file...

#define ATARI 1

The C compiler would review each expression below with the following
results....

#ifdef UNIX    <--- false since UNIX has not been defined
#endif

#ifdef ATARI   <--- true since Atari is defined as 1

 < do all these Atari specific commands >

#endif

#ifdef MSDOS   <--- false since MSDOS has not been defined
#endif

#ifdef CRAY    <--- false since CRAY has not been defined
#endif

This is all for now but next time we will do more with conditional
statements in your program (not just for the C compiler), creating
your own functions and more on variables.

/***********************************************************************/
                Advanced Computing
                 By: Carl Barron
/************************************************************************/

As promised I am presenting an edited Compuserve (CIS) capture of
files to download to a Flash (1.x or II.x) do file generator. The
generator will download all the selected files with no human
intervention (most of the time). This will speed up your CIS 9600 baud
downloads via Flash.

The source code includes the standard headers we will use, declares
some constants, including the ASCII equivalent of your prompt code for
CIS. I then declare some regular expressions by name to make the code
more readable.

We are looking for specific lines:

A)  The name of the forum in lower case, followed by a space, tab or
    newline.
B)  [number,number] spaces/tabs Lib: number junk. This line will
    tell us at the third number in which the file is located.
C)  Starting with a sequence of anything but newlines or slashes,
    followed by a slash. This is the filename as stored on CIS and is
    normally in upper case.

Upon finding one of the above line types (other lines are ignored, as
are errors, by this code), we return what type of line we found and
what we found in one of the pointer arguments. Note that YY_DECL is
undefined and then defined to be the function heading that we desire.
This is a "goodie" of flex, that I believe is not in the parent
program lex.

Our main function opens the FILE *'s yyin, yyout. If either of these
fails we quit with a message, since we do not want to use either of
the defaults stdin or stdout.

We then go into a loop until yylex returns 0 indicating end of file.
In this loop is the switch which is the heart of our do file
generator. This switch determines what to do given the return value of
our yylex function. There are three cases to consider.

If it is a forum line we check to see if it is different from the last
line used. If it is different we issue commands to CIS to go to that
forum, and reset the old lib to -1 so that the next LIB line will
create a set of CIS commands to go to the library.

If is a LIB line, to a different library, we create the commands to
goto the new library.

Finally if it is a FNAME line we issue the commands to download the
file from the library.

Note again that is not as complicated as it sounds, all the gory
details of text analysis are hidden in the flex generated code. After
I introduce YACC (Berkeley PD yacc in particular), I will revisit this
problem to solve it again. It will use a simpler flex file and a yacc
file to do the same thing, a good way to get to see what this really
is doing as the yacc version is programmed in a more intuitive manner.

/*   code for cisdls.l example */

%{
#include <stdlib.h>
#include <string.h>
#undef YY_DECL
#define YY_DECL     int yylex(int *lib,char **text)
#define FORUM  1
#define LIB         2
#define FNAME  3
#define PROMPT '\007'         /* MY prompt char. change
accordingly.*/
%}
forum          [a-z]+
num            [0-9]+
lib            [ \t]+"Lib:"[ \t]*
fname          [^\n\\]+
%x   skip get_number
%%
^{forum}/[ \t\n]              {*text=strdup(yytext);BEGIN(skip);
                              return FORUM;}
^{fname}/\/                   {*text=strdup(yytext);BEGIN(skip);
                              return FNAME;}
^\[{num},{num}\]{lib}/[0-9]   BEGIN(get_number);
\n                            /**/
.                             BEGIN(skip);
<get_number>{num}             {*lib=atoi(yytext);BEGIN(skip);
                              return LIB;}
<skip>.*\n                    BEGIN(INITIAL);
%%
static char *forum,*fname;
static int lib;

void main(int ac,char *av[])
{
     char *text;
     int  new_lib,c;

     if((yyin=fopen(av[1],"r"))==NULL)
     {
          fprintf(stderr,"Can't open %s\n",av[1]);
          exit(1);
     }
     if((yyout=fopen(av[2],"w"))==NULL)
     {
          fprintf(stderr,"Can't create %s\n",av[2]);
          exit(1);
     }
     forum = strdup("?");          /* strdup copies string to */
                                   /*   malloced memory */
     fname = strdup("?");
     lib = -1;

     while(c=yylex(&new_lib,&text))
          switch(c)
          {
          case FORUM:
               if(strcmp(forum,text)!=0)
               {
                    free(forum);
                    forum = text;
                    lib = -1;
                    fprintf(yyout,
                         "g %s|\n>WA \"%c\"|\n",text,PROMPT);
               }
               else
                    free(text);
               break;
          case LIB:
               if(lib!=new_lib)
               {
                    lib = new_lib;
                    fprintf(yyout,
                    "LIB %d|\n>WA \"%c\"|\n",new_lib,PROMPT);
               }
               break;
          case FNAME:
               if(strcmp(fname,text)!=0)
               {
                    free(fname);fname=text;
                    fprintf(yyout,
                    "DOW %s|\n>WA \"omputer:\"|\n%s|\n"
                    ">WA \"%c\"|\n",text,text,PROMPT);
               }
               else
                    free(text);
          }
     exit(0);
}

I linked the resulting lexyy.o file with this linker file for LC5:

from c.o lexyy.o
lib lc.lib
to cisdls.ttp

A second example is a lot shorter and is a gem based text unformatter.
One that will not weld words together like 'thisis' unless they are so
welded in the original text. This unformatter will take formatted
ASCII text and remove all endlines except at the end of a paragraph.
This process makes the importation of text into desktop publishers and
word processors easy to handle than the normal ASCII formatted text.

All we are doing is looking for a sequence of newlines ignoring the
spaces and tabs in between them. If we find such a sequence of only
one newline, we replace it with a blank, otherwise we replace it with
a pair of newlines. This process removes all blank lines but one
between paragraphs. The code is fairly simple but includes two
functions I use with a lot of the gem code I write, namely a formatted
alert function, and a get complete path name from a file selector.
This code does contain a couple of lattice specific functions, but
these should be fairly easy to rewrite if you do not have Lattice C,
just knowing what they do. It uses standard C function vsprintf()
which if you have non-ANSI C compiler you may not have.
Fsel_exinput() is used but with Lattice this will work with all
versions of TOS. Some other compiler systems may require TOS 1.4 or
newer to prevent the computer from crashing!

Here is my 'better' unformatter code :

/* begin of gemunf.l */

%{
#include <aes.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define output(x)   (fputc(x,yyout))
%}
%%
[ \t]*\n([ \t]*\n)+[ \t]*     output('\n');output('\n');
[ \t]*\n[ \t]*.               output(' ');
.                             ECHO;
%%
#include <stdarg.h>

void quit(void)     /* easier quitting of gem prgs via exit */
{
     appl_exit();
}

char *get_file(char *prompt);
int  alertf(int,char *,...);

void main(void)
{
     char *fname;

     appl_init();
     atexit(quit);  /* call appl_exit() just before any exit() call */

     if(fname=get_file("formatted file"))
     {
          if((yyin=fopen(fname,"r"))==NULL)
          {
               alertf(1,"[3][Can't open |%s][ ok ]",fname);
               exit(EXIT_FAILURE);
          }
          if(fname=get_file("Unformatted file"))
          {
               if((yyout=fopen(fname,"w"))==NULL)
               {
                    alertf(1, "[3][Can't create |%s][ ok ]",fname);
                    exit(EXIT_FAILURE);
               }
               yylex();
          }
     }
     exit(EXIT_SUCCESS);
}

/* formatted alert box ansi style */

int alertf(int n, char *fmt,...)
{
     va_list   args;
     char buf[BUFSIZ];

     va_start(args,fmt);
     vsprintf(buf,fmt,args);
     va_end(args);
     return form_alert(1,buf);
}

/*  get full path via fileselector */

char *get_file(char *prompt)
{
     static char path[BUFSIZ] = "", result[BUFSIZ], name[14];
     short button;
     char *p;

     if(path[0]=='\0')
     {
          getcwd(result,BUFSIZ);        /* get current dir. */
          strmfp(path,result,"*.*");    /* combine path, fname to complete*/
          memset(result,0,BUFSIZ);      /* clear result */
          *name='\0';
     }

     /* OK with LC5 else req. tos>=1.4 */

     fsel_exinput(path,name,&button,prompt);
     if(button!=1 || *name=='\0')   /*  if cancel or no filename selected*/
          return NULL;

     strcpy(result,path);       /* copy path to result; */
     p=strrchr(result,'\\');    /* fsel always has at least one \ in path. */
     strcpy(p+1,name);          /* append filenname to path */
     return    result;
}
/* end of gemunf.l */

I linked with the following LC5 linker file:

from c.o lexyy.o
lib lcg.lib lc.lib
to gemunf.prg

If you have ANY questions, problems or suggestions, do not forget
to contact me.  I think we can handle just about any C or tool
related question.


/***********************************************************************/
          HARD CORE - Interview with Charles Smeton
          By: Albert Dayes
/***********************************************************************/


AD: What is your current product for the Atari line of computers?

CS: Our current product is STraight FAX! 2 for the Atari ST/STe/Mega
    ST/Mega STe/ TT030/Falcon030 computers. STraight FAX! 2 has a
    suggested list price of $109.95 (US). Owners of STraight FAX!
    1.xx can upgrade to STraight FAX! 2 for $25.00 (US) or $20.00 (US)
    if STraight FAX! 1.xx was purchased since June 1, 1993.

    STraight FAX! 2 is a complete send/receive FAX application that
    will operate with standard Class 1, Class 2 or SendFAX Modems.

    We also have available a driver for the Navarone/Canon IX-12
    series sheet feed and flat bed scanners that will allow full page
    scanning from inside of STraight FAX! with these cartridge
    interfaced scanners for $19.95 (US).


AD: When did you decide to write FAX software for that Atari?

CS: In early 1990, I purchased a generic model of the Zoom SendFAX
    Modem for my PC Clone. This FAX Modem is a plain 2400 baud data
    modem with 4800 baud SendFAX capabilities. This particular modem
    was an internal PC card model. Upon looking at the FAX Modem and
    software, I thought that it would be possible to write a program
    to send FAXes if an external version of this modem was ever
    released. A few months later, Zoom released external versions of
    this Send FAX Modem. I purchased one.

    Before I began a full scale development effort, I did what is
    known as a "Rapid Prototype" design effort. I needed to prove that
    I could take a monochrome graphic image and convert it to the
    CCITT Group 3 format. This required doing some research to obtain
    the necessary standards that document the data format. Once this
    step was proven, the next step was to prove that the FAX Modem
    could be commanded to send the FAX image. Again this required
    contacting companies to obtain the necessary documentation. Once
    these two steps had been completed, the next step was to layout
    the requirements for the program along with its user interface.


AD:  How long was the design phase before you actually started
     writing the code?

CS: The design phase, including rapid prototype was about 2 months
    for the original Send FAX software that was released in October of
    1990.  Many areas of the rapid prototype were reused in the final
    design and implementation (coding).

    In April of 1992, STraight FAX! 1.00 was released. STraight FAX!
    added support for Class 2 FAX Modems to both send and receive FAX
    documents. Many other enhancements were also added to STraight
    FAX!, such as scheduling FAX events to occur up to a year in
    advance and enhanced viewing capabilities.

    Just as with the Send FAX software, a "Rapid Prototype" phase was
    necessary to prove that the Class 2 send and receive functions
    were possible on the ST architecture. However, most of the added
    features were an evolutionary growth of the original SendFAX
    software that were added over time based on new operating system
    features, hardware features, user suggested enhancements and
    analysis of the FAX software marketplace.

    Over the 11 months, STraight FAX! was enhanced to support a wider
    array of Class 2 FAX Modems, additional file support (GEM
    Metafiles), additional FAX Modem capabilities (Silent Answer and
    Caller ID), and additional printer drivers (Calligrapher, Speedo
    GDOS and That's Write 2).

    In the 6 months prior to its release, STraight FAX! 2 was
    developed.  Again the primary emphasis was on increased support
    for a wider array of FAX Modems (Class 1), file support (First
    Word Plus, Word Writer ST & PCX import, PCX & Encapsulated
    PostScript export and CardFile 4 import into the Phone List) and
    support for the latest operating system and hardware enhancements
    (3D user interface, MultiTOS, Speedo GDOS and the Falcon030).
    STraight FAX! 2 went through extensive beta testing with beta
    testers in North America and Europe. Many enhancements were
    suggested by beta testers and users.


AD: Any particular problems in the design phase that were a significant
    obstacle in your work that had to be overcome?

CS: Most of the problems that we discovered were related to the fact
    that not all Class 2 FAX Modems were 100% identical in operation.
    While Class 1 is an EIA approved specification, Class 2 was not.
    The Class 2 FAX Modems in used today are based on the initial
    Class 2 specification that was not approved (due to politics from
    members of the committees that regulate the FAX Modem standards).
    This did not stop several companies, such as Rockwell, Sierra,
    Exar and ZyXEL from releasing FAX Modem chipsets and firmware.

    This required obtaining various FAX Modems to test and verify the
    software with. To maintain maximum compatibility, the software
    polls the FAX Modem for its manufacturer's identification and
    adjusts as necessary. Other variances between FAX Modems can be
    tested for with proper AT commands and can also be accounted for.

    Other problems that had to be overcome were the need for tools to
    verify the operation of the FAX Modem and FAX software. Normally,
    an RS-232 monitor device would be used. However, these devices are
    not inexpensive. The next best thing was to write our own
    monitoring software that used a Mega STe or TT030 (with multiple
    serial ports) to monitor in real-time the data that was sent to or
    received from the FAX Modem and save this data to a log file for a
    post mortem analysis.  This device has proven to be a very useful
    tool in being able to diagnose differences between FAX Modems.

    On a smaller level, there were many operating system and hardware
    related problems to overcome, such as the need for patches to
    correct Hardware Flow control problems in various TOS versions.
    Working with Atari Developer support (primarily Mike Fulton),
    these problems were solved.


AD: What programming language is STraight FAX written in?

CS: STraight FAX! is written in C with some 680x0 assembly language.
    Megamax Laser C was used, as it had the best source level
    debugger at the time. While Laser C has not been updated in a
    while, the debugger will still operate on the Falcon030 with its
    68030 CPU as long as the ST compatible graphic modes are used.
    Laser C's editor/shell is also not compatible with TOS 2.00 and
    above, so we use the gulam (UNIX-like) shell with many special
    script files to streamline operations.

    Most of the printer drivers and CPU intensive functions in
    STraight FAX! (image scaling, cleanup, rotate, flip, fax
    compression/decompression) are written in assembly language for
    optimum performance.

    Many of the tools from the Atari developer's package were utilized
    such as the ALN linker and RCS Resource Construction Set.


AD: How long was total development cycle before the first commercial
    release of your product?

CS: It took approximately 5 months from the initial concept to the
    release of the first SendFAX software in October of 1990. However,
    the size of the original program pales in comparison to the
    program today (the original SendFAX software was about 100K for
    the main program, STraight FAX! 1.00 was about 150K, STraight FAX!
    1.07 was about 200K, STraight FAX! 2.00 is about 276K (this does
    not even take into consideration the additional utilities and
    printer drivers).


AD: Can you so give some general ideas how your program works from
    a software point of view? Trade secrets are not required. (smile)
    This can also include general information on how a FAX, FAX modem,
    and FAX software work too. Hardware and Software overview would
    also be helpful.

CS: In the Send Mode, STraight FAX! allows the user to select one or
    more files of various types that they wish to FAX. These files can
    be bitmapped graphics such as Image, Degas, PCX or FAX files
    genetrated from an application program with the special FAX
    printer drivers, object oriented GEM Metafile graphics, ASCII Text
    files, or Word Processing files such as First Word, First Word
    Plus or Word Writer ST. In addition, the user can choose to attach
    a Cover Page to the start of the transfer, the user can enter the
    necessary Cover Page information and specify a logo graphic to be
    placed at the top of the Cover Page.

    The user can then select from up to 100 destination FAX Numbers in
    the Phone List or enter a single FAX Number to send the FAX to.
    The FAX transfer can be sent immediately or it can be scheduled to
    occur at a later date and time of up to a year in advance.

    After the transfer has taken place, the Send Log will contain
    information about the transfer, including the status of the
    transfer.

    Prior to dialing the destination FAX all files are converted to
    FAX format as necessary. This requires decompressing bitmapped
    graphics into a raw bitmapped format and compressing them into FAX
    format, rendering GEM Metafiles into a FAX resolution bitmap and
    compressing it into FAX format, and rendering ASCII Text, Word
    Processing documents and the Cover Page using special internal FAX
    resolution fonts into a raw bitmap and compressing them into FAX
    format.

    In the Receive Mode, things are a bit simpler. The user activates
    the FAX Auto Receive Mode and waits for a FAX to arrive. The
    Receive Log will detail information about the received FAX. From
    the log, the user can choose to View, Print (Via GDOS), Rename,
    Export or Delete the received FAX.

    From the hardware point of view, the three different types of FAX
    Modems (Class 1, Class 2 and SendFAX) present different AT command
    interfaces to the FAX software. FAX operation is controlled with
    special commands which are an extension to the basic Hayes
    compatible AT command set. In addition to the special FAX commands
    for each type of FAX Modem, standard AT commands such as those
    that set S Registers (ATSnn=xxx), configure the modem speaker,
    result code format, dialing, etc. are used.

    Class 2 and SendFAX are similar in that the
    microprocessor/firmware in the FAX Modem handles all of the low
    level Group 3 FAX Protocol.  This has the benefit of isolating the
    FAX software from the low level Group 3 FAX Proctcol, which
    lightens the processing requirements on the FAX software. The
    disadvantage, is that if a problem exists during a FAX connection
    that is not resolved by the firmware in the FAX Modem, there is
    little that the FAX software can do to recover from the problem.
    Many early firmware releases of Class 2 FAX Modems had problems
    connecting with specific models of FAX Machines. These problems
    were eventually corrected with newer firmware releases by the FAX
    Modem vendors. For this reason, we strongly encourage users to
    obtain the latest firmware releases for their FAX Modems.

    The initial Class 2 specification that the current Class 2 FAX
    Modems is based on defines 100's of commands, but not all FAX
    Modem vendors and chipset/firmware manufacturers support every
    defined command in Class 2. This creates the additional problem of
    having to send commands to the FAX Modem to ask it if it supports
    a specific Class 2 capability. If the capability is not
    implemented, then there is no way to provide it in Class 2.

    Class 1 defines a very simple set of AT commands, but requires
    the FAX software to implement the low level Group 3 FAX Protocol.
    This has the benefit in lowering the cost of the FAX Modem, as it
    does not require a microprocessor that is as powerful as Class 2
    requires.  However, most Class 1 FAX Modems are either from
    companies that do not support Class 2 (since it was not an
    official standard) and are also high speed data Modems (V.32 or
    V.32bis) or support both Class 1 and Class 2.

    Since the FAX Software is required to implement the low level
    Group 3 FAX Protocol, the Class 1 FAX software is much more
    complex than Class 2. The processing and timing requirements for
    Class 1 are also alot higher. For this reason, Class 1 is not
    recommended in a multitasking operating system unless the CPU is
    sufficiently fast or the main CPU has an intelligent I/O
    controller to handle RS-232 communications.  However, since the
    control of the FAX Protocol is in the FAX software, problems can
    be resolved with updates to the FAX software. In addition, as new
    Group 3 FAX capabilities are defined by the CCITT, they can be
    added to the FAX software.


AD: Any plans for a C API so one could hook into the Fax Server and
    send a FAX directly from their own programs?

CS: Not at this time.

    Our FAX Manager CPX and TSR allow a user to specify where
    generated FAX files should be located. Using one of the special
    printer drivers that are included for Pagestream (1.8x & 2.x),
    Calamus (1.09x & S/SL), That's Write 2/3, Original GDOS, FSM/Font
    GDOS or Speedo GDOS applications, it is possible to FAX directly
    from an application with MultiTOS or Geneva.

    One of our goals at this time is to work with developers of other
    telecommunication software applications (terminal programs and
    BBSes) to develop ways for both programs to be running at one time
    on a multi-tasking operating system (such as MultiTOS or Gribnif's
    Geneva) to allow sharing of the FAX Modem for FAX and Data.


AD: Any other enhancements you plan in the future for your product?

CS: Full background transfer support is something we are working on.
    This is not an easy task to accomplish, as an 8MHz 68000 is just
    not fast enough to do this in real-time and MultiTOS's pre-emptive
    multitasking is not sufficient for real-time applications
    (MultiTOS will stop multitasking whenever the CPU is placed into
    Supervisor mode, this can happen at just about any time and if it
    does for more than 1 second, the FAX operation will be affected.
    Operations such as formatting a floppy and printing via GDOS are
    two that would cause this to occur).

    There are other difficulties, such as locking a serial port from
    use by other applications during a FAX transfer.

    One area we are researching at this time is Voice Mail. Several
    new and inexpensive Voice/FAX/Data Modems are appearing on the
    market now and allow such capabilities as Voice and FAX Mailboxes
    and FAX on Demand.

    We will also consider adding support to the STraight FAX! for
    newer FAX Classes as they are defined by the EIA and when FAX
    Modems are readily available that support these new standards.
    Class 2 was finally approved in late 1992, but in a much different
    form than the initial Class 2 specification. To avoid confusion,
    the official Class 2 is being called "Class 2.0". FAX Modems based
    on Class 2.0 should be appearing at some point in the near future.
    If someone is unsure as to exactly which Class(es) a FAX Modem
    supports, the command AT+FCLASS=? will return a list of the
    supported Classes, e.g.,

    0,1        = Class 0 (Data) and Class 1 (FAX)
    0,2        = Class 0 (Data) and Class 2 (FAX)
    0,1,2      = Class 0 (Data), Class 1 (FAX) and Class 2 (FAX)
    0,2.0      = Class 0 (Data) and Class 2.0 (FAX)
    ERROR      = Not a FAX Modem


AD: Thank You.


For more information:

   GEnie: C.S.SMETON
   CompuServe: 73047,2565
   Internet: c.s.smeton@genie.geis.com or 73047.2565@compuserve.com

 [ Editor's Note

   STraight FAX! is marketed for NewSTar Technology Management by Toad
   Computers and is distributed in North America by Eastern Front
   Distributing Company and Pacific Software Supply. For more
   information contact Toad Computers or your Atari Dealer.

   Toad Computers
   570F Ritchie Highway
   Severna Park, Maryland 21146
   USA

   410-544-6943 (Voice)
   410-544-1329 (FAX)
   410-544-6999 (BBS, 300-14400 baud, allow up to 60 seconds to
   connect)]


/***********************************************************************/
                     DABBLING IN PASCAL
                     By: Kris Gasteiger
/***********************************************************************/

I am currently using OSS/ICD Personal Pascal, Ver 2.02. on a 2.5Mb
520ST with TOS 1.4, one double sided floppy drive, a ToadStor130 hard
drive, SC1224 color monitor, 2400 baud modem, 24 pin printer, and a
few other peripherals. All code examples I present will run on MY
system, other TOS versions, may give problems, so be cautious.

I'm going to assume that you, have at least read the manual, and
installed Pascal, and that it knows the paths it needs to find its
associated files. If you are in a bind about this, I can address this
in a future article or privately by E-Mail on Compuserve.

Someone once said "Steal from the best.", this I believe to be the
secret of programming in Pascal, or any other language. There's no
need to "reinvent the wheel" each time you have an idea you want to
turn into code. I keep libraries of DOCUMENTED Pascal code so I can
cut and paste it into my programs. Key word, DOCUMENTED. If you're a
cut and paste programmer like me, you need to know what those snippets
of code do MONTHS from the time you hide them away on your disk. I use
the { } curly brackets everywhere in my code. Curly brackets denote a
comment in Pascal, and comments are just about the only way you'll
know what you were trying to do.

Aside from my libraries of Procedures, Functions, and assorted
Algorithms, I keep three "Program Skeletons" on my hard disk, one each
for .TOS (non GEM), .PRG (GEM), and .ACC (Desk accessory) programs.

This month, I'll present my TOS program skeleton, and an example.

Why use TOS? GEM is so much nicer to work in, it gives you windows,
dialogs, alerts, mouse stuff but TOS is just text.

I use TOS. when I need a quick and dirty program to solve a simple
problem OR, when I want to be able to run my program from the AUTO
folder. Quick and Dirty (Q&D) programs are the kind you might dash off
to solve simple math problems. Gas mileage calculations, checkbook
balancing, printer set up... AUTO folder programs CANNOT use GEM, as
GEM has not been initialized when they are run automatically by the
operating system at boot up.

My TOS program skeleton:

------------------------------------------------------------------------
Program ******* (Input, Output);

Const
{Declare constants.}

Var
{Declare Variables.}

Function
{Declare functions.}

Procedure
{Declare procedures.}

{Main}
Begin
{Use all of the above to do useful work.}
End.
-------------------------------------------------------------------------

Notice there is not much there! I use the TOS skeleton mainly to
remind me of the basic layout of a TOS program. There are not any $I
includes, as there is nothing else needed.

An example of a Q&D program:

I am a home wine maker, and I sometimes need to calculate the amount
of grape brandy to add to a wine in order to fortify it to a certain
percentage of alcohol to make Sherry, or other fortified wines.
There is a simple way to do this calculation on paper, using a
"Pearson square".

The method is as follows:

1) Draw a square on a piece of paper.
2) In the upper left corner, enter the alcohol content by volume of
   the brandy you intend to use (this is usually about 40 percent).
   Call this number "A".
3) In the lower left corner, enter the alcohol content by volume
   of the wine to be fortified.  Call this number "B".
4) in the center of the square, enter the alcohol content desired
   in the finished wine. Call this number "C".
5) In the upper right corner, write the difference, C-B. Call this
   number "D".
6) In the lower right corner, write the difference, A-C. Call this
   number "E".

   D represents the number of parts of brandy required.
   E represents the number of parts of wine to be fortified.

Simple right?  Well, I tend to forget the formula, and my math skills
are non-existent. So, I wrote a Q&D program to take the drudgery out
of this simple calculation...

Note: The above outlined method is an ALGORITHM. Computer programs
      are implementations of algorithms.

(The text between the dashed lines is a complete Pascal program
 which I have compiled and run on my system.)

------------------------------------------------------------------------
Program Sherry( Input, Output );

{ This program is intended to allow you to figure out the amount of
  fortifying spirits to be added to a given amount of wine, to achieve
  a given final proof.
  Written in OSS/ICD Personal Pascal. 1/14/92 By: Kris J. Gasteiger.
  Parts Copywrited by OSS/ICD. }

{ Because this program does not use procedures, all variables are global. }
{ Global variables are those accessible from anywhere in the program.     }

Var
   Pts_Sp_F, Pts_Wn_F, Fortifier_A, Wine_A, F_Wine_A, Parts_spirits,
   Parts_Wine: Short_Integer;

{ You should choose your variable names so they contain an explanation
  about what is going on, it takes more typing, but six months later, you'll
  still be able to figure out your program!.

  These variables are pretty well explained by the Writeln statements
  in the following code... }

Begin
   Writeln;

   Writeln( ' Enter the % of alcohol by volume in the fortifying spirits:' );
   Readln( Fortifier_A );

   Writeln( ' Enter the % of alcohol by volume in the wine:' );
   Readln( Wine_A );

   Writeln( ' Enter the % of alcohol by volume desired in the finished Wine:' );
   Readln( F_Wine_A );

{ Take the inputs, and act on them. }

   Parts_Spirits := F_Wine_A - Wine_A;
   Parts_Wine := Fortifier_A - F_Wine_A;
   Writeln;
   Writeln( ' You should use ',Parts_Spirits,' parts spirits to ',Parts_Wine,
            'parts wine.' );
   Writeln;

{ Find the actual parts of brandy needed to fortify the amount of wine you
  have. }

   Writeln( ' Enter the number of parts of wine to be blended:' );
   Readln( Pts_Wn_F );

{ Make the answer whole numbers through use of the ROUND function. }

   Pts_Sp_F := Round((Parts_Spirits * Pts_Wn_F) / Parts_Wine);
   Writeln;

{Display the numbers.}

   Writeln( ' You will need ',Pts_Sp_F,' parts spirits to make a sherry of
            ',F_Wine_A, '%.' );
   Writeln;
   Writeln( ' Press <CR> to exit...' );
   Readln;

End.

----------------------------------------------------------------------------

Okay, all that was pretty simplistic (I hope), now, do I go on to show
how functions and procedures work, so you can get a handle on Pascal
as a second language? Or should I grind on into the intricacies of GEM
programming? GEM is a lot of fun, but you do need a handle on Pascal
first... so send me FEEDBACK PLEASE!


/**********************************************************************/
                           Practical DSP
                           By: BrainStorm
/**********************************************************************/

                  Falcon030: Programming the 56001


         Reprinted from "Passerelle n02" published by Atari France.

                Translation and Adaptation: Albert Dayes

One of the most outstanding features of the Falcon030 is its DSP 56001
installed as standard. Well used, this processor offers some
impressive speed gains in various tasks like compression/
decompression, 3D calculations, video or audio effects. Taking full
advantage of the 68030/56001 on the Falcon030 is often faster than a
486DX2/66. However two rules have to be followed:

1) Attempt to use both processors in parallel, dividing parts of the
   task between the 68030 and the 56001.
2) Write "true" DSP code in the 56001's native tongue.

It is stupid to take a 68030 routine and convert it line by line into
56001 assembly because in this case you will not take advantage of the
highly parallel architecture of the DSP. We will not explain DSP
programming theory. For that just purchase the "DSP 56001 User's
Guide" from Motorola. What we want to show with practical examples,
are some subtleties of the Motorola DSP 56001. And to illustrate the
correct method to utilitize/program the DSP to its greatest potential.

Example 1: Copy a memory block
==================

The following assembly source copies a block of 32 bytes into memory.

; source pointer
     move #INBuffer,r0

; destination pointer
     move #OUTBuffer,r1

; loop 32 times
     do   #$20,_EndLoop

; read a word
     move X:(r0)+,a

; write a word
     move a,X:(r1)+
_EndLoop


This program is fast but does not take advantage of the DSP. Now, we
will try to change the destination register R1 to R4, as well as the
type of RAM used (remember the DSP uses two RAMs: X and Y).

[ Editor's Note:

  A basic block diagram of the Motorola 56001 DSP ---|
                                                     |
  |------------|                                     |
  | [A][B][C]  |  <----------------------------------|
  |------------|

========================================================================

  |--------------------------|
  | program memory           |
  | program controller       |  <------ contents of [A]
  | Address Generation Unit  |
  |--------------------------|

  |--------------------------|
  | X memory                 |
  | Y memory                 |  <------ contents of [B]
  | MAC (Multiply/Accumulate)|
  |--------------------------|

  |--------------------------|
  |                          |
  | input/output             |  <------ contents of [C]
  |                          |
  |--------------------------|

======================================================================= ]

The previous routine can be rewritten like this:

; source
     move #INBuffer,r0

; destination
     move #OUTBuffer,r4

; read 1 word
     move X:(r0)+,a

; repeat 31 times
     rep  #$1f

; write a word and read next one
     move X:(r0)+,a a,Y:(r4)+

; write last word
     move      a,Y:(r4)+

With this little optimization the speed has been increased by a factor
of three! This optimization uses instructions in parallel that allows
one to read AND write at the same time!

NOTE:

To be executed in parallel, two memory moves have to be done in
different memories and use registers from two different banks. The
DSP56001 uses two banks of registers:

Bank number 1 includes: R0, R1, R2, R3
Bank number 2 includes: R4, R5, R6, R7

[ Editor's Note: These registers are located in Address Generation
                 Unit ]

For example: In one instruction, it is possible to read from RAM X and
write to RAM Y. But you cannot read from RAM Y and write into RAM Y.
In the same way, you can associate the same instruction registers R2
and R7, but not R1 and R3.

Example 2: Invert a memory bloc
==================

In this sample we will try to invert 32 DSP words, using the NEG
operation. The easiest way to do that is in the example below:

; ptr source
     move #INBuffer,r0

; ptr destination
     move #OUTBuffer,r1

; 32 loops
     do   #$20,_EndLoop

; read a word
     move X:(r0)+,a

; invert it
     neg  a

; write the inverted word
     move a,Y:(r1)+
_EndLoop

 
Here again, the algorithm choice is not the best one for the DSP.
Each loop includes 1 read from memory, 1 arithmetic operation, and 1
write of the data. ON THE DSP, ALL THIS CAN BE DONE IN ONE
INSTRUCTION!!  Here is how to achieve this goal:

; ptr source
     move #INBuffer,r0

; ptr destination
     move #OUTBuffer,r4

; read a word
     move X:(r0)+,a

; invert it, and read the next one.
     neg  a    X:(r0)+,b

; repeat 16 times
     do   #$10,_EndLoop

; invert current word(b), read next one(a),  write previous one
     neg  b    X:(r0)+,a a,Y:(r4)+

; invert current word (a), read next one (b), write previous one
     neg  a    X:(r0)+,b b,Y:(r4)+
_EndLoop


This new routine does the job in one instruction instead of three.
Because we are dealing with two words at the same time. While one is
inverted, the previous one is written down and the next one is read
from memory.

As you can see, even with simple operations, the DSP can provide an
incredible increase in speed.

For the next step we will try to avoid the "MOVE" instruction as a
memory move can (most of the time) be done in parallel with an
arithmetic instruction.


Example 3: Memory shift
=============

On the DSP, instructions ASL and ASR shift the specified register of
only one bit (68030 can shift multiple bits). However one can easily
avoid this problem. One has to remember what a shift [left] is... it
is just a multiplication by a power of 2.

The following routine will shift a register 4 times:

; ptr source
     move #INBuffer,r0

; ptr destination
     move #OUTBuffer,r1

; loop 32 times
     do   #$20,_EndLoop

; read 1 word
     move X:(r0)+,a

; shift 4 times to the right
     rep  #4
     asr  a

; write the shifted word
     move a,Y:(r1)+
_EndLoop

It takes 7 instructions, which is definitely quite a bit for a small
DSP job. We can do much better using multiply instructions as detailed
below.

; ptr source
     move #INBuffer,r0

; ptr destination
     move #OUTBuffer,r1

; multiplier
     move #$80000,y0

; loop 32 times
     do   #$20,_EndLoop

; read 1 word
     move X:(r0)+,x0

; right shift of 4 bits
     mpy  x0,y0,a

; write shifted word
     move a,Y:(r1)+
_EndLoop

This routine only uses 3 instructions. This is much better!  But one
can do exactly the same job in ONE instruction in the same manner as
example 2.

; source
     move #INBuffer,r0

; destination
     move #OUTBuffer,r4

; multiplier
     move #$80000,y0

; read 1 word
     move X:(r0)+,x0

; shift it and read the next one
     mpy  x0,y0,b   X:(r0)+,x0

; repeat 31 times the next instruction
     rep  #$1f

; shift the current word, read the next one, write the previous one
     mpy  x0,y0,b   X:(r0)+,x0     b,Y:(r4)+

; write last word
     move           b,Y:(r4)+

Isn't this easy?

The art of DSP programming is based on the clever choice of the
registers and the combination of memory accesses with arithmetic
operations. The DSP can replace the 68030 for many calculations with a
speed gain of over 10 times. And do not forget that on the Falcon, the
DSP clock is twice the clock of the 68030! That is 32Mhz for the 56001
DSP versus 16mhz for the 68030 cpu.

[ Editor's Note:

The above article is Copyright 1993 Atari France and BrainStorm.
Permission is denied for reproduction in any form other than this
issue of AEO-PJ.

References:

DSP 56000/DSP 56001 Digital Signal Processor User's Manual
Author/Publisher: Motorola

USA:

Motorola Literature Distribution
PO Box 20912
Phoenix, Arizona 85036

EUROPE:

Motorola Ltd.; European Literature Center;
88 Tanners Drive
Blakelands, Milton Keynes
MK14 5BP, England

Atari Compendium
ISBN: 0-9638331-0-3

DSP related sections:

XBIOS Overview   : 4.7 - 4.10
XBIOS Reference  : 4.33 - 4.54
Memory Map       : B.24 - B.26
XBIOS Opcodes    : A.10 - A.11  ]


/***********************************************************************/
                        THE LIBRARY
                      By: Albert Dayes
/***********************************************************************/

                    X-11R5 & GNU CD-ROM disc.

There are many CD-ROM discs that include the X-Windows 11 Release 5
and the complete GNU distribution. There are probably two to five
different sources who can provide CD-ROM distributions of the above
including Walnut Creek.

This overview is just to discuss the contents in general and not any
vendor specific version of the X11R5 & GNU CD-ROM. These CD-ROM
discs can be found for about 20 to 50 dollars on the current market.

The first part is X-Windows 11 Release 5. X-windows is the base
windowing environment used on many UNIX workstations. This is
produced by the MIT (Massachusetts Institute of Technology) X
Consortium. Some brief history follows...

    X Window System research began in the summer of 1984 at MIT as an
    informal joint undertaking between the Laboratory for Computer
    Science and Project Athena. Since that time, researchers and
    engineers at numerous other universities and companies have been
    involved in the design and implementation.

    The MIT X Consortium was formed in January of 1988 to further the
    development of the X Window System. It is part of the Laboratory
    for Computer Science at MIT, and has as its major goal the
    promotion of cooperation within the computer industry in the
    creation of standard software interfaces at all layers in the X
    Window System environment. MIT's role is to provide the
    vendor-neutral architectural and administrative leadership
    required to make this work. The Consortium is financially
    self-supporting, with membership open to any organization.

Included is the source code, fonts(bitmap and outline), proof of
concept code, documents, etc.

The GNU distribution contains approximately 120 programs include GNU
C/C++, Bash (Bourne shell work-a-like), Sed (stream editor), Grep,
Emacs, etc. Many of these have been ported to the Atari platform.
Gnu C/C++ is one of the most common and is the compiler currently used
in OBJECT::ATARI Column in this very magazine. Most of the source
code is set up for UNIX machines (ready to run makefiles, etc) but it
can be ported to other platforms including the Atari.

As someone once said it's useful to "steal from the best" when it
comes to source code. And this is definitely true of this CD-ROM.
One does not have to port the programs to the Atari to get the
benefits of this CD. Just browsing the source code will reveal
wonderful and unique treasures.

By looking in the Perl directory one can find routines to handle
regular expressions. Even if one is not taking the routine and using
it as is; it can give one some good ideas on writing one's own
routines. There is even a spell checker called ISPELL which includes
a several dictionary files.

The indent program allows one make their C/C++ source code to be
indented or formatted to his/her specifications. Its default setting
is for the standard that GNU uses in most if not all of its source
code. This has some interesting code for parsing a text file as well.

One can even find some ATARI directories on the CD. Some code
written by Dale Schumacher, John Stanley and Eric Smith are some of
the names I found in the source code.

There is also a file called Jargon... and here are some samples...

   FEATURE n. 1. A surprising property of a program.  Occasionally
   docu- mented.  To call a property a feature sometimes means the
   author of the program did not consider the particular case, and the
   program makes an unexpected, although not strictly speaking an
   incorrect response.  See BUG.   "That's not a bug, that's a
   feature!"  A bug can be changed to a feature by documenting it.  2.
   A well-known and beloved property; a facility.  Sometimes features
   are planned, but are called crocks by others.     An approximately
   correct spectrum:

   (These terms are all used to describe programs or portions thereof,
   except for the first two, which are included for completeness.)
   CRASH  STOPPAGE   BUG  SCREW  LOSS  MISFEATURE CROCK  KLUGE HACK
   WIN   FEATURE  PERFECTION (The last is never actually attained.)


Anyone who written or used software can relate to this very easily.

And another one....

   HACKER [originally, someone who makes furniture with an axe] n. 1.
   A person who enjoys learning the details of programming systems and
   how to stretch their capabilities, as opposed to most users who
   prefer to learn only the minimum necessary.    2. One who programs
   enthusiastically, or who enjoys programming rather than just
   theorizing about programming.  3. A person capable of appreciating
   hack value (q.v.).  4. A person who is good at programming quickly.
   Not everything a hacker produces is a hack.    5. An expert at a
   particular program, or one who frequently does work using it or on
   it; example: "A SAIL hacker".  (Definitions 1 to 5 are correlated,
   and people who fit them congregate.)  6. A malicious or inquisitive
   meddler who tries to discover information by poking around.   Hence
   "password hacker", "network hacker".

A word to the wise [for programmers and users] DO NOT keep any axes
near your computer!!! (smile)

In another directory is BSD (University of California, Berkeley
developed most of the software) there are some useful UNIX tools.
Like tail ( which lists N number of lines from the bottom of the
file), head (which lists N number of lines from the top of the file).
There some networking code, telnet, FTP protocol and many other tools
all in C source code form. BSD has been releasing quite a bit of the
source to the general public. The source released does not contain any
AT&T copyrighted source code by the way.

Most of the GNU software has a readme file so one can learn something
about the software before even looking at the source code. For the
amount of interesting software/source code one can find on CD-ROMs
these days is just incredible. The price that I paid for this CD was
only $20 at a CD-ROM tradeshow several months ago.

CD-ROM source code is not just limited to C or C++ either. There are
many other CDs with pascal, dBASE, Cobol, etc. And the prices are
quite low considering the large quantity of source available. Where
can one find such CD-ROMs?

Computer Shopper Magazine and programming magazines like Dr. Dobbs
Journal, Software Development, and C Users Journal generally have a
list of a several companies that have such CDs. So look around and one
will be surprised at what one can find on CD-ROM.


/**********************************************************************/
                    PERIODICALS
                  By: Damien M. Jones
/**********************************************************************/

          The Atari Compendium by SDS publishing


If you're like most Atari programmers, you probably have half a dozen
reference books you use while writing code. You might have a VDI
reference, an AES reference, a GEMDOS/BIOS/XBIOS reference, and a few
other books you look in for specific pieces of information. The Atari
Compendium, from SDS Publishing (Scott Sanders) will effectively
replace most of the Atari reference books you own.

This gargantuan tome covers almost every aspect of the Atari's
operating system - TOS. It totals over 860 pages. While that may not
seem like a lot (smile) it is really more like perhaps 2000 pages.
Some reference books fill up space with a lot of "fluff"; the
Compendium has no such fluff, just pure, distilled information. Let me
list the chapters included in this book:

    Introduction to Atari Programming
    GEMDOS
    BIOS
    XBIOS
    Hardware
    AES
    VDI
    Line-A
    The Desktop
    XCONTROL
    GEM User Interface Guidelines

Several appendices are also included, such as an outstanding memory
map, descriptions of native file formats, ASCII tables (and Speedo
character code tables as well), and a description of the new Drag &
Drop Protocol.

What this book DOESN'T do is teach you Atari programming. While each
chapter includes an "Overview" to explain some basic concepts, it will
not teach you how to write programs. It is a REFERENCE book - a single
place that will answer almost any question about the operating system
you might have. For the most part, examples are given in C or
assembly, whichever is more appropriate, but source code is presented
only where it is necessary to understand the topic in discussion. You
won't find explanations of how to write DSP code, either, but you WILL
find information on how to get that code into the DSP and use it once
it's written.

That said, now let me dig a little deeper into the structure of the
book. As I mentioned, each chapter contains an overview section.  This
starts out with very simple material, and then proceeds to more
advanced topics. Some of the chapters, by their very nature, start out
advanced and get even more so. Again, these are not tutorials; they
merely explain aspects of TOS that may not be apparent to a non-Atari
(or new Atari) programmer.

The function references themselves are superb. Each function is
listed, along with opcodes (as necessary), parameters, and more. The
Compendium even lists how to tell whether the function is
available - this may require checking a GEMDOS version, a TOS version,
an AES version, checking for SpeedoGDOS, finding a specific cookie, or
other things (all of which the overviews will explain how to do).
Many functions have a "Caveats" section, which tells of known bugs
with the function or possible problems with its use. There are quite a
few functions which are documented, but not implemented in TOS
(particularly in the VDI); they are included for completeness and are
clearly marked as being practically unusable.

The Hardware section is very useful. It explains how to work with the
hardware in Atari computers, but only when there is no other way to do
it. For example, the STe/TT DMA sound does not have any supporting
calls in the XBIOS, so the Compendium explains how to work with DMA
sound by programming the hardware directly.

The memory map (one of the appendices) is more complete than any I
have ever seen. It lists addresses for the 680x0 vectors, system
variables, and addresses for TT and even Falcon hardware registers.
It also tells you which machines those addresses are valid for.

Of particular importance to new Atari programmers are the GEM User
Interface Guidelines. These are some general principles to follow when
designing application interfaces, and are very useful for those who
are not too sure of how to make an interface that is friendly,
consistent, and intuitive.

And of course, no reference book is worth much without a good index...
and the Compendium has a fine one. It also has an excellent table of
contents, good page headers, and functions are arranged alphabetically
by name within their chapters. If you have a function number, but not
a name, you can look it up also as one of the appendices is a function
listing by opcode, rather than by name. Scott seems to have thought of
everything.

So there it is. The Atari Compendium could easily have been named the
Atari Bible, it is so complete. At the developer's conference held
just before the Glendale show, Mike Fulton said he would be able to
eliminate a great deal from Atari's developer documentation, now that
the Compendium includes so much of what used to be in it. Scott
Sanders spent time in Sunnyvale working with Atari staff to make sure
the information is accurate and current. It shows.

With a suggested list price of just $49.95, this book is an ESSENTIAL
buy for Atari programmers of ALL levels. Get it. You won't regret it.

SDS Publishing
996 Redondo Ave #404
Long Beach, CA 90804
USA

GE: S.SANDERS2
IN: S.SANDERS2@genie.geis.com

Atari Compendium
ISBN: 0-9638331-0-3

[ Editor's NOTE:

 By sending in the registration card one will receive:

 a) Information on how to obtain errata and addendum sheets
 b) Information on upcoming SDS products
 c) Sample independent developer's newsletter ]


/***********************************************************************/
                 OBJECT::ATARI
              By: Warwick Allison
/***********************************************************************/

     Part 3 : C++ And Your Atari


------------------------------------------------------------------------
ERRATUM:  In the last column, I forgot to include one vital environment
          variable.  You need GCCEXEC = /gnu/bin/gcc- (or whatever your
          path to your gcc-*.ttp files is).  Note that the "gcc-" is
          part of the value.  GCC uses this variable and appends each
          of the subprocess names (like "cpp", "cc1-plus", etc).
------------------------------------------------------------------------



                             C++ And Your Atari
                             ------------------

1. Why C++ on Atari?

C++ is an excellent language choice for the Atari programmer.

Firstly, the Atari computers, like most modern computers, use the C
language as the primary systems programming language. This means that
all of the operating system functions are designed to be called from
C, and while other languages are usually capable of interfacing with
the operating system, these other languages will always lag behind.
For example, before most people had even SEEN an Atari Falcon030, the
interface to its new operating system functions were available (in the
"falcon.h" file). For other languages, it is necessary to wait for the
next version, or to hand-craft your own assembler language interfaces
to the operating system. Since C++ is the successor to C, and can call
C in a totally seamless way, C++ is as good as C for interfacing with
the operating system.

Secondly, the GEM environment on which all Atari GEM applications run
is inherently an Object Oriented environment. In fact, one of the
basic types in the system is called OBJECT! It was this highly object
oriented nature that prompted me to provide the GEM++ library that
makes GEM programming in C++ easier than it is plain C. We will be
looking at GEM++ in detail in a later column, for now we will look for
objects in our Atari....


2. Objects in the Atari environment

The first task when writing a program in an Object Oriented language
like C++ is to try to identify the *objects* in your design. For
example, if you wanted to write a Space Invaders program in C++, you
would quickly think of the following objects:

    - Player turret
    - Invaders
    - Mother ships
    - Barriers
    - Attack waves
    - Score
    - Lives

You would also recognize that there are 6 or 7 different types of
invader, and a couple of types of mother ship. Also, you would see
that each attack wave contains a number of invaders.

Given these observations, you could write a Space Invaders program by
writing a PlayerTurret class of object, an Invader class of object
(and 6 or 7 "derived classes" for each of the slightly different
invaders), a MotherShip class (and 2 derived classes), a Barrier
class, etc.

Each of the classes of object you identify in your observations has a
small number of behaviors. For example, a PlayerTurret can be created
at the beginning of a level, can move left, move right, fire a bullet,
or, sadly, explode. A Barrier can be created, can take a hit from
above at a certain position, be hit from below at a position, or can
be gobbled by advancing invaders. A Score can be created at the
beginning of a game and can increase by a certain amount. The other
object have there own behaviors, which the prospective Space Invaders
author would think about.

So, objects are easy to identify in games. But so too are they easily
seen in GEM applications and any other program you might write. In a
GEM application, we would expect to see objects like dialogue boxes,
windows, alert boxes, and menu bars. Also, just as there are different
types of invader, there are also different types of these GEM objects.
Applications would be pretty boring if all of the dialogue boxes did
the same thing! So if your application is a drawing program, you might
make a special kind of window that you can draw in, and if you are
writing a text editor, a kind of window in which you can print text
would be useful.


3. A Simple Example

The program below is a very simple, but complete example that requires
nothing more than your GNU C++ or other C++ setup.

The example treats the Atari VDI (Virtual Device Interface) as an
object, and allows you to clear the screen and draw lines.


//
// Simple example program.
//
// Compile using:
//
//    gcc example1.cc -lg++ -lgem
//
// When compiling, be sure to put the libraries in the right order.
// In general, put any C++ libraries you use, then -lg++ (the
// standard GNU C++ library), then any C libraries you use.
//

// Include the C AES and VDI libraries.
//
#include <aesbind.h>
#include <vdibind.h>

// We declare a class called "SimpleVDI". This class provides a
// small number of drawing functions.
//
// Usually, a class would be declared like this in a header file,
// usually // the file would be called "simplevdi.h".  That header
// file would then be included into any C++ files (.cc files) that
// used SimpleVDI.
//
// The "VDI" is the Virtual Device Interface of the Atari that
// programmers can use to do graphics without directly accessing
// the computer's graphics
// hardware, thus making their programs portable to graphics
// cards, newer hardware, etc.
//
class SimpleVDI {
public:
     // The "constructor" of the class.  This member-function is
     // automatically called whenever a SimpleVDI is created (such
     // as a variable declaration).
     SimpleVDI();

     // The "destructor" of the class.  This member-function is
     // automatically called whenever a SimpleVDI is destroyed (such
     // as at the end of the "scope" of a variable).
     ~SimpleVDI();

     // The member-function "Clear" wipes the SimpleVDI, making the
     // screen blank.
     void Clear();

     // MaxX returns the maximum X co-ordinate that this SimpleVDI
     // allows.  MaxY returns the maximum Y co-ordinate.
     //
     // Here we are using "in-line" member-functions - that is, we
     // give the code for the member-function right here.  The
     // compiler will often include the code directly into the
     // program that calls these functions, rather than actually
     // calling a function, thus making access very fast.
     //
     int MaxX() { return work_out[0]; }
     int MaxY() { return work_out[1]; }

     // Line draws a line from (x1,y1) to (x2,y2).
     void Line(int x1, int y1, int x2, int y2);

private:
     // The following members are private data - they are only
     // "visible" to the member-functions in this class.

     int handle;        // The VDI handle.
     int work_out[64];  // Attributes found when the VDI is opened.
};



// Now we define the member functions.  Usually, these would be in
// a separate file, usually called "simplevdi.cc".  That file would
// include the "simplevdi.h" file.
//
// Notice that member functions deal with a *particular* object.
// For this reason, when one of the member functions is called,
// it makes sense to refer to the data members of that object.
// For example, in the constructor for SimpleVDI, we set "handle"
// and "work_out", which are the two data members of every
// SimpleVDI object.

// The definition of the "constructor" for SimpleVDI.
//
SimpleVDI::SimpleVDI()
{
     // Find the graphics handle that the aes is using.
     //
     int j;
     handle=graf_handle(&j,&j,&j,&j);

     // Open a virtual workstation on that handle, giving us a new
     // handle in "handle" and an array of attributes in "work_out".
     //
     int work_in[]={1,1,1,1,1,1,1,1,1,1,2};
     v_opnvwk(work_in,&handle,work_out);
}

// The definition of the "destructor" for SimpleVDI.
//
SimpleVDI::~SimpleVDI()
{
     // Close the virtual workstation which we opened when this
     // SimpleVDI was created.
     //
     v_clsvwk(handle);
}

// The definition of other member-functions...

void SimpleVDI::Clear()
{
     // Clear the virtual workstation, using the handle we were
     // given when the workstation was opened in the constructor.
     //
     v_clrwk(handle);
}

void SimpleVDI::Line(int x1, int y1, int x2, int y2)
{
     // Create an array holding the co-ordinates.
     //
     int pxy[]={x1,y1,x2,y2};

     // Pass the array of 2 points to v_pline.  We use the handle
     // we were given when the workstation was opened in the
     // constructor above.
     //
     v_pline(handle,2,pxy);
}


// We define some simple functions (non-member functions).

// This function finds the minimum of two integers.
int minimum(int a, int b)
{
     if (a>b) return b;
     return a;
}

// This function, which has the SAME NAME as the function above,
// finds the minimum of two integers.  As long as the parameters
// to the function are different, we are permitted to have
// functions with the same name.  This is good, because it means
// we don't have to invent so many names (eg. min_int, min_dble),
// and don't have to use unsafe #define macros.
//
double minimum(double a, double b)
{
     if (a>b) return b;
     return a;
}


// Now the main function.  Just as in C, the main() function is
// called when the program is run.
//
main()
{
     // Declare a SimpleVDI variable.  This is just like declaring
     // an integer variable, or any other type of variable.
     // We are calling our SimpleVDI simply "vdi".  We could call
     // it "fred"!
     //
     SimpleVDI vdi;

     // Clear the SimpleVDI we know as "vdi".
     //
     vdi.Clear();

     // Find the maximum X or maximum Y co-ordinate, whichever is
     // smallest.
     //
     int size=minimum(vdi.MaxX(),vdi.MaxY());

     // Draw a pattern of lines on our SimpleVDI.
     //
     for (int i=0; i<=size; i+=3) {
          vdi.Line(0,i,size-i,0);
     }

     // At this point in the program, the variable "vdi" is going
     // "out of scope", and its destruction, ~SimpleVDI() will be
     // called automatically.
     //
}

--
  _-_|\      warwick@cs.uq.oz.au            / Times like these:
 /     * <-- Computer Science Department,  /      Move your mop into the
 \_.-._/     University of Queensland,    /       circle and see twice a
      v      Brisbane, Australia.        /        programming tool.



/***********************************************************************/
                 In the Trenches
                 By: Albert Dayes
/***********************************************************************/

                 "Straight as an Arrow"

There are two levels for programming one is the design level and the
other is the code level. The design phase is like flying over a large
area in a helicopter while mapping it for a new road. The code phase
is the physical labor ("In the Trenches") to make the road...
digging ditches, moving dirt, etc. Both are equally important but
some of us like one phase more than the other.

This article deals with some work "in the trenches" I was doing just
recently. It involved using a PostScript Library for C. The library
gives one full control over fonts including track and pair kerning.
There are functions for fully justified text but just in general
terms. It does not allow one to use AFM (Adobe Font Metric)
information or multiple fonts.

After a period of several months I finally created a library that
would give me both (justified text and multiple fonts). After making
some minor changes to the code I noticed that the justified text was
not working quite right. After closer examination it was very
noticeable on some columns and not on others. What could be wrong?

The next three hours (10pm to 1am) involved stepping through the
entire program line by line. And using the Pure C source level
debugger to check calculations. It was discovered that the problem
was in calculations of the size of the line. So the problem was not
in string_wrap() function but in the justify_text() function itself.
This was good since the problem was not a logic error which would mean
a complete redesign of the string_wrap() function.

The justify_text() function works as follows...

  |<----------- width of the column ---------------->|
  |<-- size of the string -->||<-- remaining room -->|

The string needs to be expanded to make sure it fits exactly within
the width of the column. For this to work each space has a small
offset added to it. This offset is calculated as follows...

  space_offset = size_of_a_space + ( remaining_room / number_spaces );

This works perfectly for this calculation. But then came the actual
output of the single line of text itself which failed. The output
section works as follows...

  while not end of line
    {
     read characters
     if ( character = a space character )
       {
        output the contents of the word buffer with track and/or pair kerning
        add the size of the word plus the space offset to the cursor position
       }
     else
       {
        add characters to the word buffer
       }

    } /* while */

  output the last word with track and/or pair kerning

While stepping through this part of the function with the debugger I
noticed that the calculations were different. By the time the output
was done it was up to +/- 10 points from where it should be. Then it
finally dawned on me that it was a calculation error. So how does one
fix this error?

After some thought I remembered taking a class on Numerical Analysis.
After finding the book I started reading through the section
"round-off errors and computer arithmetic." There were several
algorithms to fix/control these errors like (Secant, Fixed-Point,
Bisection, Newton, etc). But all of the above would take some time to
adapt to my particular problem. Then there was something more general
about calculating errors. Absolute and relative error looked like
something much easier to work with. Here are the simple equations for
these errors.

Absolute Error = | P - *P |

Relative Error = | P - *P | / | P |

Where P = correct value and *P = estimated value.

The vertical bars indicate absolute value. Absolute value ensures
the result is always positive. (i.e., | -7 | = 7 )

So I decided to use a modified version of Absolute Error to fix the
error. The absolute value was dropped since the line could bigger or
smaller than the column width (after the calculation for output had
been completed).

Basically the output function was run twice. The first time was just
to perform the calculations. The second part involved the error
calculations, fixing the error and finally outputting the text.

After running through the function the first time with no output the
size of the calculated string is known. This is stored in the variable
approx_string (declared as a double). Then the approx_string is
subtracted from the column_width (declared as double). The difference
is the amount of error between the two. This could make the line
either longer or shorter than the defined column width. One can see
why the absolute value had to be dropped from the equation when it
comes to fixing the error.

For this to work the error must be subtracted from the calculated
value so it will always be perfect. Some examples....

column width ............ = 276 points
approximated string width = 282 points
======================================
"absolute" error ........ =  -6 points

If absolute value was allowed then | -6 | = 6 which would increase the
error and not eliminate it.

column width ............ = 276 points
approximated string width = 253 points
======================================
absolute error .......... =  23 points

Then this error is divided by the number of spaces and added to the
space offset. So each calculation using the space offset variable will
effectively handle the error caused by the calculation itself.


A code fragment follows...

 /* Calculate approximate string error and then fix the calculation error */

 error_margin = (column_width - approx_string);

 /* correct space offset */

 if ( number_spaces > 0 )
   space_offset += (error_margin/number_spaces);


The result makes a perfect straight line down the right side of the
column. It does not look half justified and half ragged right but
complete... straight as an arrow.

The error that is occurring is a linear type error and not an
exponential type of error. Basically one can think of linear as a one
to one relationship. One can press a single key on the keyboard (L for
example) and only 1 character would appear. If it was exponential
pressing a single key on the keyboard (E for example) and 1000
characters would appear. Not only would this be frustrating it would
not be tolerable. This condition is considered un-stable while the
opposite condition is stable. When conditions are stable they are much
easier to correct. For example if one had 1000 characters per keypress
it would be very hard to correct a 25 page document using a word
processor. It would be impossible and could not be tolerated.  Since
the error rate is linear it can be corrected easily just as easily as
one corrects mistakes in a word processor. Using the technique
outlined above demonstrates how simple it can be.

==========================================================================

   GRAPH(s): ERROR GROWTH RATES [ TIME (X-axis) vs ERRORs (Y-axis) ]


   |            E        |  E
   |         E           |  E
   |      E              |  E
   |   E                 | E
   |E                    |E
   |--------------> X    |--------------> X
     LINEAR                EXPONENTIAL

==========================================================================

References:

Numerical Analysis, 4th Edition
Authors: Richard Burden & Douglas Faires
Publisher: PWS-KENT Publishing Company
ISBN: 0-534-91585-X

C_Graph Software Inc
PO Box 5641
Austin, TX 78763
USA
(512) 444-3336 (voice)

c_ps.lib     -- Ansi C library for creating PostScript from C applications
c_psFontInfo -- Ansi C library for setting PostScript Text from C
                applications

Learning PostScript - A Visual Approach
Author: Ross Smith
Publisher: PeachPit Press
ISBN: 0-938151-12-6

PostScript Language Reference Manual, 2nd Edition
Author: Adobe Systems Inc
Publisher: Addison-Wesley Publishing Company, Inc
ISBN: 0-201-18127-4

(also known as the red book)

[ Editor's NOTE:

A demo of the PostScript library can be found on Compuserve and GEnie.  It
includes C source code for the demo and technical specifications for the
two libraries. ]

/***********************************************************************/
     Language Watch -- Current versions of developer tools
/***********************************************************************/

DEV| version & date   | product
==========================================================================
A  | 1.1 Jan 1993     | Pure C (with ASM/C source level debugger) (German)
A  |     Sept 4, 1992 | Pure Pascal (German) (Turbo pascal 7.x compatible)
A  | 2.x              | Interface, (resource file editor, with 3D icons)
B  | 3.00             | Devpac 3 (assembler)
B  | 5.52             | Lattice C
B  | 2.10             | HiSoft BASIC 2 (includes compiler)
B  | 2.03.02          | HiSoft C (C interpreter)
B  | 1.6              | HiSpeed Pascal (Turbo pascal compatible)
B  | 1.21             | FTL Modula-2
B  | 1.24             | WERCS (resource file editor)
C  | 2.05             | Personal Pascal
D  |      Aug 3, 1988 | Assempro (assembler)
E  | 2.1  1989        | Laser C
E  | 1.1  1989        | Laser DB (assembly & C source level debugger)
F  | 3.7  1991        | GFA BASIC (includes compiler)
G  | 1.14, 1989       | Prospero C
G  | 2.15, 1989       | Prospero Pascal for GEM
G  | 2.15, 1989       | Prospero Fortran for GEM
G  | 1.11, 1989       | Prospero Developer's Toolkit
H  | 3.6d Oct 1, 1988 | Aztec C
H  | 3.6e Dec 6, 1988 | Aztec SDB (C source level debugger)
I  | 3.0.9, 1988      | Mark Williams C
I  | 1.0, 1988        | CSD (C Source level Debugger)
J  | ***              | GNU tools, compilers and assembler

A = Gribnif Software/Applications Systems Heidelberg
B = Oregon Research Associates and/or HiSoft
C = ICD/OSS
D = Abacus Software
E = Megamax
F = GFA
G = Prospero
H = Manx
I = Mark Williams Company
J = Free Software Foundation

*** see Warwick's OBJECT::ATARI part 2 for specifics

[ Editor's NOTE:

  Producers of development tools are strongly encouraged to send press
  releases and upgrade announcements to the Editor ]

/**********************************************************************/
                   Bad Example
                   By Albert Dayes
/**********************************************************************/

NOTE: Pascal Source code is used this time.


-----------------------------------------------------------------------
                             bad example
-----------------------------------------------------------------------
program DRAWDIAGONAL( OUTPUT ); { Draws a diagonal line of integers.}
const SIZE = 5; {number of integers printed} var COLUMN : INTEGER;
{loop control variable} begin { DRAWDIAGONAL } { Print 5 Integers } For
COLUMN := 1 to SIZE do WRITELN ( COLUMN : COLUMN ) end. { DRAWDIAGONAL }

------------------------------------------------------------------------
                             good example
------------------------------------------------------------------------
program DRAWDIAGONAL( OUTPUT );

{ Draws a diagonal line of integers. }

const
  SIZE = 5;            { number of integers printed }

var
  COLUMN : INTEGER;    { loop control variable }

begin  { DRAWDIAGONAL }

  { Print 5 Integers }

  for COLUMN := 1 to SIZE do
    WRITELN( COLUMN : COLUMN )

end.   { DRAWDIAGONAL }


Looking at both programs one can easily see how much easier the good
example is to read versus the bad example. Even though both programs
do exactly the same thing the first is near impossible to read.
Consider if one asked a friend to help write some routines for a
program. If the routines were delivered in the form of the bad
example I'm sure one would definitely protest. And demmand that the
routines be rewritten in a much easier to read style or format.

This is not only important for functions/procedures that others write
for you but also for you as well. If one writes code to beat a
deadline it is very important one go back soon after the deadline is
completed to reformat the code. Going back six months later to fix
the problem in the code and it looks like the source code in the bad
example will not be very appealing. It is best to do it right the
first time and then one will not have to go back and "beautify" the
code later on.

Being able to spot errors is another reason to use a good, readable
format for one's source code. One does not have to use the style
presented above in the good example but use a style that one finds
most comfortable. Also be consistant in your style! If one mixes a
"good" style and "bad" style it does not help when looking for
problems later on.

/************************************************************************/
                          ON THE NETWORKS
/************************************************************************/

Some feedback on our first issue from GEnie and CIS... and other
exciting topics.

#: 89082 S11/Programming
    23-Aug-93  23:34:11
Sb: #AEO Prg. Journal
Fm: Shawn Laughlin 76547,1032
To: All

 I just finished reading Atari Explorer's Programmer's Journal
(AEPJ01.ZIP in the news/reviews lib of ATARIARTS) and was very
impressed with it. IMHO, it's right on target for the audience its
trying to reach.

 I especially liked the article on interfaces as I am currently
trying to design a good one for something I'm working on. I intend to
incorporate the idea of the little help window that changes messages
as the mouse passes over an icon. Mine is also an icon based interface
and I believe this will make it much friendlier. I don't know about
"talking dialog boxes " <g>.

 There was a very helpful tidbit in the developers information
section about keeping programs compatable with MultiTOS (i.e., stick
to GEM I/O or Bios I/O but don't mix them). I'd like to see more
articles on exactly what to watch out for when trying to keep a
program portable to the different TOS's . I guess we all know to stay
away from the taboo line_a, but I'd like to know more about the
different screen resolutions of the Falcon and TT (e.g. do they
interleave bit planes like the ST/STE? Are the palettes stored the
same ? etc).

 Think maybe an assembly column could be worked in (for those of us
that still like to hack <g>) ?  Maybe Tony @ Moving pixels could do an
article or two <ducking>.

 All in all it is a well balanced and informative mag. I'll be
following the series on lex, and OOP.

 I do have a question though, why is the mag over in ATARIARTS ? I
suspect if it stays around (and it needs to), it will become a
reference source for programmers. Perhaps it should be in the
programming library?

 Good job Atari Explorer!

 Shawn

 P.S. Dump the ZIP format <g>.

Message 104       Sun Aug 29, 1993
MIKE-ALLEN [NM~SysOp]        at 16:43 EDT
 
Albert,

I really enjoyed the first issue.

I would like to see more assembly language stuff in AEO-PJ.  I would
also like to see information about the OS and the hardware such as
that that used to be available from third parties, such as Abacus.

I'd like to see some basic stuff (not BASIC, the language) like
walking the rectangle list and using event_multi.  For instance, I
have heard that event_multi really slows down execution time.  True?

I suspect that many people would get more interested in programming
for the ST/STe/TT/F030 if more information were available.  I know
people will say "buy the developers kit, it's not that expensive," but
many folks don't want to invest in the DK until they get their feet
wet.

I'd sure like to see something on the format and contents of the
DESKTOP/NEWDESK.INF files.  Hardware address and contents would be
nice.  Cookie Jar rules and utilization.  Using the DMA sound on
STes/TTs/F030s.  I know you have to respect Atari's NDA, but maybe
Atari would allow you to publish some of this info.

More assembly and C, less GFA BASIC.  (that may just be me.  I hate
basic in any form <g>).  Maybe comparative routines in all three?

I really think that people will be looking to AEO-PJ for the type of
info that used to be available from third parties when such parties
existed.  Now that resources for programmers/users have been reduced
to almost exclusively Atari, I feel that Atari needs to be a little
more forthcomming with that info.  Maybe (I hope) AEO-PJ can fill that
void.

        Mike Allen

Message 109       Mon Aug 30, 1993
M.HILL13 [Mike]              at 22:55 EDT
 
Albert,

I thought the issue was pretty good.

I would like to see topics like:
   "Writing MultiTos/Geneva Compatible Programs"
   "Fast Sprites routines"
   "XBRA protocol"
   "Cookie Jar info"

Mike Fulton at Atari had an article on writing Multi-Tos compatible
programs in a developers newsletter awhile back. Maybe you guys could
talk to Atari about getting reprint rights.

I personally would like to see some sprite stuff.  I have worked with
the other issues and encountered some challenges getting info on those
topics until I got the devleopers package.

Articles on writing compatible software, XBRA protocol, and the
Cookie Jar would be excellent info to get out to programmers just
getting started.

Mike

P.S. Source code for articles with examples is great, but if if gets
too lengthy I would recommend keeping it in a separate file.

Message 23        Wed Sep 08, 1993
DMJ [dmj]                    at 22:48 EDT
 
Albert:

Personally, I would prefer the User View columns to be written by non-
developers.  As you stated, developers sometimes get out-of-touch
with their userbase.  The User View column is the perfect place to
remind them who they're dealing with.

Have you looked at the typical PC word processor these days?  They're
chock- full of features that nobody can figure out how to use.  You
end up with this huge (and I mean MEGAbytes) package sitting on your
hard drive, with perhaps 200K of it being actually used.  What's the
point?  It's pathetic, if you ask me... but then, I think that about
most of the PC world in general.

Anyway, please try to draft some non-technical people to write the
User View.

     -dmj

Category 15,  Topic 5
Message 27        Thu Sep 09, 1993
TOWNS [John]                 at 15:09 EDT
 
 Albert.. I agree. The author of the Object::Atari column could handle
 both C++ and OOD type columns. I didn't mean to imply otherwise.

 As for User Views.. Sounds good to me. I think Developers would enjoy
 hearing from users about what they are looking for in products. I
 know that I would certainly listen to what they have to say.

 I would still suggest that you see if you can reprint those Atari
 User Interface Guidelines. They could really help steer some
 developers in the right direction.

 I look forward to the next issue. it's really great to have a journal
 for programmers again. The last time I remember having a suitable
 journal for programmers was the magazine ST Applications (anyone of
 you remember that magazine?)

 As for OOP.. I guess I am a fan! I better be.. my job is completely
 OOP stuff!

 -- John

Category 15,  Topic 5
Message 28        Thu Sep 09, 1993
R.WATSON15 [Wayne Watson]    at 18:04 EDT
 
  I think everyone that writes GEM applications and interfaces should
read the Pro GEM series (I believe that was the name of it). It is a
very nice series. Maybe you could look into making it a regular series
in AEO-PJ. I know it's been out awhile and is available for download
and all but, having it in with the PJ would be a nice touch to the
Interface section for beginners. Heck, even non-beginners could use it
as I have seen some terrible interfaces. Just a thought.
 ------------
Category 15,  Topic 5
Message 24        Thu Sep 09, 1993
R.WHITTAM [Ron - ABUG]       at 00:53 EDT
 
Travis,

I am very impressed with your initial issue.  A lot of good stuff, to
say the least.  Keep it coming!

My most expensive compiler is SOZOBON C.  I know it is not ANSI
compliant, but I would like to see some tips on this one in the future
as well as GNU.  I tried GNU (a few years back) but couldn't get it
off the ground--took too much space and memory.   I don't have a
specific question right now, or I would ask it.

The general info on basic concepts in this issue is GREAT.  However,
being new to online, acronyms need to be explained.  The letters IMO
in the middle of a sentence is unclear.  I think a good rule of the
thumb (ROTT) would be to give the expanded expression the first time
with the acronym in parenthesis, in my humble opinion (IMHO).  OTOWA,
(or the other way around).

I am generally unindated with TLA's (three letter acronyms) at my job
as a mainframe tech support using IBM, REI, DEC, and STC hardware.
With IBM and Novel's competition in this area, the development of
ETLA's (Extended three letter acronyms) have made learning simple
acronyms a basic nightmare with ANSI, ASCII, EPCDIC, DFDSS, MVS/OS and
a pleathoria (where's that spell checker??) of other similarly
understandable letteric, like PCMCIA (which I have heard to really
stand for: People Can't Memorize Computer Industry's Acronyms).  All
in all, (AIA) I think I have made my point.  Thanks for listening.

 Ron Whittam
 Atari Boise Users Group

R.WATSON15 [Wayne Watson]    at 23:56 EDT
 
  GFA BASIC is used by quite a bit of people so the inclusion of
examples for that language would be nice. Just because some people
don't like it or use it doesn't mean it shouldn't be included. Also,
Pascal is starting to pick up some. I am using HS Pascal. I know a lot
of GFA BASIC, intermediate Pascal and some C and a small touch of
assembly. Having examples in the different languages would really help
out.

  There was a file placed in the libraries a month or two ago that
gave the full hardware layout of the ST/STE/MSTE/TT.

  I wouldn't waste my money on the Dev. Kit.
 ------------
Category 15,  Topic 20
Message 107       Mon Aug 30, 1993
R.WATSON15 [Wayne Watson]    at 05:17 EDT
 
  I hope the AEO-PJ continues as it did in the first issue. I liked
the the material in it and hope for some more.

  I have been programming in GFA for a long time. After dealing with
problems in GFA in a large application that I have and after finding
out that GFA has temporarily dropped support, I decided to expand my
horizons a little. I got the Lattice C package and found that C was a
hard language to move to from GFA. I learned a lot from people online
here who were very helpful showing me how to do things.

  On a tip from a friend, I tried Pascal and find it a lot easier to
move to from GFA. In Pascal, I see some things comman with GFA and
some things comman with C. My big problem with C is having to deal
with pointers and the like.

  Anyway, my point is that I hope you continue to provide help with
people that are starting to expand their horizons in other languages
(beginners).  That is why I think that examples in as many languages
as possible are important. It helps the beginner in other languages
see the differences and can relate things a lot easier.

  I am not asking that the magazine be a teacher to beginners. I just
hope that you do not leave us out.

  I would like to thank those involved for starting this as I feel it
is an important part of the puzzle for people programming on the
Atari. Resources like this are common on the other platforms and
readily available. It's time we also have those resources. Hopefully
Atari can pitch in now and then to help.

#: 329775 S5/C Programming
    22-Aug-93  06:56:33
Sb: #Substrings from string
Fm: renwick preston 73117,3301
To: all

If I read in a string composed of the characters shown below, how do I
extract the "XX","YY" and "ZZ" into their own strings?  
.  


-----------------------------------------
Return to message index