Copy Link
Add to Bookmark
Report

AEO Programmers Journal Installment 02

eZine's profile picture
Published in 
AEO Programmers Journal
 · 22 Aug 2019

  

/***********************************************************************
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 (c) 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 nx2" 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?
.
.
AAAAA
BBBBB
CCCCC
XXYYZZ .

I know how to use strtok if the substrings are separated by spaces but
I do not know how to start at a certain character and only copy a
certain number of characters. I am trying to port over a program from
Turbo Pascal and the only reason I am resorting to C is the limitation
in TP of 255 chars in a string. The string I am reading in contains
369 chars. Thanks in advance,

#: 329780 S5/C Programming
22-Aug-93 07:49:42
Sb: #329775-#Substrings from string
Fm: Gary Blaine (TeamB) 70007,4650
To: renwick preston 73117,3301 (X)

Ren,

There are lots of ways to do it, depending on just what it is you are
wanting to do. Here are some examples:

#include <stdio.h>
#include <string.h>

int main(void)
{
char* str = "AAAAA BBBBB CCCCC XXYYZZ";
char* ptr_start;
char* ptr_end;

char x[3];
char y[3];
char z[3];

// use just strncpy()
strncpy(x, str+20, 2);
x[2] = '\0';


// use strchr(), strrchr()
ptr_start = strchr(str, 'Y');
ptr_end = strrchr(ptr_start, 'Y');
strncpy(y, ptr_start, ptr_end-ptr_start+1);
y[2] = '\0';

// use strpbrk()
ptr_start = strpbrk(str, "Z");
strncpy(z, ptr_start, 2);
z[2] = '\0';

printf("%s %s %s\n", x, y, z);

return 0;
}

Category 14, Topic 34
Message 151 Tue Sep 21, 1993
ERIC.SMITH [Eric Smith] at 17:11 EDT

Thunderbird:

MultiTOS has 2 distinct parts: the MiNT multitasking kernel, and the
multitasking AES.

If you want to know if MiNT is present, check the cookie jar for the
cookie 'MiNT'. If present, its value is the version of MiNT running
(e.g. 0x0104 for MiNT 1.04).

If you want to know if the AES supports multitasking, check the AES
global array. The first word of that array is the AES version number,
and the second is either -1 (if the AES supports unlimited
multitasking, e.g. MultiTOS) or a positive number (the number of
programs that can be loaded at once; 1 under ordinary TOS).

Note that you should use the number of applications supported, and
not the AES version number, to test for multitasking, since some AESes
can run either in single or multi-tasking mode.

Which one of the two tests above is appropriate depends upon what
you're trying to do. If you want to use a MiNT/GEMDOS feature, test
the MiNT cookie; for an AES feature, test the AES global

  
array. Note
that it is possible to run MiNT with a single tasking AES (e.g. if you
just want the MiNT CD-ROM driver, but don't want the MultiTOS
desktop). There are also third party multitasking products (like Mag!X
or Geneva) which may not provide MiNT services but do provide AES
level multitasking.

MiNT does not task switch while the machine is in supervisor mode, so
you can protect critical sections of your code that way. Obviously you
should do this only when you really, REALLY have to, since users will
be very peeved if your application is grabbing all the CPU time and
they're trying to do something else!

Gordon:

The _FLK cookie indicates whether or not file locking is supported;
it's always there under MiNT, but may also be there if a MetaDOS
network driver is installed on ordinary TOS.

M.ABDULKAREE,W.KILWINGER:

I think I mentioned this in an earlier post, but just to make sure
there's no confusion:

(1) Check for the presence of a MiNT cookie if you need MiNT features,
including GEMDOS level multitasking.

(2) Check the number of AES processes supported (global[1]) if you
need AES level multitasking; this will be -1 if the AES is
multitasking.

(3) The AES version number should *not* be used for either of these
purposes, since (as Wilfred correctly pointed out) some AES versions
can function in either single or multitasking mode. The AES version
may be useful for determining features (like 3D gadgets) present in
the system; an even better method of doing the latter, though, is to
use the appl_getinfo() system call to determine whether or not various
AES features are supported. See the developer's documentation, or the
Atari Compendium book from SDS, for details on this call.

#: 89354 S11/Programming
30-Aug-93 00:56:57
Sb: #89339-evnt_multi()
Fm: Shawn Laughlin 76547,1032
To: Atari Explorer 70007,3615 (X)

Albert-

The following compilable code demonstrates the problem. The first
time you press a key you will go to the function "foobar". While in
that function, hit some keys. When the program returns to the
evnt_multi loop, these unwanted keypresses will be processed. I don't
want the keypresses that happen while the program is in "foobar()".

Either mouse button to exit.

#include <stdio.h>
#include <gemfast.h> /* include your favorite GEM headers */

int main()
{
int which,dummy[8];
int firstkey = TRUE, done = FALSE;

appl_init();
printf("(evnt_multi): Press a key to go to foobar");
do{
which = evnt_multi(MU_KEYBD|MU_BUTTON,0x101,3,0,0,0,0,0,0,0,0,0,0,0,
dummy,0,0,dummy,dummy,dummy,dummy,dummy,dummy);
if(which & MU_KEYBD){
if(firstkey){
foobar();
firstkey = FALSE;
}
else printf(" keypress ");
}

if(which & MU_BUTTON)
done = TRUE; /*exit with either mouse button*/


}while(!done);

return 0;
}

foobar()
{
long i = 1000000;
printf( " (foo): Press some keys ");

while (i--);

}


#: 90333 S11/Programming
24-Sep-93 06:50:26
Sb: #89354-evnt_multi()
Fm: guus ellenkamp 100111,3146
To: Shawn Laughlin 76547,1032

I had about the same problem and fixed it by calling evnt_multi with
the flag of events I don't want + timer event with time value set to
zero. Then I just have to wait until the only event that is returned
is the timer event.


Message 49 Fri Sep 10, 1993
PARADIGM [Mark O'Bryan] at 07:29 EDT

Wayne, specifically which 32k limits are you referring to? And what
are you trying to accomplish?

For the most part, there are no 32k limits in HighSpeed Pascal!
This is in spite of the fact that there are numerous references to
them in both the manual and the on-line help. I know this can be
surprising, as well as confusing.

Here are the true limits in HighSpeed Pascal, v1.5 and beyond:

- global data = 16 meg (per unit, or program)
- stack space = 16 meg
- heap space = 16 meg
- array size = 16 meg (per global array, 32k for a local array)
- program size = 16 meg (code)
- unit size = 16 meg (with $F+; 32-50k each without Far on)

- record size = 32 kB (each)
- procedure size = 32 kB (approx. 60-70 pages of code)
- local proc vars = 32 kB (can include pointers to megabytes on the heap)
- symbol table = 32 kB (per unit)

Obviously, you can't have all of these at once, and of course you're
limited to the total RAM in your machine (minus system overhead). I
don't consider any of these limits to be significant, although the
32k bound im- posed on local variables in procedures by
stack-relative addressing with 16-bit offsets may occasionally
require some extra coding.

((O))
/=\ Mark O'Bryan, Paradigm Software Products [Sep09/92 at 9:57p]
/===\ (makers of Omni-Banker ST, the universal MIDI librarian)

Message 92 Wed Sep 08, 1993
TOWNS [John] at 15:35 EDT

Use this trick to make sure that headers don't get included more than
once:

// top of header file

#ifndef __HEADER__
#define __HEADER__

// Body of header goes here

#endif

Make sure the symbol you define (__HEADER__) is something unique. I
usually use the name of the file.

Another tip: When including header files, do the following:

#ifndef __HEADER__
#include <Header.h>
#endif

This will cause the C preprocessor to only include the header file if
it is included. This should save some time on compiles because this
will prevent the C preprocessor from even opening the header file if
it is already included. Big time saver on most systems.

If you already know about this, feel free to ignore me ;-)

-- John

Message 44 Thu Oct 07, 1993
C.ROUNTREE2 [RoadKill] at 23:26 EDT

DMJ: The fact of the matter is that on the PC I don't have to
worry about shifting or masking sprites. Every pixel is a byte and I
can write one line of C code to grab a pixel. On the ST it is almost
impossible to directly access the graphics from C(the CLUT storage
format needs bitwise operations). And the Put_pixel/Get_pixel assem
routines that I wrote are nearly 3 (screen) pages long, fully
optimised! (err, mostly optimised. I have one multiplication I could
get rid of with a screen line address lookup table)

Yes, the PC has a miriad of problems, but the graphics format
isn't one of them. I would never want to program applications on the
PC, nor do I want to do games on the ST. *sigh* Now if the PC was more
like the Atari. . . .

Dmj, suggesting that he write his own routines for sprites is
assuming a lot. It takes a lot of know how to do those routs.
Everytime I've sat down to flow chart the code for one, I get the
shakes and put the whole idea away.

Damien (DMJ) discusses sprites...

Yeah, you do have to know a lot to write a sprite routine on the ST.

Lessee, were those 16x16 sprites? 16 colors (4 bitplanes) plus one
mask plane? Here's a routine to do them, rated at around 420 sprites
per second (that's only 7 per VBL, but I didn't spend a lot of time on
this routine optimizing it):

-- Code begins --

* 16x16 Sprite Blitter Bundle
* by dmj, v1.0, October 8, 1993.

* This routine trashes d0-d2 and a0-a2; as such, it should be
* callable as a C function. Garbage will be returned in d0.

* On the stack:
* 16(a7).w Y coordinate to put sprite / screen height.
* 14(a7).w X coordinate to put sprite.
* 10(a7).l Pointer to sprite data (function 0) or screen
* address (function 1)
* 6(a7).l Pointer to vertical lookup table.
* 4(a7).w Function number (0=blit, 1=create vertical
* table).

* Sprite data is five bitplanes. The last four are sprite image,
* the first is the sprite mask. Bits SET in the mask will be
* transparent; bits CLEAR will be filled with sprite image. Sprite
* data should not occupy transparent areas.

* Negative values (up to -15) may be passed for the coordinates.
* Sprites will be clipped at the screen's edge.

* This routine assumes an ST Low resolution screen. Adapt the
* routine as necessary to allow for other screen sizes and depths.

* This is NOT the world's fastest code. But it does work, and it
* is reasonably fast (250 sprites per second on an 8MHz ST).

sprite tst.w 4(a7) ; Function 1?
bne make_lookup_table ; It wasn't zero, create table.

movem.l 6(a7),a0-a1 ; Get pointers.
movem.w 14(a7),d0-d1 ; Get coordinates.
movem.l d3-d7,-(a7) ; Save registers.

* Account for negative Y coordinates.

moveq #15,d2 ; Number of lines to blit.
tst.w d1 ; Negative Y coordinate?
bge.s .ypositive ; Nope.

neg.w d1 ; Make this positive.
move.w d1,d2 ; Make a copy.
add.w d1,d1 ; Double it.
add.w d1,d1 ; Quadruple it.
add.w d2,d1 ; Add original to make it * 5.
add.w d1,d1 ; Double to get * 10.
add.w d1,a1 ; Add offset to sprite address.
moveq #0,d1 ; Now treat it as Y-coordinate 0.
eor.w #15,d2 ; And this is how many lines are
left.

* Now calculate the screen address for the sprite.

.ypositive
add.w d1,d1 ; Double Y-coordinate.
add.w d1,d1 ; Quadruple Y-coordinate (offset in
* table of longs).
move.l 0(a0,d1.w),a0 ; Get address of screen line.
lsr.w #2,d1 ; Get Y-coordinate again.
add.w d2,d1 ; Add in size of sprite (Y-coordinate
of
* bottom line).
cmp.w #200,d1 ; Off the bottom?
blt.s .onscreen ; Nope, just fine.

sub.w d2,d1 ; Restore Y coordinate.
sub.w #199,d1 ; Figure Y-199.
neg.w d1 ; Invert to get 199-Y.
move.w d1,d2 ; That's how many lines can be drawn.

.onscreen
move.w d0,d3 ; Make a copy of the X-coordinate.
and.w #$FFF0,d3 ; Clear the low nibble.
asr.w #1,d3 ; Get offset in bytes (16 pixels = 8
* bytes).
add.w d3,a0 ; Add it to the screen address.

and.w #$F,d0 ; Take just the low nibble (right
shift
* amount).

moveq #0,d7 ; Clear right-edge flag.
cmp.w #152,d3 ; Past X coordinate of 304?
blt.s .loop ; No, not off right edge, blit sprite.
moveq #1,d7 ; Set right-edge flag.

* Blit the sprite.

.loop moveq #-1,d4 ; Start mask out as -1 (all
* transparent).
move.w (a1)+,d4 ; Read sprite mask.
ror.l d0,d4 ; Shift right.

* Bitplane 0.

moveq #0,d5 ; Clear this.
move.w (a1)+,d5 ; Read first bitplane.
ror.l d0,d5 ; Shift right.

tst.w d3 ; Negative X position?
blt.s .skip1 ; Yes, don't draw left edge.
move.w (a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,(a0) ; Put it back on the screen.

tst.w d7 ; Off the right edge?
bne.s .skip2 ; Yes, don't draw right edge.
.skip1 swap d4 ; Swap mask.
swap d5 ; Swap data.
move.w 8(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,8(a0) ; Put it back on the screen.
swap d4 ; Swap mask back.

* Bitplane 1.

.skip2 moveq #0,d5 ; Clear this.
move.w (a1)+,d5 ; Read first bitplane.
ror.l d0,d5 ; Shift right.

tst.w d3 ; Negative X position?
blt.s .skip3 ; Yes, don't draw left edge.
move.w 2(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,2(a0) ; Put it back on the screen.

tst.w d7 ; Off the right edge?
bne.s .skip4 ; Yes, don't draw right edge.
.skip3 swap d4 ; Swap mask.
swap d5 ; Swap data.
move.w 10(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,10(a0) ; Put it back on the screen.
swap d4 ; Swap mask back.

* Bitplane 2.

.skip4 moveq #0,d5 ; Clear this.
move.w (a1)+,d5 ; Read first bitplane.
ror.l d0,d5 ; Shift right.

tst.w d3 ; Negative X position?
blt.s .skip5 ; Yes, don't draw left edge.
move.w 4(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,4(a0) ; Put it back on the screen.

tst.w d7 ; Off the right edge?
bne.s .skip6 ; Yes, don't draw right edge.
.skip5 swap d4 ; Swap mask.
swap d5 ; Swap data.
move.w 12(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,12(a0) ; Put it back on the screen.
swap d4 ; Swap mask back.

* Bitplane 3.

.skip6 moveq #0,d5 ; Clear this.
move.w (a1)+,d5 ; Read first bitplane.
ror.l d0,d5 ; Shift right.

tst.w d3 ; Negative X position?
blt.s .skip7 ; Yes, don't draw left edge.
move.w 6(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,6(a0) ; Put it back on the screen.

tst.w d7 ; Off the right edge?
bne.s .skip8 ; Yes, don't draw right edge.
.skip7 swap d4 ; Swap mask.
swap d5 ; Swap data.
move.w 14(a0),d6 ; Get screen word.
and.w d4,d6 ; AND in the mask.
or.w d5,d6 ; OR in the image.
move.w d6,14(a0) ; Put it back on the screen.
swap d4 ; Swap mask back.

* End of loop.

.skip8 lea 160(a0),a0 ; Move to next line.
dbra d2,.loop ; Next sprite line.

movem.l (a7)+,d3-d7 ; Restore registers.
rts ; Done.

* Function 1: Create lookup table. For this, the sprite address
* is interpreted as the screen address, and the Y position as
* the screen height (in pixels). The X position is the length
* of a screen line in bytes.

make_lookup_table
movem.l 6(a7),a0-a1 ; Get addresses.
movem.w 14(a7),d0-d1 ; Get screen line size & height.
subq.w #1,d1 ; One less for looping.

.loop move.l a1,(a0)+ ; Store pointer to screen line.
adda.w d0,a1 ; Add offset for a single line.
dbra d1,.loop ; Fill in the whole table.

rts ; All done.

-- End of code --

This shows just how much is involved in putting something as simple
as a 16x16 sprite on the screen. Agreed, this isn't something to be
undertaken lightly; this took me about an hour and a half to put
together today. I tested it moderately well (to make sure the border
clipping is working), which is how I came up with the 420 sprites per
second figure--while I was testing it, I timed it.

- DMJ

J.STANFORD2 [John] at 20:00 EDT

Roadkill:

I don't understand why you're saying plane interleaved graphics "is
almost impossible... from C"
? The C language has a full complement
of bitwise operators (the only one off hand I can think of it lacks is
rotate).

My set & get pixel routines for an arbitrary number of bit planes are
four lines each in C. Though not the speediest, they could easily be
optimized significantly with lookup tables for the shifts and/or hard
coding the # of planes.

here's get_pixel:

int pull_pixel(int *image_buffer,int x, int y, int width, int planes)
{
int pixeloffset, colorindex=0;

image_buffer+=(((long)(width+15)/16L)*(long)planes)*(long)y+(long)((x/16)*
planes);
pixeloffset=15-x%16;

while(--planes>=0)
colorindex|=((*(ptr+planes)>>pixeloffset)&0x01)<<planes;

return colorindex;
}

This is relatively simple, and you can see where creating lookup
tables for pixel masks, addresses, and restricting bitmap widths to
multiples of 16 pixels would result in significant improvements.

I'm sure there are much better ones.

But a bitblit is really quite different from a pixel set/get as you're
dealing with blocks of pixels and it really becomes a specialized
memory move operation, which in many ways is much easier.

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

Category 3, Topic 6
Message 49 Fri Oct 08, 1993
C.ROUNTREE2 [RoadKill] at 23:22 EDT

John: Err. A nearly impossible task for me, I should say. My
experience bit wise is rather limited when it comes to C; when ever
I've needed to do bitwise opperations I've gone to assem, sionce I'm
totaly comfortable with it (3-4 years of C just isn't enough
experience to do everything)

I'm very glad I said what I did, I CAN USE THAT CODE! (if you
say ok. If not, I'll go back to Assembly. Not the fastest though)



/************************************************************************/
NETWORK SIGN-UP INFORMATION
/************************************************************************/
---------------------------------------------------------------------------
-- --==--==-- GEnie Sign-Up Information --==--==-- --
-- --
-- 1. Set your communications software for half duplex (local echo) --
-- at 300, 1200, or 2400 baud. --
-- --
-- 2. Dial toll free: 1-800-638-8369 (or in Canada, 1-800-387-8330). --
-- Upon connection, enter HHH. --
-- --
-- 3. At the U# prompt, enter XTX99436,GENIE then press <Return>. --
-- --
-- 4. Have a major credit card ready. In the U.S., you may also use --
-- your checking account number. --
-- --
-- For more information in the United States or Canada, call 1-800- --
-- 638-9636 or write: GEnie, c/o GE Information Services, P.O. Box --
-- 6403, Rockville, MD 20850-1785. --
-- --
-- --==--==-- Atari's Official Online Resource! --==--==-- --
---------------------------------------------------------------------------
---------------------------------------------------------------------------
-- --==--==-- CompuServe Sign-Up Information --==--==-- --
-- --
-- --
-- --
-- To sign up for CompuServe service, call (voice call) (800) 848-8199. --
-- Ask for operator #198. You will be sent a $15.00 value CIS membership --
-- kit for free. --
-- --
-- --
-- --
-- --==--==-- CompuServe Sign-Up Information --==--==-- --
---------------------------------------------------------------------------
---------------------------------------------------------------------------
-- --==--==-- Delphi Sign-Up Information --==--==-- --
-- --
-- To enroll as a Delphi subscriber, modem call 1-800-365-4636. Press --
-- [Return] once or twice, and type IP26 [Return] at Password: --
-- --
-- Answer all of the questions, and you'll be cleared for Delphi --
-- access in a few days. If you have questions about Delphi services, --
-- give a voice call to Delphi Member Services at 1-800-544-4005. --
-- --
-- --==--==-- Delphi Sign-Up Information --==--==-- --
---------------------------------------------------------------------------


/***********************************************************************/
USER VIEW
By: Ron Whittam
/***********************************************************************/

Technical Support

In every line of work, help is needed. With a computer it could be a
daily necessity. Computers on all platforms are becoming more and
more technically advanced. No more "plug and play". Even the Falcon
isn't as simple as the old Atari 520 ST. This is due to an ever
broadening scope of what people are using computers for. The more
diverse the applications get, the more changes the computer must be
ready to handle. The basic configuration of the hardware, firmware,
and software isn't as cut and dried as it used to be. For a
programmer, this could be a nightmare to support.

However, the key to a successful application in the last half of the
decade will be a good quality product with superior customer support.
More recently than in the past has the subject of customer support or
technical support come up when people are thinking about software to
purchase. No longer is the computer a math or writing tool for the
technical elite. The modern computer owner is a person who needs to
get a job done. Unlike their earlier counterparts, they don't enjoy
tweaking the performance of their computers. They expect them to be
operating at optimum performance out of the box. These newer owners
want to be able to turn on the computer, do a job, and then leave it;
going about their daily routine. They don't want to be encumbered
with a computer.

I recently set up a computer for a client. While he wanted to do his
finances on it, he was more interested in getting his golf program to
run without a lot of keystrokes or mouse clicks. Essentially he
wanted to just turn on the computer and play golf. He had no real
interest as to how it worked as long as it did work.

In the recent past programmers have been able to get away with
shipping a product that let the user configure it to their own
technical whim. While those types still exist, a whole new group of
users just want to plug and play. They don't want to know how it
works they just want it to work. And when it doesn't they need a
quick and simple "how to" to get it running.

This is where technical support comes in. With the communication
technology of our day, even a one man operation can handle technical
support skillfully. The rise of electronic information services, and
the media promotion of the internet, allows many developers to use
this media to handle technical queries. Many of their customers can
easily contact them on-line, (assuming the customer has an electronic
service's account). However, in our verbal society, people enjoy and
expect person to person technical assistance. The success of
WordPerfect Corporation is a tribute to person to person customer
support.

A quality technical answer desk is not an easy feat when you are a
company of one. This is probably why many have resorted to online
EMail support, answering machine support, or no support at all except
by "snail" mail. I think WordPerfect's 200 plus people in customer
support explains why WordPerfect for Windows is the hottest selling
Windows' application (second only to the Windows operating system
itself).

How can a small programmer compete in such a demanding market place?
One might argue that a well written manual and start up booklets with
step by step illustrated instructions would eliminate the need for
technical support. While it might help to alleviate the general and
commonly asked questions, it wouldn't eliminate the problem. Face
reality: No one reads the manual, (until the technical support person
tells them which page the answer is on). At least no one of this new
generation of computer users. They want you to do it.

As a prime user of technical support phone services, (both hardware
and software), it isn't so much that they solve my problem
immediately, but that they do something. Granted, I want my problem
fixed NOW. However, I understand that fixes sometimes take time...
sometimes weeks. What I find really helpful is a quick work-around.
But what I also need is communication. This means that I get a status
call or can call for a status report. I need to know that they ARE
working on my problem.

Here are some suggestions to better technical support of your
customers:

1. Create a "problem log" form. Have a field for the customer's
name, address, and phone number. Have a place for the
description of the problem and a place for the resolution.
Number these forms.

2. Prioritize problems as they occur. Get colored sticky tabs,
(blue, yellow, and red). If a problem is easily fixed but a blue
tab on it. If you have provided the customer with a work-a-round
use the yellow tab, (you will then work on these yellow problems
when your red ones are taken care of). If the problem is
critical use the red tab. You might also want to have a bin to
use for any problems that you will want to fix in the next
release.

3. Keep a "flatfile" of the problems. Here's how. Create a
file. Call it PROBLEM.LOG. Then, enter a problem on one line
and the solution on the other. Keep it brief but descriptive.
In the solution, note the problem log number when applicable.

4. Access the flatfile when needed. Use a program like GREP or
EGREP to locate the problem. Or use a search option in your word
processor. You will be able to type in key words of the problem.
The search will display the problems that match those key words.
You can then look at the solution section and find (hopefully)
quick answers to past problems.

5. List your technical support phone number. Be careful to have
a sufficient number of lines to keep the "busy" signal down to a
minimum; but not too many where your customers would be "on hold"
for too long.

6. List alternate ways of contacting you.

7. Put an ASCII text problem sheet on your program diskettes for
your customers to fill out when mailing a problem.

8. Make a habit of calling your customers back, even if you
don't have the problem fixed. People like it when you
demonstrate that you care about them.

This will cost the programmer more. It will take time away from
developing, and fixing those pesky bugs, to answer the phone and
listen to problems people are having with their program. However, this
may be the key to succeeding or the reason for failure in the last
half of this decade. It is something to think about. A good quality
product and superior customer support will be the key to a successful
software (or hardware) product in this decade.


/************************************************************************/
Brain Stem Rotator
By: Albert Dayes
/************************************************************************/

Use the following program to find the solution to Ackermann( 7, 7 ).
Use the source code provided below.

Definition of Ackermann's function:

A( i, j ) where i and j are integers greather than or equal to Zero

if i = 0
then A( 0, j ) = 1

if j = 0 and i = 1
then A( 1, 0 ) = 2
else A( i, 0 ) = i + 2

if i > 0 and j > 0
then A(i,j) = A( A(i -1), j -1 );

< ==== cut here for C source code === >

/* Ackermann function in ANSI C */

#include <stdio.h>
#include <stdlib.h>

/* function prototype */

unsigned int ackermann( unsigned int x, unsigned int y );

/*--------------------------------------------------------------*/

main( int argc, char *argv[] )
{
unsigned int x, y;

if ( argc != 3 )
{
printf("Illegal number of parameters.\n");
printf("Ackerman [x] [y]\n");
return (1);
} /* if */

x = atoi( argv[1] ); /* convert strings to integers */
y = atoi( argv[2] );

if ( (x < 0) || (y < 0) )
{
printf("X and Y cannot be negative!\n");
return( 2 );
} /* if */

printf( "Working on Ackermann( %u, %u ) ... \n", x, y );

printf ("Ackermann( %u, %u )= %d", x, y, ackermann(x, y) );

return( 0 );

} /* main() */

/*----------------------------------------------------------------*/

unsigned int ackermann( unsigned int x, unsigned int y )
{
/* un-comment to view values of x and y within the function itself.

printf( "Ackermann(%d,%d)\n", x, y); */


if ( x == 0 )
return (1);

if ( y == 0 )
{
if ( x == 1 )
return( 2 );
else
return( x + 2 );
} /* if */
else
return ackermann( ackermann( x -1, y ), y - 1 );

} /* ackermann() */

< ========= end source code ============ >

[ Editor's Note:

Information below from Joe Celko...

One can also find ways to optimize the performance via the algebraic
properties of the function in book RECURSIVE FUNCTION THEORY by
Ann Yasuhara (Academic Press, ISBN 0-12-768950-8) ]


/*************************************************************************/
Glossary of Terms
/*************************************************************************/

AES = Application Environment System
ALGORITHM = A logical sequence of discrete steps used to solve a problem
in a finite amount of time.
DSP = Digital Signal Processor
EIA = Electronic Industries Association
FIRMWARE = System software that is stored in ROM
GEM = Graphics Environment Manager
LEX = Lexical Analyzer
POINT = 1/72 inch, used in PostScript and corresponds to the standard
"point" system used in the printing industry.
POSTSCRIPT = A page description language created by Adobe Systems Inc.
"RAPID" -
PROTOTYPE = Proof of concept. In Software - development of a preliminary
version of the software system in order to allow certain
aspects of that system to be investigated.
RECURSION = Principle of expressing an algorithm by using a simpler
version of the same algorithm in its explaination.
ROM = Read Only Memory
VDI = Virtual Device Interface
YACC = Yet Another Compiler Compiler

/*************************************************************************/
ATARI DEVELOPER INFORMATION
/*************************************************************************/

What you can buy from Atari in terms of developer documentation and
support. Contact Atari for the specific details.

Atari Corp
1196 Borregas Ave
Sunnyvale, CA 94089
USA
(408)-745-2000 (voice)

Some of the benefits:

y Several disks and approximately two thousand pages of programming
documentation.
y Atari Developer Newsletter: ATARI.RSC
y Atari Developer RoundTable support on GEnie (private)
y Atari Developer CD-ROM (coming soon)
y Book: Atari Compendium by SDS Publishing

Call or write for details.

/************************************************************************/
Sources of Information (References)

Books, Magazines and Company Information
/************************************************************************/

book: The C Programming Language (2nd edition, ANSI C)
by Brian Kernighan and Dennis Ritche
ISBN 0-13-110362-8

Prentice Hall
Englewood Cliffs, New Jersey 07632
USA

ANSI and ISO indexes/documents, EIA, Aerospace, Military, Engineering,
and Government documents. Over one million documents available.
Some documents are also available on CD-ROM.

Global Engineering Documents
15 Inverness Way East
Englewood Colorado 80112-5704
Phone 800-624-3974
Fax 303-972-2192

/***********************************************************************/
POST INCREMENT
(what is coming up in the next installment)
/***********************************************************************/

We are always looking for new articles, tricks, questions, tips and
suggestions related to programming on the Atari. Also your favorite
brain teasers (Brain Stem Rotator) problems are also needed.

* More on Advanced Computing using FLEX
* C++/Object Oriented Programming
* More on the 56K DSP by BrainStorm

The type of articles we are looking for are anything programming
related. STOS, dBMAN, C, Assembly, BASIC, Pascal, Lex, YACC, etc, etc.
This is of course a very small list.

Letters and comments are always welcome! And if you have a better
technique for solving a problem we want to hear from you. If one has a
suggestion on a particular topic that he/she would like covered please
send EMail to the editor.

Developers [Worldwide] send press releases about your products as
well. We want everyone to know about the newest developer tools
available.

/************************************************************************/
LEGAL NOTES
/************************************************************************/

Articles and letters in Atari Explorer Online Programmers' Journal
(AEO-PJ) represent the views of the authors and do not necessarily
reflect those of the publisher.

Note that all code and listings in Atari Explorer Online Programmers'
Journal (AEO-PJ) appear "as is," and AEO-PJ makes no guarantee or
warranty of their quality, performance, accuracy, or suitability for
any particular purpose. AEO-PJ assumes no responsibility or liability
to any person or entity with respect to any damage caused or alleged
to be caused by their use.

Material published in this issue may be reprinted under the following
terms only: articles must remain unedited and include the issue number
and author at the top of each article reprinted. Reprint permission
is granted, unless otherwise noted at the beginning of the article, to
registered Atari user groups and not for profit publications.

Atari Explorer Online Programmers' Journal is a service
of Atari Explorer Online Magazine.

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

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos from Google Play

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT