home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 10: Diskmags / nf_archive_10.iso / MAGS / STEN / STEN08.MSA / NEWS.TXT / GFA_TUTR.ASC < prev    next >
Text File  |  2010-04-21  |  90KB  |  2,152 lines

  1.                    GFA TUTORIAL - FROM INSIDE INFO #54
  2.                    =================================== 
  3.                          (from INSIDE INFO #49) 
  4.  
  5.                         T - Returns to this menu
  6.  
  7.  
  8.                    F1 - Introduction      F2  - Part 1
  9.  
  10.                    F3 - Part 2            F4  - Part 3
  11.  
  12.                    F5 - Part 4            F6  - Part 5
  13.  
  14.                    F7 - Part 6            F8  - Part 7
  15.  
  16.                    F9 - Part 8            F10 - Part 9
  17.  
  18.  
  19.  
  20.                                 ~~~OOOO~~~
  21.  
  22.  
  23.  
  24.       *****   *****  *****      *****  *****  *****  *****  *****
  25.       *       *      *   *      *   *  *   *  *        *    *
  26.       *       *      *   *      *   *  *   *  *        *    *
  27.       *  ***  *****  *****      *****  *****  *****    *    *
  28.       *   *   *      *   *      *   *  *   *      *    *    *
  29.       *   *   *      *   *      *   *  *   *      *    *    *
  30.       *****   *      *   *      *****  *   *  *****  *****  *****
  31.  
  32.               YOU NO LONGER HAVE AN EXCUSE NOT TO TRY IT!
  33.  
  34.     ====================== by John Hutchinson ====================
  35.  
  36.  
  37.      In the January 1989 issue of Start Magazine, published by 
  38.    Antic Publications, readers found a very pleasant surprise.  
  39.    Included on the magazine disk was one of the most successful 
  40.    commercial programs ever made for the Atari ST.  It was, in 
  41.    fact, GFA BASIC 2.0!
  42.  
  43.      While not "exactly" public domain (Antic reserves the 
  44.    rights to all programs published by their magazines), the effect 
  45.    is the same.  Thousands of Atari ST users now have immediate, 
  46.    almost zero-cost access to the second best programming language 
  47.    ever created for the ST.  Why only "second best"?  Well 
  48.    obviously, those kudos belong to GFA BASIC 3.0.
  49.  
  50.      GFA BASIC 2.0 is miles (alright, alright... kilometers)
  51.    ahead of any other BASIC for the ST and often vastly superior to 
  52.    lower level languages such as Pascal, C, and Modula II.  I'll try
  53.    to justify those claims in a moment, so stay with me.
  54.  
  55.      As is common practice, ACE-NSW is making the Start magazine 
  56.    disk available to its members via the ST public domain library.  
  57.    (As with any program published by Antic, you should own a copy 
  58.    of the magazine containing the software to be legally entitled 
  59.    to use it.)
  60.  
  61.      So why am I decidely sold on GFA BASIC?  Look at the facts:
  62.  
  63.      1)  First and foremost, like most lesser BASICs, GFA is an 
  64.    interpreted language.  Simply put, this makes it easier to use 
  65.    and takes less time to see the results of your programming 
  66.    efforts.  You use it's built-in editor (much like a word 
  67.    processor) to enter your command statements and then push two 
  68.    buttons to RUN the program.  None of this edit, compile, link, 
  69.    run business.  It's all done from the editor.
  70.  
  71.      2)  GFA BASIC supports a "structured programming" style 
  72.    which does not use line numbers.  This may seem bewildering at 
  73.    first but it makes a lot of sense.  Lower level languages such 
  74.    as Pascal, C, Modula II, and assembly don't use line numbers 
  75.    because they are a pain and lead to sloppy, difficult to manage 
  76.    and debug code.  Face it, if you have to "jump" to another part 
  77.    of the program, it's much more intuitive to use the statement 
  78.    "show_the_picture" than "GOSUB 1210"!
  79.  
  80.      3)  You can call C and assembly programs and routines 
  81.    direct from GFA BASIC whenever you wish.  When the external 
  82.    program finishes, control is passed back to your GFA BASIC 
  83.    program.  You can even pass parameters back and forth.
  84.  
  85.      4)  GFA BASIC has a very "healthy" set of commands, includ- 
  86.    ing graphics and AES functions (GFA 3.0 added over 300 new 
  87.    ones!).  If you can't do it in GFA BASIC, it probably doesn't 
  88.    need to be done in the first place!
  89.  
  90.      5)  GFA BASIC is, in a word, FAST!  Speed used to be the 
  91.    downfall of BASIC but not any longer.  As an admitedly biased 
  92.    example, check out the benchmark times below for sorting 1000 
  93.    random strings in alphabetical order:
  94.  
  95.           ST BASIC ................. 304.00 seconds
  96.           GFA BASIC V2.0 ...........  23.50    "
  97.           GFA BASIC V3.0 ...........  18.10    "
  98.           GFA BASIC V3.0 (QSORT) ...   0.82    "
  99.  
  100.      If you want your program to be even faster, you can buy the 
  101.    GFA BASIC 2.0 Compiler to convert your *.BAS files into stand- 
  102.    alone *.PRG programs (the compiler for GFA BASIC 3.0 should be 
  103.    available in February 1989).  You will find that the speed of 
  104.    compiled GFA BASIC programs compare very favourably with (if not 
  105.    surpassing) those of Pascal and C.
  106.  
  107.      6)  Absolutely no royalty fees need ever be paid for any 
  108.    commercial usage of GFA BASIC.  In fact, you don't even have to 
  109.    mention your published code was written in GFA.  There are even 
  110.    separate run-time only versions of GFA BASIC 2.0 and 3.0 which 
  111.    Michtron has placed in the public domain.
  112.  
  113.      7)  GFA BASIC is the preferred language for submissions to 
  114.    both START and ST-LOG magazines (I myself have had four articles 
  115.    and programs published in START which ALL concerned GFA BASIC).  
  116.    The *** INFO DISK *** program which you are using now to read 
  117.    this newsletter was written in GFA BASIC.
  118.  
  119.      9)  Michtron has published a series of books to help 
  120.    you learn how to use GFA to its fullest.  The book GFA BASIC 
  121.    TRAINING REBOOT CAMP is a great beginner's tutorial even if it 
  122.    does have a silly name.  Separate intermediate to advanced books 
  123.    are also available for GFA 2.0 and 3.0.
  124.  
  125.      10)  Lastly, it's just plain FUN to use.
  126.  
  127.      So if you are still using ST BASIC, do yourself a favor and 
  128.    FORMAT the disk (at least it will be worth something then).  Buy 
  129.    the GFA BASIC 2.0 disk from the ACE library.
  130.  
  131.      Whether you are a novice beginner or a seasoned programmer, 
  132.    I'm sure you will find GFA BASIC to be a real winner.  I did!
  133.  
  134.                       ++++++++++++++++++++++++++++
  135.  
  136.  
  137.                     Using GFA BASIC - Part One
  138.  
  139.                         by John Hutchinson
  140.  
  141.  
  142.     GREETINGS...
  143.  
  144.      Welcome to the first installment of "Using GFA BASIC", a new
  145.    monthly column for INSIDE INFO.  If reader response is
  146.    encouraging, each month I will try to pass along a few tips and
  147.    tricks intended to make your GFA BASIC programming efforts more
  148.    effecient, productive, and hopefully... fun!
  149.  
  150.  
  151.    WHO IS THIS COLUMN FOR?...
  152.  
  153.      Sorry, but I don't intend to make this a beginner's
  154.    tutorial series.  There are other sources of information better
  155.    suited to that task (see below).  But neither will I restrict
  156.    discussion of use only to those with considerable programming
  157.    experience.  I will initially assume that most readers of this
  158.    column are somewhat familiar with the GFA BASIC editor, and have
  159.    likely dabbled a little with other BASICs as well.
  160.  
  161.  
  162.    WHY GFA BASIC?...
  163.  
  164.      As of this writing, GFA BASIC is undoubtedly the most
  165.    popular programming language for most ST users.  It's easy to
  166.    use, fast, powerful, and very inexpensive.  This is not to say it
  167.    is best for all purposes (Assembly, C, et al, certainly have
  168.    their place) but if you only have the time or inclination to
  169.    learn one ST programming language, GFA should be it.
  170.  
  171.  
  172.     WHERE DO I GET GFA BASIC 2.0?...
  173.  
  174.      Antic Publications recently bought the distribution rights
  175.    to GFA BASIC 2.0 and included it on their December 88 Start
  176.    magazine disk.  You can get a copy of the disk from the ACE[NSW]
  177.    library but you need to purchase the magazine to legally use it.
  178.    An equally good bargain is that Antic is selling the GFA BASIC
  179.    manual for only $US9.95.  This is an exceptionally good deal so
  180.    be fair and send them the money required for the back issue and
  181.    manual to be a legal user:
  182.  
  183.                      Start
  184.                      544 Second Street
  185.                      San Francisco, CA  94107
  186.                      USA
  187.  
  188.      If you have never programmed in BASIC before but want to
  189.    learn, I recommend you purchase a copy of Michtron's book, GFA
  190.    BASIC TRAINING REBOOT CAMP by D.A. Brumleve (US$19.95).  Yes,
  191.    it's a silly title but it is quite an excellent tutorial that
  192.    doesn't treat you like an idiot yet it's not overwhelming either.
  193.    If you can't find it locally, you can order it direct from:
  194.  
  195.                      Michtron, Inc.
  196.                      576 Telegraph Road
  197.                      Pontiac, MI  48053
  198.                      USA
  199.  
  200.      Michtron also has available several other books on GFA you
  201.    might be interested in.  George Miller's new book, the GFA BASIC
  202.    REFERENCE GUIDE, VOLUME 1, is a superb, massive volume with loads
  203.    of information for new and experienced users alike.  Another is
  204.    the GFA BASIC BOOK which is a guide for advanced users.
  205.  
  206.  
  207.    WHAT ABOUT GFA BASIC 3.0?...
  208.  
  209.      GFA BASIC 3.0 is the latest version and is jam-packed with
  210.    features including over 300 NEW commands and a 600 page manual.
  211.    It retains all the good features of the 2.0 version while
  212.    improving the editor and overall run-time speed plus full AES
  213.    implementation.  If you already own GFA BASIC 2.0, I strongly
  214.    recommend you upgrade to 3.0 (US$40 for the upgrade).  Otherwise,
  215.    I recommend you start off with GFA 2.0 because it's so cheap.
  216.    This column will be written with the 2.0 user in mind, but since
  217.    3.0 is entirely downward compatible, any routines mentioned will
  218.    work fine with both versions.  [NOTE:  Michtron has just
  219.    announced availability of a NEW BASIC called HiSoft which they
  220.    claim to be even more powerful than GFA 3.0.  I hope to have a
  221.    hands-on review of HiSoft soon so stay tuned!]
  222.  
  223.  
  224.    DO I NEED THE GFA BASIC COMPILER?...
  225.  
  226.      No, but you will probably want it eventually.  Essentially,
  227.    the compiler takes your GFA BASIC source code and converts it
  228.    into a standalone executable program (*.PRG) file.  The end
  229.    result is an even faster running program that anyone can use (and
  230.    your source code is kept private as well).  The 2.0 compiler
  231.    retails for US$80.  The 3.0 compiler is not yet available.
  232.  
  233.  
  234.    GETTING STARTED...
  235.  
  236.      Now that all that rubbish is out of the way, let's get down
  237.    to business.  Load GFA BASIC and when the editor screen comes up,
  238.    press the ESCape key to put you in "immediate" mode.  Now type
  239.    the following line and press RETURN:
  240.  
  241.                      DEFLIST 0
  242.  
  243.    Now return to the editor by pressing ESCape followed by RETURN.
  244.    All this did was to change the display mode of your editor so
  245.    that all GFA BASIC reserved words will be displayed in upper case
  246.    and all others in lower case.  This will be the format I will use
  247.    in this column so it will be easier to understand if we all use
  248.    the same mode.
  249.  
  250.  
  251.    OPTIMIZING YOUR CODE...
  252.  
  253.      Let's try a little experiment.  Enter the following code in
  254.    the editor, then press SHIFT+F10 to run it:
  255.  
  256.                 a=1
  257.                 start=TIMER
  258.                 FOR i=1 TO 1000
  259.                   a=a+i
  260.                   a=a-i
  261.                   a=a*i
  262.                   a=a/i
  263.                 NEXT i
  264.                 PRINT (TIMER-start)/50;" seconds"
  265.                 PRINT FRE(0);" bytes free"
  266.  
  267.    Note the "seconds" and "bytes free" amounts then make the
  268.    following changes and try it again:
  269.  
  270.                 a%=1
  271.                 start%=TIMER
  272.                 FOR i%=1 TO 1000
  273.                   ADD a%,i%
  274.                   SUB a%,i%
  275.                   MUL a%,i%
  276.                   DIV a%,i%
  277.                 NEXT i%
  278.                 PRINT (TIMER-start%)/50;" seconds"
  279.                 PRINT FRE(0);" bytes free"
  280.  
  281.    Quite a difference, isn't it?  The whole point of this little
  282.    exercise is to demonstrate simple ways to optimize your code for
  283.    speed and memory usage.  This leads to Hutch's Optimization Rules
  284.    #1 and #2, namely... "Use INTEGER variables (those with a "%"
  285.    suffix) whenever possible" and "Use GFA's built-in integer math
  286.    functions whenever possible".  INTEGER variables operate much
  287.    faster in loops and require less memory than REAL variables and
  288.    the math functions are considerably faster too.  If your program
  289.    needs REAL numbers then by all means, use them, but only when you
  290.    have to.  Conserving memory may not seem like a big deal when you
  291.    have 1/2 to 4 Megabytes to play with but as your programming
  292.    efforts expand in complexity, it becomes important.
  293.  
  294.      There are many other ways to optimize your programs, of
  295.    course, and we will deal with some of them when appropriate.  As
  296.    a general rule of thumb, however, simply try to write your code
  297.    so it does what it needs to do in as few lines as possible and it
  298.    will generally be more efficient.  That may seem self-apparent
  299.    but many programmers seem to become "oblivious to the obvious".
  300.    This leads us to Hutch's Optimization Rule #3... "If a given
  301.    routine needs to be duplicated more than twice in a program, make
  302.    it a procedure call".  For example, if you have a program that
  303.    has the following lines repeated at several places in the code:
  304.  
  305.                      IF key$<>right_key$
  306.                        OUT 2,7
  307.                        SETCOLOR 0,7,0,0
  308.                        ALERT 1,"Wrong key,|  Dummy!|,1," Rats! ",dummy%
  309.                        SETCOLOR 0,7,7,7
  310.                      ENDIF
  311.  
  312.    it's more efficient (and elegant) to do this:
  313.  
  314.                      IF key$<>right_key$
  315.                        GOSUB wrong_key_alert        ! User messed up
  316.                      ENDIF
  317.                      '
  318.                      PROCEDURE wrong_key_alert
  319.                        OUT 2,7                      ! Ring the bell
  320.                        SETCOLOR 0,7,0,0             ! Turn screen red
  321.                        ALERT 1,"Wrong key,|  Dummy!|,1," Rats! ",dummy%
  322.                        SETCOLOR 0,7,7,7             ! Turn screen white
  323.                      RETURN
  324.  
  325.    Again, use your best judgement but if the use of procedures can
  326.    result in fewer lines of code then go for it!  You will likely
  327.    find that your code is easier to read and understand as well.
  328.    One more thing, note the use of my comments, above.  I use a LOT
  329.    of comments in my code.  If you have ever written a complicated
  330.    piece of code, put it away, then came back again after six months
  331.    and scratched your head trying to figure out what the heck you
  332.    were trying to do then you will understand why.
  333.  
  334.      I believe that's more than enough for this session.  Next
  335.    month we will talk about "structured programming" (ARGHHH!) and
  336.    perhaps demonstrate a couple of handy graphics routines.
  337.  
  338.  
  339.    HELP!!!
  340.  
  341.      Your feedback is IMPORTANT!  Send your comments, questions,
  342.    suggestions, hate mail, etc, to me via E-mail on the ACE [NSW]
  343.    BBS.  We hope to have a GFA SIG up and running on the BBS soon so
  344.    stay tuned for announcements.  
  345.  
  346.                             Enjoy,
  347.  
  348.                             <HUTCH>
  349.  
  350.       *   *   *   *   *   *   *   *   *   *   *   *   *   *   
  351.  
  352.  
  353.                     Using GFA BASIC - Part Two
  354.  
  355.                         by John 'Hutch'inson
  356.  
  357.  
  358. IS ANYONE OUT THERE???
  359. ----------------------
  360.      In the course of writing articles for newsletters, one 
  361. sometimes wonders whether or not anyone out there is actually 
  362. reading them.  In the last month, I have had very little response 
  363. to this column and absoultely ZERO input to the GFA BASIC SIG 
  364. (message area number 20) on the ACE [NSW] BBS.  To be honest, if 
  365. we don't get any positive feedback soon, then I'll recommend we 
  366. release the much needed disk space back to the Editor and Sysop 
  367. for topics of more widespread interest to members.  So if anyone 
  368. out there wishes this GFA support to continue, let me know, O.K.?
  369.  
  370.  
  371. STRUCTURED PROGRAMMING
  372. ----------------------
  373.      You hear a lot about structured programming nowadays, and 
  374. perhaps it's time that someone (me, for instance) cleared out the 
  375. cobwebs and put the issue in its proper perspective.  First of 
  376. all, what is it?  Quite simply, it is a programming style which, 
  377. when followed in a logical manner, will tend to make your programs 
  378. more understandable and easier to debug and maintain.  That's all 
  379. there is to it.  It won't make your programs faster or more user 
  380. friendly, but it can help make YOUR life as the programmer a 
  381. little less tiresome in the long run.
  382.  
  383.      The first rule in structured programming is that there are no 
  384. rules.  After all, it's YOUR program (discounting those of you who 
  385. hack for a living, of course).  What you can do though is to set 
  386. up a few guidelines for yourself and try to follow them in each 
  387. program that you write, hence establishing a sort of pattern.  For 
  388. example, here are a few guidelines that I TRY to follow:
  389.  
  390.           1)  Use a program header.  I always include a program 
  391. header which consists of a bunch of remarks at the very top of my 
  392. listing which identifies the program name, filename, date last 
  393. revised, major modifications made, and a list of bugs that still 
  394. need to be corrected.
  395.  
  396.           2)  Write your program like you are writing a story.  
  397. Have an "introduction" (initialization), "body" (main), and a 
  398. "conclusion" (finish).  Keep the main routine as short as possible 
  399. by using procedures to do the dirty work.  Put the main routine 
  400. near the beginning of your program and arrange your procedures in 
  401. a logical order, putting those less frequently used near the end.
  402.  
  403.           3)  Use one command/statement per line.  Fortunately, 
  404. GFA BASIC pretty much forces this requirement on you by not 
  405. allowing concatenation of multiple commands on a single line.  
  406. Yes, this may make your program listings longer but also makes 
  407. them SO-O-O-O-O much easier to read.
  408.  
  409.           4)  Use intuitive variable and procedure names.  The 
  410. days of 8 character long variable names are long since past.  GFA 
  411. allows variable names of up to 256 characters in length, and these 
  412. may consist of letters, numbers, underscores, etc.  Why use 
  413. "d=1.5" and "GOSUB gc" when "dollar_amount=1.5" and "GOSUB 
  414. get_colors" are so much more understandable.
  415.  
  416.           5)  Be consistent in variable names.  Use the same 
  417. variables as loop counters throughout your program, and establish 
  418. a common rule for nameing integer, real, and boolean variables.
  419.  
  420.           6)  Minimize GOTO instructions.  Note that I say 
  421. "minimize", not "eliminate".  There are times when a GOTO 
  422. instruction may, in fact, be not only appropriate but the most 
  423. efficient way to handle an exit condition.  Even so, GOTOs are 
  424. notorious for making code hard to follow so do try to use them 
  425. sparingly, if at all.
  426.  
  427.           7)  Make your code self documenting.  Each procedure 
  428. should be relatively understandable when taken by itself.  Make 
  429. liberal use of comments (remarks) to clarify what each procedure 
  430. or function does.
  431.  
  432.      Remember, these are just some of MY guidelines.  Develop a 
  433. programming style that is comfortable to YOU and stick to it.  GFA 
  434. BASIC is not near as restrictive as Pascal or Modula II but it has 
  435. a lot of features to support structured programming so use them!
  436.  
  437.  
  438. LOADING GRAPHICS SCREENS INTO GFA BASIC
  439. ---------------------------------------
  440.      One of the most common tasks faced by ST programmers 
  441. (especially for games) is the loading of a DEGAS (*.PI*) format 
  442. picture file.  While there are many ways to accomplish this in GFA 
  443. BASIC, what follows is a short standalone program with procedures 
  444. I have found to work well for this task.  The following example is 
  445. for color files but monochrome works the same way.
  446.  
  447. ' GETDEGAS
  448. ' Use the following routine to load an uncompressed, 32K DEGAS
  449. ' picture file into GFA BASIC.
  450. '
  451. ' Do this DIM statement only ONCE at the beginning of your program
  452. DIM sa%(16)                             ! Array for DEGAS palette
  453. '
  454. ' Your program goes here
  455. '
  456. ' Set a$ to the DEGAS file you wish to load.  Include proper path.
  457. a$="A:FILENAME.PI1"
  458. @get_degas                              ! GOSUB to the procedure
  459. '
  460. ' The rest of your program goes here
  461. '
  462. END
  463. '
  464. PROCEDURE get_degas
  465.   CLS                                   ! Clear the screen
  466.   HIDEM                                 ! Turn the mouse off
  467.   ' Optional "black-out" routine to turn off screen during loading
  468.   ' FOR i%=0 TO 15                    
  469.   '   SETCOLOR i%,0,0,0
  470.   ' NEXT i%
  471.   BLOAD a$,XBIOS(2)-34                  ! Load the picture
  472.   a%=XBIOS(2)-32
  473.   FOR i%=0 TO 15                        ! Read DEGAS colors
  474.     sa%(i%)=DPEEK(a%)
  475.     ADD a%,2
  476.   NEXT i%
  477.   FOR i%=0 TO 15                        ! Set the ST's colors
  478.     a=XBIOS(7,i%,sa%(i%))
  479.   Next i%
  480.   SHOWM                                 ! Turn mouse back on
  481. RETURN
  482. '
  483.      
  484.      Similarly, you may load NEOCHROME (*.NEO) format picture 
  485. files with this routine:
  486.  
  487. PROCEDURE get_neo
  488.   BLOAD a$,XBIOS(2)-128                 !  Load the file
  489.   a%=XBIOS(2)-124
  490.   FOR i%=0 TO 15                        !  Get the NEO colors
  491.     sa%(i%)=DPEEK(i%)
  492.     ADD a%,2
  493.   NEXT i%
  494.   FOR i%=0 TO 15                        !  Set the ST colors
  495.     a=XBIOS(7,i%,sa%(i%))
  496.   NEXT i%
  497. RETURN
  498. '
  499.  
  500. CHANGING SCREEN RESOLUTION ON THE FLY...
  501. ----------------------------------------
  502.      In the above examples, the DEGAS or NEOCHROME format picture 
  503. files must match the screen current resolution.  But what if your 
  504. application runs in medium resolution but you wish to display a 
  505. low resolution picture file (or vice versa).  Try this routine:
  506.  
  507. PROCEDURE switch_res
  508.   res%=XBIOS(4)                         !  Get screen resolution
  509.   ' If pix is medium & screen is low:
  510.   IF RIGHT$(a$,1)="2" AND res%<1   
  511.     VOID XBIOS(5,L:-1,L:-1,W:1)         !  switches to med res
  512.   ELSE
  513.     ' Or if pix is low & screen is medium:
  514.     IF RIGHT$(a$,1)="1" AND res%>0  
  515.       VOID XBIOS(5,L:-1,L:-1,W:0)       !  switches to low res
  516.   ENDIF
  517. RETURN
  518.  
  519.      Note the use of the XBIOS(4) call.  This simple function 
  520. returns the current screen resolution:
  521.  
  522.           0 = Low resolution color
  523.           1 = Medium resolution color
  524.           2 = High resolution monochrome
  525.  
  526.      That's it for now. Stay tuned for more hints next time.
  527.  
  528.  
  529. HELP!!!
  530. -------
  531.      Your feedback is IMPORTANT!  Send your comments, questions,
  532. suggestions, hate mail, etc, to me via E-mail or the GFA SIG on
  533. the ACE BBS.  
  534.                             Enjoy,
  535.  
  536.                             <HUTCH>
  537.  
  538.          *******************************************************
  539.  
  540.  
  541.  
  542.                   ******************************
  543.                   *                            *
  544.                   *  Using GFA BASIC - Part 3  * 
  545.                   *                            *
  546.                   *     by John Hutchinson     *
  547.                   *                            *  
  548.                   ****************************** 
  549.  
  550. GREETINGS
  551. ---------
  552.      Last month I asked for some reader feedback to gauge the 
  553. level of interest in  this column.  I'm pleased to report that I 
  554. have received several encouraging comments from ACE[NSW] members 
  555. so for the time being, "Using GFA BASIC" will continue as a 
  556. regular feature of Inside Info.  Thanks for the kudos folks!
  557.  
  558.  
  559. BACK TO BASICS
  560. --------------
  561.      Since Start magazine's recent publication of GFA BASIC v.2.0 
  562. there are a great deal of brand new GFA users out there, some of 
  563. which are attempting to learn the language without benefit of the 
  564. manual which is in short supply.  Therefore, to help get these 
  565. people started, we will digress a little this month with a quickee 
  566. introductory tutorial.  If you are a more experienced GFA user, 
  567. stick around because we will begin a series on GEM programming 
  568. next month, concentrating on the AES routines.
  569.  
  570.  
  571. THE GFA BASIC EDITOR
  572. --------------------
  573.      When you run GFABASIC.PRG from the desktop, you will enter 
  574. the editor from which all your GFA commands will be entered.  The 
  575. editor is much like a word processor and consists of an 80 column 
  576. text display (even in low res) with the following menu bar at the 
  577. top of the screen:
  578.  
  579. --------------------------------------------------------------------
  580. |Save|Save,A|Quit |New  |Blk Sta|Replace| Pg up |      |Direct|Run |
  581. |Load| Merge|Llist|Block|Blk End| Find  |Pg down|Insert| Flip |Test|
  582. --------------------------------------------------------------------
  583.  
  584.  (NOTE: Version 2's editor is shown but Version 3's is similar).
  585.  
  586. You may select any of the menu items by pointing and clicking with 
  587. the mouse or by use of the function keys (F1=Load, Shift+F1=Save; 
  588. etc).  Here is a brief rundown on the use of each item:
  589.  
  590.      LOAD (F1) - brings up a fileselector box from which you may 
  591.      load existing GFA BASIC programs (files ending in .BAS).
  592.  
  593.      SAVE (SHIFT+F1) - brings up a fileselector box from which you 
  594.      may enter the path and filename to save whatever GFA BASIC 
  595.      program is currently in memory (the editor) at the time.  You 
  596.      should always give your GFA programs a filename extension of 
  597.      .BAS so you can easily recognize them as BASIC programs.
  598.  
  599.      MERGE (F2) - brings up a fileselector box from which you may 
  600.      choose an ASCII GFA file (one saved with the "Save,A" 
  601.      command) to be merged with whatever program is currently in 
  602.      memory.  The merge will take place at whatever line the 
  603.      cursor is on when MERGE is called.
  604.  
  605.      SAVE,A (SHIFT+F2) - brings up a fileselector box from which 
  606.      you may enter the path and filename to save whatever GFA 
  607.      BASIC program is currently in memory as an ASCII file.  Since 
  608.      ASCII files are pure text they may be shown/printed from the 
  609.      desktop, merged into a word processor, etc.  You should 
  610.      always save ASCII files with a .LST extension.
  611.  
  612.      LLIST (F3) - If you have a printer connected to your ST, this 
  613.      command will allow you to get a printed listing of whatever 
  614.      program is currently in memory.
  615.  
  616.      QUIT (SHIFT+F3) - Takes you back to the desktop.  Save your 
  617.      work first!
  618.  
  619.      BLOCK (F4) - Brings up a sub-menu of block commands that let 
  620.      you move, copy, write as a text (.LST) file, print, hide, or 
  621.      delete a block of text previously defined with the START 
  622.      BLOCK and END BLOCK editor commands.
  623.  
  624.      NEW (SHIFT+F4) - Erases whatever program is currently in 
  625.      memory.  Be careful... once it's gone, it's really gone!
  626.  
  627.      BLOCK START (SHIFT+F5) - Lets you specify the beginning of a 
  628.      block of code which begins with the line the cursor is on.
  629.  
  630.      BLOCK END (F5) - Lets you specify the end of a block of GFA 
  631.      code.  The block will be highlighted and ends with the line 
  632.      directly above the line the cursor is on.
  633.  
  634.      FIND (F6) - Allows you to enter a string of text which will 
  635.      be searched for from the present cursor position to the end 
  636.      of the program in memory.  FIND is case sensitive.
  637.  
  638.      REPLACE (SHIFT+F6) - Like the FIND command, but allows you to 
  639.      replace text with other text of your choice.  REPLACE is case 
  640.      sensitive.
  641.  
  642.      PG DOWN (F7) - Moves the program listing down one page.
  643.  
  644.      PG UP (SHIFT+F7) - Moves the program listing up one page.
  645.  
  646.      INSERT (F8) - Toggles between the insert and overwrite mode 
  647.      of text entry.
  648.  
  649.      FLIP (F9) - This command allows you to switch to the output 
  650.      screen of the last previously run program.  Press any other 
  651.      key to return to the editor.
  652.  
  653.      DIRECT (SHIFT+F9) - Calls the direct mode in which GFA BASIC 
  654.      commands can be entered and carried out directly after 
  655.      pressing the RETURN key.  Return to the editor by pressing 
  656.      the ESCAPE key followed by RETURN.
  657.  
  658.      TEST (F10) - Tests the structure and integrity of all loops 
  659.      and subroutines in the current program in memory.
  660.  
  661.      RUN (SHIFT+F10) - Executes the current program in memory.
  662.  
  663.  
  664. CONTROL COMMANDS
  665. ----------------
  666.      Several additional commands can be carried out via keyboard 
  667. commands without using the mouse:
  668.  
  669.      LEFT ARROW - moves cursor one character to the left.
  670.  
  671.      RIGHT ARROW - moves cursor one character to the right.
  672.  
  673.      UP ARROW - moves cursor up one line.
  674.  
  675.      DOWN ARROW or RETURN - moves cursor down one line.
  676.  
  677.      CONTROL+RIGHT ARROW - moves cursor to end of line.
  678.  
  679.      CONTROL+LEFT ARROW - moves cursor to beginning of line.
  680.  
  681.      CONTROL+UP ARROW - scrolls program up one page.
  682.  
  683.      CONTROL+DOWN ARROW - scrolls program down one page.
  684.  
  685.      TAB - moves cursor one tab position to the right.
  686.  
  687.      CONTROL+TAB - moves cursor one tab position to the left.
  688.  
  689.      HOME - moves cursor to top of present page.
  690.  
  691.      CONTROL+HOME - moves cursor to beginning of program.
  692.  
  693.      CONTROL+Z - moves cursor to end of program.
  694.  
  695.      UNDO - cancels all changes made to a program line as long as 
  696.      the cursor has not left the line after changes were made.
  697.  
  698.      INSERT - inserts a blank line into the program at cursor.
  699.  
  700.      CONTROL+DELETE - completely deletes the line cursor is on.
  701.  
  702.      CONTROL+F - find the next occurrence of the search string 
  703.      entered in the FIND command.
  704.  
  705.      CONTROL+R - replaces the next occurrence of the search string 
  706.      entered in the FIND command with the text string entered in 
  707.      the REPLACE command.
  708.  
  709.      ESC - shifts into the DIRECT mode (same as SHIFT+F9).
  710.  
  711.      CONTROL+SHIFT+ALTERNATE - Breaks the execution of a program.
  712.  
  713.  
  714. USING THE EDITOR
  715. ----------------
  716.      Here are some basic points to remember about GFA:
  717.  
  718.      * GFA does not require archaic line numbers (thank God) and 
  719. each line's syntax is automatically checked everytime you press 
  720. the RETURN key.
  721.  
  722.      * If you make a typo, a bell will ring and an error message 
  723. will appear in the menu line at the top of the screen.
  724.  
  725.      *  GFA automatically indents your program for you to make loops and 
  726. conditions and procedures easier to read.
  727.  
  728.      * If you are using the editor in low resolution, your mouse 
  729. cursor will "disappear" about half-way across the screen.  Nothing 
  730. is wrong, that's just how they support 80 columns of text in low 
  731. resolution mode (this problem does not exist in GFA 3.0 however).
  732.  
  733.      * GFA does not allow concatenated lines.  In other words, 
  734. only one command per program line, please.
  735.  
  736.      * GFA subroutines are called PROCEDURES and must end with a 
  737. RETURN statement:
  738.  
  739.           PROCEDURE example
  740.             PRINT "This is an example PROCEDURE."
  741.           RETURN
  742.  
  743.      * Remarks must begin with the REM (or ' symbol) and be placed 
  744. at the beginning of a program line.  Comments may be placed on the 
  745. same line as a command if separated by a ! symbol:
  746.  
  747.           REM This is a remark.
  748.           ' This is a remark too.
  749.           PRINT "Hello"           !  This is a comment
  750.  
  751.      * Variable names may consist of alphanumeric characters and 
  752. the underscore _ symbol and may be up to 256 characters long.  The 
  753. assignment command, LET (i.e., LET A=2), is entirely optional.  
  754. GFA   supports multiple variable types but the most useful are:
  755.  
  756.           A  = 12345.12345678     !   real
  757.           A% = 12345              !   integer
  758.           A! = -1                 !   boolean  (TRUE or FALSE)
  759.           A$ = "HELLO"            !   string
  760.  
  761.      * Single and multi-dimensional real, integer, boolean, and 
  762. string arrays are supported.
  763.  
  764.      * Standard arithmetic operators (+,-,*,/,^) are supported 
  765. plus fast integer math functions ADD,MUL,DIV,INC,DEC plus trig 
  766. functions SIN,COS,TAN,ATN,SQR,PI and other numerical operators 
  767. MIN,MAX,INT,TRUNC,ROUND,FRAC,MOD,ODD,EVEN,TRUE,FALSE,AND,OR,XOR, 
  768. EQV,IMP, etc.
  769.  
  770.  
  771. QUICKEE TIP OF THE MONTH
  772. ------------------------
  773.      Need a simple timing routine in your programs?  Why not use 
  774. the built in TIMER function in GFA?  TIMER is a system variable 
  775. that returns the time in 200ths of a second since your computer 
  776. was turned on.  Here's a simple example of how to use it to time 
  777. something in seconds:
  778.  
  779.      ' TIMER demo
  780.      PRINT "GFA BASIC Timer Demo"
  781.      PRINT "  Press any key to start timer..."     
  782.      REPEAT
  783.      UNTIL INKEY$<>""
  784.      t%=TIMER
  785.      PRINT "  Press any key to stop timer..."
  786.      REPEAT
  787.      UNTIL INKEY$<>""
  788.      et%=TIMER-t%
  789.      PRINT "    Time elapsed = ";et%/200;" seconds." 
  790.  
  791.  
  792. THAT'S ALL FOLKS
  793. ----------------
  794.      Hope this month's article helps to get our new GFA BASIC 
  795. users off to a good start.  The last I heard was that Antic 
  796. Publications in San Francisco was sold out of the GFA 2.x manuals 
  797. so if you need a GFA reference book, I recommend the following:
  798.  
  799.    ->  For the beginner:
  800.           GFA BASIC Training Reboot Camp
  801.                by D. Brumleve and M. Marks
  802.  
  803.    ->  For the advanced user:
  804.           The GFA BASIC Book
  805.                by F. Ostrowski
  806.  
  807.    ->  Very good all around reference (good manual substitute):
  808.           GFA BASIC Programmers Reference Guide, Volume I
  809.                by G. Miller
  810.  
  811.    Each of these are about US$20-$25 and are available from:
  812.                Michtron, Inc.
  813.                576 S. Telegraph
  814.                Pontiac, MI  48053  USA
  815.  
  816. And remember, if you like what you see in GFA BASIC 2.x, you will 
  817. love the latest 3.x version, now being distributed by Antic.  And 
  818. hopefully by the time you read this, the 3.x compiler will have 
  819. been released.  Stay tuned for an upcoming review in Inside Info!
  820.  
  821.             Till next time, keep on hackin'... <HUTCH>
  822.  
  823.             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  824.  
  825.                       GFA COMMAND TABLE  (Ver 2.0+)
  826.                       ^^^^^^^^^^^^^^^^^
  827.                        (From Probe by Alf)
  828.  
  829. 1. Arithmetic Commands
  830.  
  831. ABS          ADD          ATN          BIN$          COS          DEC 
  832. DEFFN        DEFNUM       DIV          EVEN          EXP          FALSE
  833. FIX          FRAC         HEX$         INC           INT          LOG
  834. LOGIO        MUL          ODD          OCT$          PI           RANDOM
  835. RND          SGN          SIN          SQR           SUB          TAN
  836.  
  837.  
  838. 2. Graphic Commands
  839.  
  840. BOX          CIRCLE       CLS          DEFFILL       DEFLINE      DEFMARK
  841. DEFTEXT      DRAW         ELLIPSE      FILL          GRAPHMODE    LINE
  842. PBOX         PCIRCLE      PELLIPSE     PRBOX         PLOT         POINT
  843. POLYFILL     POLYLINE     POLYMARK     RBOX          SPRITE       
  844.  
  845.  
  846. 3. I/O Commands
  847.  
  848. BGET         BLOAD        BPUT       BSAVE         CHAIN           CLOSE
  849. CRSCOL       CRSLIN       EOF        FORM INPUT    FORM INPUT AS   GET
  850. HARDCOPY     INKEY$       INP        INP?          INPUT           INPUT$
  851. LINE INPUT   LIST         LLIST      LOAD          LOC             LPOS
  852. LPRINT       OPEN         OUT        OUT?          POS             PRINT
  853. PRINT USING  PSAVE        PUT        REAS          RELSEEK         SAVE
  854. SEEK         SGET         SPC        SPUT          TAB             TEXT
  855. WRITE
  856.  
  857.  
  858. 4. Disk Commands
  859.  
  860. CHDIR        CHDRIVE      DFREE       DIR           DIR$            EXIST
  861. FILES        FILESELECT   KILL        LOF           MKDIR           NAME
  862. RMDIR
  863.  
  864.  
  865. 5. Gem Commands
  866.  
  867. ALERT         BIOS        CLEARW       CLOSEW       FULLW           GEMDOS
  868. GEMSYS        INFOW       MENU         ON MENU      OPENW           TITEW
  869. VDIBASE       VDSYS       VOID         WINDTAB      XBIOS
  870.  
  871.  
  872.  
  873. 6. Structure Commands
  874.  
  875. CONT       DO..LOOP       END             ENDIF      EXIT       FOR..NEXT
  876. GOSUB      GOTO           IF..THEN..ELSE  ON BREAK   ON ERROR   ON..GOSUB
  877. PROCEDURE  REPEAT..UNTIL  RESUME          RETURN     STOP       WHILE..WEND
  878. @
  879.  
  880.  
  881.  
  882. 7.  System Commands
  883.  
  884. ARRPTR     BASEPAGE      C:             CALL         DATE$       DEFLIST
  885. DEFMOUSE   DPEEK         DPOKE          EDIT         ERR         ERROR
  886. EXEC       FATAL         FRE            HIDEM        HIMEM       LPEEK
  887. LPOKE      MONITOR       MOUSE          MOUSEK       MOUSEX      MOUSEY
  888. NEW        PAUSE         PEEK           POKE         QUIT        RESERVE
  889. SETTIME    SDPOKE        SHOWM          SLPOKE       SPOKE       SYSTEM
  890. TIME$      TIMER         TROFF          TRON         VARPTR      VSYNC
  891.  
  892.  
  893.  
  894. 8. Data Commands
  895.  
  896. ARRAYFILL  ASC           BITBLT         BMOVE        CHR$        CLEAR
  897. CLR        CVD           CVF            CVI          CVL         CVS
  898. DATA       DIM           DIM$           ERASE        FIELD       INSTR
  899. LEFT$      LEN           LET            LOCAL        LSET        MAX
  900. MID$       MIN           MKD$           MKF$         MKI$        MKL$
  901. MKS$       OPTION        RESTORE        RIGHT$       RSET        SPACE$
  902. STRING$    STR$          SWAP           TYPE         UPPER$      VAL
  903. VAL?       #
  904.  
  905.  
  906. 9. Other Commands
  907.  
  908. COLOR      REM         SETCOLOR        SOUND         WAVE
  909.  
  910.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  911.  
  912.                      Using GFA BASIC - Part 4
  913.  
  914.                         by John Hutchinson
  915.  
  916.  
  917. GREETINGS
  918. ---------
  919.      Due to a couple of requests from members, this month we will 
  920. begin looking into incorporating GEM routines in GFA BASIC.  GEM 
  921. is great stuff, but taking full advantage of all it has to offer 
  922. can become quite complicated.  Nonetheless, we will take it a 
  923. small step at a time so as not to overwhelm you (or me!).
  924.  
  925. AN INTRODUCTION TO GEM
  926. ----------------------
  927.      GEM, or Graphics Environment Manager, is the graphics 
  928. operating system built-in to your Atari ST.  It alone is 
  929. responsible for the user-friendly (ACKKK!  I hate that term!) 
  930. windows, icons, and menus that mouse lovers adore.  It is not 
  931. without its faults, of course, but its relative ease of use as 
  932. compared to a command line operating system has opened the door to 
  933. thousands of people who heretofore were intimidated by computers.
  934.  
  935.      GEM consists of two major subsystems, namely VDI (Virtual 
  936. Device Interface) and AES (Application Environment System).  These 
  937. are actually just libraries of program routines that the operating 
  938. system (or you, as a programmer) calls when needed.
  939.  
  940.      The VDI contains all the essential graphic functions needed 
  941. for drawing boxes, circles, lines, etc, that make your life as a 
  942. programmer much easier.  GDOS, GIOS, and Metafiles are all logical 
  943. components of the VDI but we won't concern ourselves too much 
  944. about VDI in this article.  Its sufficient enough to know what 
  945. it is and that its always there ready to do its thing.
  946.  
  947.      The AES, however, is of considerable more interest.  It 
  948. contains all the functions that handle windows, menus, icons, 
  949. dialog and alert boxes, etc.  These are the goodies that can give 
  950. your programs that extra flair and ease of use.  Unfortunately, 
  951. programming the AES functions is at times a daunting task.
  952.  
  953.      Fortunately, GFA BASIC comes with an assortment of AES 
  954. commands inbuilt to the language and can access all others through 
  955. procedure calls.  Let's take a look at some of the simpler AES 
  956. routines you can use in your programs with very little effort.
  957.  
  958.  
  959.      ALERT BOXES
  960.      -----------
  961.      The GFA BASIC ALERT command places a GEM (or more accurately, 
  962. AES) alert box on the screen.  An alert box is an ideal way to 
  963. provide small amounts of information to a user and receive limited 
  964. feedback in return.  For example:
  965.           _____________________________________________
  966.           |                                           |
  967.           | ------   THIS IS A SAMPLE ALERT BOX       |
  968.           | \ ?  /                                    |
  969.           |  \  /          BIG DEAL, HUH?             |
  970.           |   \/     -------   ------   ---------     |
  971.           |          | YES |   | NO |   | MAYBE |     |
  972.           |          -------   ------   ---------     |
  973.           |___________________________________________|
  974.  
  975.      The alert box consists of a bordered box centered on screen 
  976. with up to four rows of text, each row consisting of up to 30 
  977. characters each.  At the bottom of the alert box is from 1 to 3 
  978. buttons through which the user enters his response to the alert.  
  979. One of these buttons may be made the 'default' which may be 
  980. selected by the user simply by pressing the return key.  An 
  981. optional symbol (explanation mark, question mark, or stop sign) 
  982. may also appear at the left side of the alert box.
  983.  
  984.      Using the ALERT command in GFA BASIC is the easiest way to 
  985. add a bit of AES flash to your program.  For example, the sample 
  986. alert box, above, would be called by this simple command:
  987.  
  988.      ALERT 2, "THIS IS A SAMPLE ALERT BOX|      BIG DEAL, HUH?|",
  989.           1,"YES|NO|MAYBE",choice%
  990.  
  991. The syntax for the ALERT command is:
  992.  
  993.               ALERT sym,text$,default,button$,choice
  994.  
  995.      The expression "sym" defines which symbol is to appear in 
  996. your alert box.  Your symbol choices are:
  997.  
  998.           0  -  no symbol
  999.           1  -  Explanation mark (!)
  1000.           2  -  Question mark (?)
  1001.           3  -  Stop sign
  1002.  
  1003.      The "text" that you want to appear in the alert box comes 
  1004. next, separating each row (up to four) with a vertical bar 
  1005. character (|).
  1006.  
  1007.      The expression "default" specifies which button in the box 
  1008. will be highlighted for automatic selection by the user pressing 
  1009. the RETURN key.  You may have up to three buttons in your alert 
  1010. box.  Use "0" if you don't want a default button specified.
  1011.  
  1012.      The variable "choice" will contain the number of the button 
  1013. selected by the user.  In the above sample, selecting "YES" would 
  1014. set choice to 1, "NO" would be 2, and "MAYBE" 3.  For efficiency, 
  1015. the above sample used an integer variable (choice%) although a 
  1016. real number (e.g., choice) would work as well.
  1017.  
  1018.      Since alert boxes are controlled by the AES, all program 
  1019. activity halts until the box is exited by selecting one of the 
  1020. buttons.  AES takes care of screen redraws so this simple one line 
  1021. command is neat and effecient in use although quite limited in the 
  1022. amount of information it can exchange with the user.
  1023.  
  1024.      NOTE for GFA BASIC 3.x users:  Version 3.2 and 3.5 both 
  1025. possess an annoying bug when calling alert boxes.  If the mouse 
  1026. display is turned off via a HIDEM command prior to calling the 
  1027. alert box, the mouse will remain hidden when the alert box is 
  1028. displayed.  The workaround is to simply do a SHOWM just prior to 
  1029. calling any alert boxes.
  1030.  
  1031.  
  1032.      FILESELECT BOXES
  1033.      ----------------
  1034.      A fileselect box is another easy way to add AES flash to your 
  1035. program, IF you need to read or write user-specified disk files.  
  1036. When envoked, the FILESELECT command will place a standard file 
  1037. select box centred on the screen from which the user can choose 
  1038. the disk file to be actioned upon.  The syntax for the FILESELECT 
  1039. command is:
  1040.  
  1041.      FILESELECT path$,default$,name$
  1042.  
  1043.      The expression path$ is the name of the disk drive and folder 
  1044. that is to be shown when the box appears, using the standard 
  1045. hierarchical file system notation.  If no path is specified (i.e., 
  1046. a null string, "") then the current disk drive path will be used.  
  1047. Note that if using the GFA BASIC interpreter, this will be the 
  1048. path from which GFABASIC.PRG was run.
  1049.  
  1050.      The expression default$ is the name of the file, if any, that 
  1051. is to appear when the box first appears.  If the user selects "OK" 
  1052. or simply presses RETURN, this default filename will be selected.  
  1053. If you don't want a default, just use a null string again ("").
  1054.  
  1055.      The expression name$ will be the name of the file that the 
  1056. user finally selects by highlighting and selecting "OK" or by 
  1057. double-clicking.  Note that if the user selects the "CANCEL" 
  1058. button, then name$ will contain a null string.
  1059.  
  1060.      As an example, suppose you want the user to select a data 
  1061. file with the filename extension of ".DAT" from a "DATA" folder 
  1062. which resides in another folder called "WHIZBANG" on floppy disk 
  1063. A.  The fileselect command could look like this:
  1064.  
  1065.      FILESELECT "A:\WHIZBANG\DATA\*.DAT","",name$
  1066.  
  1067. The fileselect box would display only those files ending with 
  1068. ".DAT" from the "WHIZBANG\DATA" folders on disk A and no default 
  1069. file would be named.  Note that although uppercase letters are 
  1070. used in the example, they are not required as GFA will convert 
  1071. them to uppercase automatically when the command is envoked.    
  1072.  
  1073.  
  1074.      DEFINING THE MOUSE SHAPE
  1075.      ------------------------
  1076.      You don't have to be stuck with that dull, drab arrow mouse 
  1077. shape.  Besides the default arrow shape, there are 7 other shapes 
  1078. built-in to the system that you can call with the DEFMOUSE 
  1079. command.  These shapes and their corresponding shape numbers are:
  1080.  
  1081.           0    ->   Arrow
  1082.           1    ->   Double parentheses
  1083.           2    ->   Bee
  1084.           3    ->   Pointing hand
  1085.           4    ->   Open hand
  1086.           5    ->   Thin cross hairs
  1087.           6    ->   Thick cross hairs
  1088.           7    ->   Framed cross hairs
  1089.  
  1090. To change the mouse shape to a pointing hand, for instance, just 
  1091. issue this command:
  1092.  
  1093.                           DEFMOUSE 2    
  1094.  
  1095. Pretty simple, huh?  Just remember that whenever an AES function 
  1096. is called that uses the mouse (like an alert or fileselect box) 
  1097. the default mouse shape of the arrow will reappear.  When the AES 
  1098. function is finished, you'll have to redefine your mouse with 
  1099. anouther DEFMOUSE command.
  1100.  
  1101.      You can also define the mouse to be any shape you wish that 
  1102. will fit in a 16 x 16 grid bit pattern string.  The easiest way to 
  1103. do so is to make use of the public domain mouse/sprite editor, 
  1104. EDSPRITE.BAS.  This program lets you design and save your design 
  1105. to disk and even writes a ".LST" file of the implementing code to 
  1106. disk as well.  For example:
  1107.  
  1108. ' Mouse-Convert data in string
  1109. LET custom$=MKI$(0)+MKI$(3)+MKI$(0)+MKI$(0)+MKI$(2)
  1110. FOR i%=1 TO 16
  1111. LET custom$=custom$+MKI$(0)
  1112. NEXT i%
  1113. FOR i%=1 TO 16
  1114. READ foregrnd
  1115. LET custom$=custom$+MKI$(foregrnd)
  1116. NEXT i%
  1117. DATA 0,0,0,64478,35344,35344,64030,35344,35344,35806,0,
  1118.      35746,51754,43946,39094,35746
  1119.  
  1120.      After running once through the code above, the custom mouse 
  1121. shape may be envoked at any time by simply using this command:
  1122.  
  1123.                          DEFMOUSE custom$
  1124.  
  1125. EDSPRITE.BAS is very simple to use for creating custom mouse forms 
  1126. and can be used to generate sprites as well (but that's another 
  1127. topic).
  1128.  
  1129.  
  1130.      That's enough for this month.  While many of you may be 
  1131. anxious to discuss windows, menus, dialog boxes, and event 
  1132. management you must remember that these are relatively complex 
  1133. subjects and we want to do this a little at a time, OK?  But fear 
  1134. not for next month I'll show you how to create a simple yet fully 
  1135. functioning GEM menu system.
  1136.  
  1137.      If you want to learn all about using real AES dialog boxes 
  1138. with resource (*.RSC) files, I suggest you read the 3-part series 
  1139. on "Resourceful GFA BASIC" which began with the Summer 1988 issue.  
  1140. It shows you how to use a Resource Construction Set as well as 
  1141. the necessary GFA code.  The author?  Oh, some guy by the name of
  1142. John Hutchinson.  <grin>  See you next time!
  1143.  
  1144.           *******************************************
  1145.  
  1146.                      Using GFA BASIC - Part 5
  1147.  
  1148.                         by John Hutchinson
  1149.  
  1150.  
  1151. GREETINGS
  1152. ---------
  1153.      Last month we began looking into incorporating GEM routines
  1154. and discussed some very rudimentary examples.  These included 
  1155. Alert boxes, Fileselect boxes, and custom mouse shapes.  This 
  1156. month we will concentrate on how to set-up and use a drop down 
  1157. menu with GFA.  Menus can add a lot of flair to your programs but 
  1158. take heart, they are NOT difficult to create (at least under GFA).
  1159.  
  1160.  
  1161. MENU COMPONENTS
  1162. ---------------
  1163.      Let's begin by looking at what things a typical drop down 
  1164. menu system consists of:
  1165.  
  1166.      Headers... A menu usually has from one to nine menu headers 
  1167. which are displayed horizontally across the top of your screen.  
  1168. These headers are used to categorize the menu 'items' which will 
  1169. appear in vertical 'drop downs' below the headers when you drag 
  1170. your mouse cursor over them.
  1171.  
  1172.      Items... These are the lines of text which appear under a 
  1173. menu header when the mouse cursor is dragged over it.  Moving the 
  1174. mouse cursor over each menu item causes them to be highlighted and 
  1175. if the left mouse button is pressed, to be 'selected'.
  1176.  
  1177.      Desk Header...  Typically, the first or left most header is 
  1178. given the name 'Desk'.  The first item below this header is 
  1179. traditionally a credits item that will present the program's 
  1180. credits, e.g., "About this program".  Desk accessories, if 
  1181. enabled, will be presented below the credits item.
  1182.   
  1183.      Separators... These are a special form of menu items which 
  1184. consist of a line of one or more hypen or minus sign (-) 
  1185. characters which are used to help separate and distinguish between 
  1186. different items of a single header.  These are convenient in that 
  1187. GEM will not allow a separator item to be selected by the mouse.
  1188.  
  1189.      All these menu components will be held in a standard string 
  1190. array for easy access by your GFA BASIC program.
  1191.  
  1192.  
  1193. DESIGNING YOUR MENU
  1194. -------------------
  1195.      The first thing to do in building a drop down menu is to get 
  1196. a clear picture in your mind of exactly what you want the menu to 
  1197. do and how you want it to appear on screen while in use.  I 
  1198. recommend you sketch your menu's intended structure on a piece of 
  1199. paper before you begin coding it in GFA.  A little prior thought 
  1200. in this area goes a long way towards saving you considerable 
  1201. frustration in the long run.
  1202.  
  1203.      After you have your rough sketch on paper, sum the number of 
  1204. headers and menu items you intend to use.  To this sum, add a 
  1205. number equal to the total number of headers.  This will give you 
  1206. the minimum size of the string array that must be dimensioned to 
  1207. hold all the components of your menu.  HINT:  Memory is abundant 
  1208. nowadays, so unless you are really concerned about it, always make 
  1209. this array size slightly larger (by 5-10) than what you plan for.  
  1210. This way, if you decide to add another menu item later on, you 
  1211. already have space reserved for it.
  1212.  
  1213.  
  1214. CODING IT IN
  1215. ------------
  1216.      OK, for an example, let's suppose we wish to design a menu 
  1217. which will have 3 menu headers (including the 'Desk' header) and 
  1218. 14 menu items (including 2 separator items).  Thus, we will need 
  1219. to dimension our menu string array to at least 20.  Why 20 when 
  1220. all we have is a total of 17 headers and items?  Because you MUST 
  1221. include a null or empty string ("") after the last item of each 
  1222. menu header and TWO null strings after the last item of the entire 
  1223. menu.  As I mentioned above, however, to plan for future enhance-
  1224. ment we'll bump this up to 25 just to be safe:
  1225.  
  1226. '
  1227. DIM Strip$(25)                          !  String array for menu
  1228. '
  1229. '
  1230. Strip$(0)="Desk"                        !  Header
  1231. Strip$(1)=" About This Demo "           !  Item
  1232. Strip$(2)="-----------------"           !    "
  1233. Strip$(3)="1"                           !  Reserved for desk accs
  1234. Strip$(4)="2"                           !      "
  1235. Strip$(5)="3"                           !      "
  1236. Strip$(6)="4"                           !      "
  1237. Strip$(7)="5"                           !      "
  1238. Strip$(8)="6"                           !      "
  1239. Strip$(9)=""                            !  Null string
  1240. Strip$(10)="Options"                    !  Header
  1241. Strip$(11)="  Option 1 "                !  Item
  1242. Strip$(12)="  Option 2 "                !    "
  1243. Strip$(13)="-----------"                !    "
  1244. Strip$(14)="  Quit     "                !    "
  1245. Strip$(15)=""                           !  Null string
  1246. Strip$(16)="Choices"                    !  Header
  1247. Strip$(17)="  Choice 1 "                !  Item
  1248. Strip$(18)="  Choice 2 "                !   "
  1249. Strip$(19)=""                           !  Null string
  1250. Strip$(20)=""                           !  Null string
  1251. '
  1252. '
  1253. MENU Strip$()
  1254. '
  1255. '
  1256. MENU 12,2                               !  Disable "Option 2"
  1257. MENU 17,1                               !  Checkmark "Choice 1"
  1258. '
  1259. '
  1260. ON MENU  GOSUB Handle_menu              !  Check for chosen items
  1261. DO
  1262.   ON MENU                               !  The main loop
  1263. LOOP
  1264. '
  1265. '
  1266. PROCEDURE Handle_menu
  1267.   MENU OFF                         !  Disable menu temporarily
  1268.   Item%=MENU(0)                    !  Item selected
  1269.   IF Item%=1
  1270.     ALERT 0,"GFA BASIC Menu Demo| |     by Hutch|",1,"Okeydoke",D%
  1271.   ENDIF
  1272.   IF Item%=11                      !  "Option 1" chosen
  1273.     MENU 12,3                      !  enable "Option 2"
  1274.     MENU 11,2                      !  disable "Option 1"
  1275.   ENDIF
  1276.   IF Item%=12                      !  "Option 2" chosen
  1277.     MENU 11,3                      !  enable "Option 1"
  1278.     MENU 12,2                      !  disable "Option 2"
  1279.   ENDIF
  1280.   IF Item%=17                      !  "Choice 1" chosen
  1281.     MENU 18,0                      !  remove check from "Choice 2"
  1282.     MENU 17,1                      !  place check on "Choice 1"
  1283.   ENDIF
  1284.   IF Item%=18                      !  "Choice 2" chosen
  1285.     MENU 18,1                      !  place check on "Choice 2"
  1286.     MENU 17,0                      !  remove check from "Choice 1"
  1287.   ENDIF
  1288.   IF Item%=14                      !  "Quit" chosen
  1289.     END
  1290.   ENDIF
  1291. RETURN
  1292. '
  1293.  
  1294.      Note that this example code will work with either GFA BASIC 
  1295. 2.0 or 3.0.  Users of GFA 3.0 may wish to take advantage of its 
  1296. flexible CASE statement instead of all those IF-ENDIF conditions.
  1297.  
  1298.      And that's all there is to building a simple drop down menu 
  1299. under GFA BASIC.  A little prior planning and very little coding 
  1300. effort will get you underway.  For your convenience, the entire 
  1301. demo program is listed below, ready to be MERGED into your GFA 
  1302. BASIC interpretor.
  1303.  
  1304.  
  1305. NEXT MONTH
  1306. ----------
  1307.      Our discussion of GEM will continue with a brief introduction 
  1308. to windows.  "I don't do windows" but fortunately, GFA does!  
  1309. Until then, keep hackin'!
  1310.  
  1311.                              <HUTCH>
  1312.  
  1313. =================================================================
  1314.  
  1315. '  MENU DEMO for ACE[NSW]
  1316. '  August 1989, by <Hutch>
  1317. '
  1318. ' *** INITIALIZATION ***
  1319. ' First dimension an array big enough to hold all menu data
  1320. DIM Strip$(25)                          !  String array for menu
  1321. '
  1322. ' Now define each header and item in order of their appearance
  1323. Strip$(0)="Desk"                        !  Header
  1324. Strip$(1)=" About This Demo"            !  Item
  1325. Strip$(2)="------------------"          !    "
  1326. Strip$(3)="1"                           !  Reserved for desk accs
  1327. Strip$(4)="2"                           !      "
  1328. Strip$(5)="3"                           !      "
  1329. Strip$(6)="4"                           !      "
  1330. Strip$(7)="5"                           !      "
  1331. Strip$(8)="6"                           !      "
  1332. Strip$(9)=""                            !  Null string
  1333. Strip$(10)="Options"                    !  Header
  1334. Strip$(11)="  Option 1 "                !  Item
  1335. Strip$(12)="  Option 2 "                !    "
  1336. Strip$(13)="-----------"                !    "
  1337. Strip$(14)="  Quit"                     !    "
  1338. Strip$(15)=""                           !  Null string
  1339. Strip$(16)="Choices"                    !  Header
  1340. Strip$(17)="  Choice 1 "                !  Item
  1341. Strip$(18)="  Choice 2 "                !   "
  1342. Strip$(19)=""                           !  Null string
  1343. Strip$(20)=""                           !  Null string
  1344. '
  1345. MENU Strip$()                           !  Call the menu routine
  1346. MENU 12,2                               !  Disable "Option 2"
  1347. MENU 17,1                               !  Checkmark "Choice 1"
  1348. '
  1349. ' *** MAIN LOOP ***
  1350. ' Look for menu events (mouse selections)
  1351. ON MENU  GOSUB Handle_menu              !  Check for chosen items
  1352. DO
  1353.   ON MENU                               !  The main loop
  1354. LOOP
  1355. '
  1356. ' *** HANDLE MENU CHOICES ***
  1357. PROCEDURE Handle_menu
  1358.   MENU OFF                         !  Disable menu temporarily
  1359.   Item%=MENU(0)                    !  Item selected
  1360.   IF Item%=1
  1361.     ALERT 0,"GFA BASIC Menu Demo| |     by Hutch|",1,"Okeydoke",D%
  1362.   ENDIF
  1363.   IF Item%=11                      !  "Option 1" chosen
  1364.     MENU 12,3                      !  enable "Option 2"
  1365.     MENU 11,2                      !  disable "Option 1"
  1366.   ENDIF
  1367.   IF Item%=12                      !  "Option 2" chosen
  1368.     MENU 11,3                      !  enable "Option 1"
  1369.     MENU 12,2                      !  disable "Option 2"
  1370.   ENDIF
  1371.   IF Item%=17                      !  "Choice 1" chosen
  1372.     MENU 18,0                      !  remove check from "Choice 2"
  1373.     MENU 17,1                      !  place check on "Choice 1"
  1374.   ENDIF
  1375.   IF Item%=18                      !  "Choice 2" chosen
  1376.     MENU 18,1                      !  place check on "Choice 2"
  1377.     MENU 17,0                      !  remove check from "Choice 1"
  1378.   ENDIF
  1379.   IF Item%=14                      !  "Quit" chosen
  1380.     END
  1381.   ENDIF
  1382. RETURN
  1383. '
  1384.  
  1385.             *************************************************
  1386.  
  1387.                      Using GFA BASIC - Part 6
  1388.  
  1389.                         by John Hutchinson
  1390.  
  1391.  
  1392. GREETINGS
  1393. ---------
  1394.      Nice to "see" you back!  I hope everyone had an enjoyable 
  1395. holiday season and I trust you are ready to jump right back into 
  1396. our tutorial series on GFA BASIC.  If we have any new members 
  1397. reading this column, welcome aboard.  If by chance you are just 
  1398. beginning to learn how to program in GFA, don't be discouraged if 
  1399. you feel somewhat bewildered right now.  Copies of the last five 
  1400. 'Using GFA BASIC' articles are available on back issues of the 
  1401. 'Inside Info' newsletter disk, available from your ever dutiful 
  1402. librarian, Cathy Tuck.  You'll find quite a few tips in those 
  1403. earlier articles well suited for the beginner and will help you 
  1404. digest the information presented here as well.
  1405.  
  1406.  
  1407. GFA BASIC 3.0 UPDATE
  1408. --------------------
  1409.      The more I use GFA BASIC version 3.0, the more I like it.  If 
  1410. you have not yet invested in a programming language for your ST, I 
  1411. strongly suggest you snap this one up.  Version 2.0 was fast, but 
  1412. 3.0 is considerable faster and its command set has been vastly 
  1413. expanded as well.  And now that the 3.0 compiler has been 
  1414. released, you can create standalone executable programs (PRG 
  1415. files) or even desk accessories (ACC files) that are even faster 
  1416. and more capable than ever before.  If you are still using version 
  1417. 2.0, you should seriously consider an upgrade to 3.0.  The 
  1418. routines presented in this column will work in either version but 
  1419. I may occasionally describe a 3.0 specific procedure just to 
  1420. familiarize you with their differences.
  1421.  
  1422.  
  1423. DIALOG BOXES
  1424. ------------
  1425.      Yeah, yeah... I know that last time (a long time ago in a 
  1426. galaxy far, far away) I promised that we would look at window 
  1427. routines this month.  But in retrospect, I thought some example 
  1428. dialog box routines might be more appropriate to our discussion of 
  1429. GEM.  I promise that we will get around to windows soon, OK?
  1430.  
  1431.      So what is a dialog box?  It's just a little GEM goodie that 
  1432. allows you, the user, to impart information to the program.  Actually, 
  1433. the alert box we discussed last month is itself a dialog box, albeit 
  1434. a very simplistic one.  Remember, that an alert box created using GEM's 
  1435. AES routines (i.e., the ALERT command in GFA BASIC), restricts you to a 
  1436. maximum of 3 radio buttons for user input.  A dialog box, however, 
  1437. allows you a great deal more flexibility.  The user can input 
  1438. text, select a multitude of standard and radio-type buttons, among 
  1439. a host of other features.  The catch-22 is that with this 
  1440. flexibility comes complexity in creating a dialog box.
  1441.  
  1442.      Most true AES dialog boxes are created through the use of a 
  1443. separate utility program called a Resource Construction Set or 
  1444. RCS.  This utility allows the programmer to "draw" his envisioned 
  1445. dialog box on screen and "paste" the objects (buttons, editable 
  1446. text fields, icons, etc) in place and then save this information 
  1447. to disk in what is known as a resource file.  Resource files 
  1448. normally have a filename extension of RSC.  You may have seen 
  1449. these already, though you might not have known what they were for.
  1450.  
  1451.      True AES dialog boxes can add a lot of flair to your program.  
  1452. Unfortunately, you not only have to purchase a separate RCS 
  1453. program but it takes quite a bit of additional code to utilize 
  1454. resource files.  Describing the use of resources is beyond the 
  1455. scope of this article but if you are insistent, borrow the club's 
  1456. copies of START magazine issues Summer, September, and October 88 
  1457. for an in-depth tutorial series on 'Resourceful GFA BASIC'.  All 
  1458. is not lost, however, as you DO have an alternative.
  1459.  
  1460.  
  1461. PSEUDO-DIALOG BOXES
  1462. -------------------
  1463.      With GFA's graphics capability and raw speed, you can quite 
  1464. often create a pseudo-dialog box that looks and functions just 
  1465. like its more complex AES generated counterpart.  As an example, 
  1466. let's say you've written a child's program that requires the user 
  1467. to enter his/her name and identify the user's sex, boy or girl.  
  1468. You would like this to be all in one nice little box for ease of 
  1469. use.  Clearly, this is not possible in a standard alert box but 
  1470. you can create a pseudo-dialog box to handle the job easily.
  1471.  
  1472.      Included on this month's Inside Info disk is a sample routine 
  1473. which creates and manages a simple pseudo-dialog box.  It's in 
  1474. ASCII format so you can merge it into your GFA BASIC editor and 
  1475. run it.  For your convenience, it's reproduced below.  Let's look 
  1476. at the sample code to try to make this more understandable:
  1477.  
  1478. (NOTE:  This demo is set up for medium resolution color only!)
  1479.  
  1480. ' PSEUDO-DIALOG BOX EXAMPLE
  1481. ' for ACE[NSW]
  1482. ' by <HUTCH>, Jan 1990
  1483. '
  1484. DEFMOUSE 3                              !  pointing hand mouse shape
  1485. REPEAT
  1486.   CLS                                   !  clear the screen
  1487.   CLR name$,sex$,ans$                   !  clear the old variables
  1488.   my_dialog                             !  call the procedure
  1489.   '
  1490.   PRINT "The name you entered was: ";name$   !  check the results
  1491.   PRINT
  1492.   PRINT "The sex you selected was: ";sex$
  1493.   PRINT
  1494.   PRINT "Try it again (Y/N)? ";
  1495.   FORM INPUT (1) AS ans$                !  input 1 letter only
  1496. UNTIL ans$<>"Y" AND ans$<>"y"
  1497. '
  1498. ' the rest of your program would go here
  1499. '
  1500. END
  1501. '
  1502. '
  1503. PROCEDURE my_dialog
  1504.   '
  1505.   LOCAL screen$,x%,y%,k%                !  some local variables
  1506.   '
  1507.   ' First, let's save the current screen image
  1508.   SGET screen$
  1509.   '
  1510.   ' Now, let's draw the box shape itself
  1511.   DEFFILL 1,0,0                         !  define our fill color
  1512.   PBOX 220,50,420,150                   !  draw a white box, black border
  1513.   BOX 219,49,421,151                    !  make the box a little thicker
  1514.   BOX 218,49,422,151                    !  make it thicker still
  1515.   BOX 215,47,425,153                    !  put an outline around box
  1516.   '
  1517.   ' Draw the button shapes
  1518.   BOX 250,120,300,140                   !  the 'boy' box
  1519.   BOX 247,118,303,142                   !  outline it
  1520.   '
  1521.   BOX 340,120,390,140                   !  the 'girl'box
  1522.   BOX 337,118,393,142                   !  outline it
  1523.   '
  1524.   ' Add in the box text
  1525.   TEXT 288,60,"Hi there!"
  1526.   TEXT 255,70,"What's your name?"
  1527.   TEXT 285,110,"Are you a"
  1528.   TEXT 312,133,"OR"
  1529.   '
  1530.   ' Add in a line to mark the editable text field
  1531.   TEXT 239,92,"--------------------"
  1532.   '
  1533.   ' Add in the button text
  1534.   DEFTEXT ,1                            !  bold face text
  1535.   TEXT 263,133,"BOY"
  1536.   TEXT 349,133,"GIRL"
  1537.   DEFTEXT ,0                            !  normal text again
  1538.   TEXT 403,133,"?"
  1539.   '
  1540.   PRINT AT(31,11);                      !  position the text cursor
  1541.   FORM INPUT 20 AS name$                !  enter name (20 characters max)
  1542.   '
  1543.   ' Now handle the button selections
  1544.   CLR sex$                              !  same thing as sex$=""
  1545.   SHOWM                                 !  make the mouse appear
  1546.   REPEAT                                !  loop #1
  1547.     REPEAT                              !  loop #2
  1548.       MOUSE x%,y%,k%                    !  check mouse position & btns
  1549.     UNTIL MOUSEK                        !  exit when a button is pressed
  1550.     '
  1551.     IF y%>120 AND y%<140                !  is mouse in button area?
  1552.       IF x%>250 AND x%<300              !  is mouse over 'BOY'?
  1553.         sex$="boy"
  1554.       ENDIF
  1555.       '
  1556.       IF x%>340 AND x%<390              !  is mouse over 'GIRL'?
  1557.         sex$="girl"
  1558.       ENDIF
  1559.     ENDIF
  1560.   UNTIL sex$<>""                        !  until sex$=something!!!
  1561.   '
  1562.   SPUT screen$                          !  restore original screen image
  1563.   '
  1564. RETURN                                  !  all done!
  1565.  
  1566.  
  1567. CODE TAKE-APART
  1568. ---------------
  1569.      Note that the above routine is written as a procedure so it 
  1570. can be easily incorporated into your program.  The first thing the 
  1571. procedure does is define some local variables that will be used 
  1572. only by this procedure and nowhere else.  You could have a global 
  1573. variable called x% elsewhere in your program but it would not be 
  1574. changed by the LOCAL x% in the procedure.  You also save on memory 
  1575. as LOCAL variables are cleared when you exit the procedure.  LOCAL 
  1576. variables are not always needed, of course, but it's a good habit 
  1577. to get into.
  1578.  
  1579.      We don't want our dialog box to permanently screw up whatever 
  1580. is on our screen so we save the current screen image as a string 
  1581. with SGET.  Then we use DEFFILL to define our fill patterns as 
  1582. desired and draw the dialog box shape with PBOX and BOX.  Next we 
  1583. add whatever dialog box text we want and draw the buttons.  Then 
  1584. we position our text cursor just so and ask the user to input 
  1585. his/her name with the FORM INPUT AS command.  The parameter of 
  1586. '20' restricts the user to input 20 characters or less.
  1587.  
  1588.      Next, we enter a double REPEAT-UNTIL loop.  This nested loop 
  1589. (one within another) handles our mouse and button selection.  The 
  1590. first loop repeats itself forever until the variable sex$ has been 
  1591. defined as something other than "" (a null or empty condition).  
  1592. Then the second loop goes on until the user presses a mouse 
  1593. button.  If the mouse is positioned over one of the two boxes when 
  1594. a mouse button is clicked, sex$ is set appropriately and we exit 
  1595. the loop.  Finally, we restore the original screen with a SPUT 
  1596. command and RETURN from the procedure.
  1597.  
  1598.      And there you have it.  A functioning dialog box created with 
  1599. simple GFA commands.  Admitedly, this is a VERY simplistic dialog 
  1600. and more complex ones would be, well, more complex.  You could 
  1601. easily jazz this one up with a few bells and whistles, however.  
  1602. How about an exit ("OK") button?  How about using GRAPHMODE 
  1603. commands to highlight the buttons when they are selected?  How 
  1604. about a colored border around the box?  How about using 
  1605. GRAF_GROWBOX and GRAF_SHRINKBOX for special effects when opening 
  1606. and closing your dialog box.  Why not ring a bell or another sound 
  1607. when a button is selected?  And why not use blue text for 'BOY' 
  1608. and pink for 'GIRL'?  And how about... well, you get the idea.
  1609.  
  1610.  
  1611. WRAP IT UP
  1612. ----------
  1613.      Remember, the only reason a pseudo-box such as this is 
  1614. feasible is because of GFA's speed.  It just wouldn't look right 
  1615. if it took a few seconds to draw the box would it?  Of course, 
  1616. there ARE ways to speed up this example.  We could use an XBIOS 
  1617. routine to draw the box on a hidden (logical) screen in memory, 
  1618. save it to a string with the GET command, and then pop it on our 
  1619. visible (physical) screen with PUT.  This technique relies on a 
  1620. method known as page-flipping, but we'll save that for a later 
  1621. discussion.
  1622.  
  1623. Until next time, keep on 'hackin'!
  1624.  
  1625. <HUTCH>
  1626.  
  1627.  
  1628.                *           *             *
  1629.  
  1630.                      Using GFA BASIC - Part 7
  1631.  
  1632.                         by John Hutchinson
  1633.  
  1634.  
  1635. GREETINGS
  1636. ---------
  1637.      This month I thought we would discuss something a little more 
  1638. esoteric than usual, specifically, page flipping.  Page flipping 
  1639. is a technique used for certain special effects, most often for 
  1640. animation.  It gets its name from the manner in which the 
  1641. animation is perceived by the human eye.  If you take a pad of 
  1642. paper and draw a stick figure of a man on each page, altering each 
  1643. one ever so slightly, then flip through the sheets rapidly, it 
  1644. will look as if the figure is moving.  Thus the name "page 
  1645. flipping" (real tech, huh?).  It is essentially the same principle 
  1646. used in cartoon animation or any moving pictures for that matter.
  1647.  
  1648.      You can use the same trick on your ST.  In its simplest 
  1649. terms, what we want is to have TWO screens in our computer's 
  1650. memory at one time and rapidly switch the display between them, 
  1651. thus providing animation or the illusion of movement.  This is 
  1652. easily done with GFA BASIC, as shown in the following demo:
  1653.  
  1654. ' *** Page flipping demo #1 ***
  1655. '
  1656. ' First reserve some space for the alternate screen.  It's address
  1657. ' must be on a 256K boundary therefore the "/4".
  1658. DIM s%(32255/4)
  1659. '
  1660. ' Now determine the addresses of the logical and alternate screens.
  1661. screen_1%=XBIOS(3)                       ! Logical screen address
  1662. screen_2%=VARPTR(s%(0))+255 AND &HFFFF00 ! Alternate screen address
  1663. '
  1664. ' Draw a ball on screen #1.
  1665. CLS
  1666. PCIRCLE 100,100,20
  1667. TEXT 200,100,"screen #1"
  1668. '
  1669. ' Now do a "page flip" by changing pointer to alternate screen #2.
  1670. VOID XBIOS(5,L:screen_2%,L:screen_2%,-1)
  1671. '
  1672. ' Draw another ball in a different position on alternate screen #2.
  1673. CLS
  1674. PCIRCLE 110,110,20
  1675. TEXT 200,100,"SCREEN #2"
  1676. '
  1677. ' Now alternate displaying the two screens (animation).
  1678. REPEAT
  1679.   FOR i%=1 TO 10
  1680.     VOID XBIOS(5,L:screen_1%,L:screen_1%,-1)   ! Flip pointer to #1
  1681.     PAUSE 5
  1682.     VOID XBIOS(5,L:screen_2%,L:screen_2%,-1)   ! Flip pointer to #2
  1683.     PAUSE 5
  1684.   NEXT i%
  1685.   '
  1686.   VOID XBIOS(5,L:screen_1%,L:screen_1%,-1)   ! Flip pointers back
  1687.   '
  1688.   CLR ans$
  1689.   PRINT AT(20,12);"Want to see it again (Y/N)? ";
  1690.   FORM INPUT (1) AS ans$
  1691.   ans$=UPPER$(ans$)
  1692.   PRINT AT(20,12);"                             "
  1693. UNTIL ans$<>"Y"
  1694. '
  1695. END
  1696.  
  1697.  
  1698. Understandably, an animation sequence with only two frames 
  1699. (images) is not be very exciting.  You could draw many frames, 
  1700. saving each one to a particular segment of memory, but this takes 
  1701. up a LOT of memory as each screen needs 32K!  To get around this, 
  1702. we make use of the ability to swap between the logical and 
  1703. physical screens with that tricky 'VOID XBIOS(5,L:a%,L:b%,-1)' 
  1704. command.  By setting a% equal to the address of screen_1 and b% 
  1705. equal to the address of screen_2, we can actually draw on one 
  1706. hidden screen while we view the other.  Take a look at the next 
  1707. program, still quite simple, but demonstrating this technique:
  1708.  
  1709.  
  1710. ' *** Page flipping demo #2 ***
  1711. '
  1712. ' First reserve some space for the alternate screen.  It's address
  1713. ' must be on a 256K boundary therefore the "/4".
  1714. DIM s%(32255/4)
  1715. '
  1716. ' Now determine the addresses of the logical & alternate screens.
  1717. screen_1%=XBIOS(3)                         ! Logical base address
  1718. screen_2%=VARPTR(s%(0))+255 AND &HFFFF00   ! Alternate screen addr
  1719. '
  1720. ' Draw a ball on screen #1 and save it as a string image.
  1721. CLS
  1722. PCIRCLE 100,100,20
  1723. GET 80,80,120,120,c$
  1724. CLS                      
  1725. '
  1726. ' Now alternate displaying the two screens, changing during flips.
  1727. REPEAT
  1728.   FOR i%=1 TO 175 STEP 5
  1729.     VOID XBIOS(5,L:screen_1%,L:screen_2%,-1)  ! See #1, draw on #2
  1730.     VSYNC                     !  optional (avoids flicker)
  1731.     CLS                       !  clear the screen
  1732.     PUT 20+i%,20+i%,c$
  1733.     VOID XBIOS(5,L:screen_2%,L:screen_1%,-1)  ! See #2, draw on #1
  1734.     VSYNC
  1735.     CLS
  1736.     PUT 21+i%,21+i%,c$
  1737.   NEXT i%
  1738.   '
  1739.   VOID XBIOS(5,L:screen_1%,L:screen_1%,-1)   ! Flip pointers back
  1740.   '
  1741.   CLR ans$
  1742.   PRINT AT(20,12);"Want to see it again (Y/N)? ";
  1743.   FORM INPUT (1) AS ans$
  1744.   ans$=UPPER$(ans$)
  1745.   PRINT AT(20,12);"                             "
  1746. UNTIL ans$<>"Y"
  1747. '
  1748. END
  1749.  
  1750.  
  1751.      Note the use of the VSYNC commands in the above code.  All 
  1752. the VSYNC command does is hold changing the screen until the 
  1753. beginning of the vertical blank interrupt.  That's techo talk for 
  1754. "reducing flicker".  It does have a drawback in that it tends to 
  1755. slow things down quite a bit.  To see how much, comment out the 
  1756. VSYNC commands and try the sample code again.  You'll notice the 
  1757. animation runs much faster but with a little more screen flicker.  
  1758. The choice is up to you whether or not to use VSYNC.  It all 
  1759. depends on your application.
  1760.  
  1761.      One important point you need to remember is to always change 
  1762. the logical and physical screen pointers back to the original 
  1763. values so that "what you see is what you get".  If you don't, your 
  1764. commands will continue going to the hidden screen instead of the 
  1765. visible one.  That can get confusing might quickly!
  1766.  
  1767.      I should mention that there are a number of ways to 
  1768. accomplish page flipping but I use the techniques shown above most 
  1769. often as they prove to be the most memory efficient (the disk 
  1770. newsletter **InfoDisk** program uses page flipping extensively).
  1771.  
  1772.      As you can see, these are VERY simple demonstrations, but 
  1773. perhaps you get the idea.  If it all seem confusing right now 
  1774. (and it should be) don't sweat it.  You really don't need to know 
  1775. WHY it works, just HOW.  With a little experimentation, you will 
  1776. soon come to understand how to get the most out of page flipping.
  1777.  
  1778.      Til next month.... keep on hackin'!
  1779.  
  1780.                              <HUTCH>
  1781.  
  1782.            *********************************************
  1783.  
  1784.  
  1785.                      Using GFA BASIC - Part 8
  1786.  
  1787.                         by John Hutchinson
  1788.  
  1789.  
  1790. GREETINGS
  1791. ---------
  1792.      This month we will take a break from our discussion of GEM 
  1793. and related techniques in order to take a look at a few more 
  1794. practical procedures that can be used in most any program.  I'd 
  1795. like to thank our editor, Greg Smith, for the suggestion for this 
  1796. month's topic.  Readers' feedback is always appreciated!
  1797.  
  1798.  
  1799. ANY COLOR YOU WANT... AS LONG AS IT'S BLACK
  1800. -------------------------------------------
  1801.      How many times have you used a program on your ST only to 
  1802. find that when you exited the proggy that your desktop colours had 
  1803. changed, usually to something billious?  This is a common problem 
  1804. with many public domain programs that were, well, let's be honest 
  1805. here, just not written very well.  You may have come across the 
  1806. same problem in a program you have written yourself.  No worries, 
  1807. for you will be amazed at how EASY it is to avoid "MUDS" (Messed 
  1808. Up Desktop Syndrome) in just a few short lines of code.
  1809.  
  1810.      But first, a little background info on how the ST manages all 
  1811. those 512 wonderful colours it's capable of producing.  In low 
  1812. resolution, the ST can display any 16 of those 512 colours at one 
  1813. time (without resorting to software tricks as in SPECTRUM 512).  
  1814. In medium resolution, the choice narrows to any 4 colours and in 
  1815. high resolution you are stuck with good old black and white.  You, 
  1816. the programmer, decide which colours you want displayed in low and 
  1817. medium resolution modes.  This colour choice is known as the ST 
  1818. colour palette.  At the desktop, you can adjust these colours to 
  1819. your liking via Atari's Control Panel Accessory.  Among other 
  1820. things, it controls the intensity of your ST's three primary 
  1821. colours of RED, GREEN and BLUE from which ALL those 512 possible 
  1822. colours are derived.
  1823.  
  1824.      For example, setting each primary colour to a value of 0 
  1825. (minimum intensity) yields BLACK.  Conversely, setting each to its 
  1826. maximum setting of 7 yields WHITE.  Set RED to 7, GREEN to 6 and 
  1827. BLUE to 0 gives you a bright YELLOW colour.  Set RED to 6, GREEN 
  1828. to 2 and BLUE to 5 yields a vile purple hue.  By juggling the 
  1829. values of each colour, you can get up to 512 different colour 
  1830. combinations (8 * 8 * 8 = 512).  Each colour in our palette can 
  1831. then be described by the amount of RED-BLUE-GREEN in its makeup.  
  1832. Therefore, WHITE is 777, BLACK is 000, pure RED is 700, etc.  
  1833. These values are stored in the ST's colour registers (16 of 'em).
  1834.  
  1835.      OK, so how do you put this knowledge to work for you?  Let's 
  1836. assume you have a program which displays different colours using 
  1837. GFA's SETCOLOR command.  It works find and dandy but you don't 
  1838. want it to alter the desktop colours.  Here's how to avoid it:
  1839.  
  1840.      Near the beginning of your program or in your initialization 
  1841. routine, include the following line:
  1842.  
  1843.         DIM palette%(15)
  1844.  
  1845.      This simply dimensions an integer array to 16 (0-15) places.
  1846.  
  1847.      Next, gosub to the following procedure:
  1848.  
  1849.         PROCEDURE Save_palette           
  1850.           FOR i%=0 TO 15
  1851.             palette%(i%)=XBIOS(7,W:i%,W:-1)
  1852.           NEXT i%
  1853.         RETURN
  1854.  
  1855.      XBIOS(7) is a special operating system routine which sets or 
  1856. determines the value of a given colour register.  What this 
  1857. routine does is look at the desktop's colour registers and saves 
  1858. them to the integer array palette%().
  1859.  
  1860.      OK, so now you can go ahead and change colours in your 
  1861. program to your hearts content.  But... before you exit or end 
  1862. your program, gosub to the procedure shown below first.
  1863.  
  1864.         PROCEDURE Restore_palette
  1865.           FOR i%=0 TO 15                 
  1866.             SETCOLOR i%,palette%(i%)
  1867.           NEXT i%
  1868.         RETURN
  1869.  
  1870.      See what we just did?  We restored the colour registers to 
  1871. the values of the original desktop colour palette.  Simple, eh?  
  1872. Ah, but what if you are using MEDIUM resolution?  There are only 4 
  1873. colour registers involved then, right?  Well, not really.  It's 
  1874. just that only the first 4 registers are used.  So while you could 
  1875. change the FOR-NEXT loops shown above to read from 0 to 3 instead 
  1876. of 0 to 15 it 'doesn't matta' because the other 12 registers will 
  1877. just be ignored anyway.  So you can use the above routines for 
  1878. any screen resolution.
  1879.  
  1880.  
  1881. HOLY DESK ACCESORY, BATMAN!!!
  1882. -----------------------------
  1883.      One of the problems with GFA BASIC 2.0 rears it's ugly head 
  1884. when your program calls a desk accessory.  Oh, it usually works 
  1885. alright.  It's just that when you close the accessory, you are 
  1886. usually left with a big gaping "hole" where the accessory was!  
  1887. Actually, this "hole" is just a portion of the screen which was 
  1888. not properly updated when the accessory was closed allowing a 
  1889. background colour to show through.  Not a devastating bug, but an 
  1890. unsightly one anyway.  Well, GFA BASIC 3.0 pretty much cured this 
  1891. problem but there is an EASY fix for 2.0 users.
  1892.  
  1893.      Just before the desk accessory is called, save the current 
  1894. screen with a command such as:
  1895.  
  1896.           SGET screen$
  1897.  
  1898.      This saves the current screen data in a 32000 byte string.
  1899.  
  1900.      Then allow the desk accessory to be called up, used, and 
  1901. closed.  Immediately after closing the desk accessory, get rid of 
  1902. the "hole" left behind by restoring the entire screen with:
  1903.  
  1904.           SPUT screen$
  1905.  
  1906.      Sure, this may be a "sledge hammer" approach, but it works 
  1907. and it's so fast as to be unnoticeable!  Sometimes the best 
  1908. solution IS the easiest too!  (I still recommend GFA 3.0 though).
  1909.  
  1910.  
  1911. BUFFER STUFFER
  1912. --------------
  1913.      As you may or may not know, the ST has a keyboard buffer.  
  1914. This is a tiny bit or memory which holds your most recent 
  1915. keystrokes (up to 256 I think).  This is usually a good idea in 
  1916. that it allows the ST to keep up with you light speed typists.  
  1917. However, it can lead to problems in programs you write which 
  1918. requires user input of some kind.
  1919.  
  1920.      For example, at some point in your program you may ask the 
  1921. user to "Press any key to continue".  If the user has not pressed 
  1922. any key up to that point, all should go according to plan.  But if 
  1923. he or she fell asleep with their head on the keyboard, that old 
  1924. keyboard buffer will be plumb full and ZAP right through your user 
  1925. friendly prompt!  Again, an easy fix can be gained through the use 
  1926. of another XBIOS call.  Immediately before you want the user to 
  1927. enter something at the keyboard, issue this command:
  1928.  
  1929.           LPOKE XBIOS(14,1)+6,0
  1930.  
  1931.      What's it do?  Well, this is your all purpose "Buffer 
  1932. Stuffer" command.  It fills the buffer with "null" values (0) or 
  1933. in other words, it erases it!  So now the user can enter in his or 
  1934. her response without having to worry about earlier accidental 
  1935. keystrokes messing things up.
  1936.  
  1937.      OK, that's all well and good.  But what if you want to know 
  1938. what the last keystroke was that the user made?  You may not know, 
  1939. but the keyboard buffer sure does.  To find out, just do this:
  1940.  
  1941.           key%=LPEEK(XBIOS(14,1)+6)
  1942.  
  1943.      The integer variable key% will now hold the keyboard value of 
  1944. the last key the user pressed.  Keep in mind that this is NOT the 
  1945. ASCII value (A=65, B=66, etc).  This is the KEYBOARD value which 
  1946. is very different and will require some experimentation on your 
  1947. part to fully understand.
  1948.  
  1949.  
  1950. RESOLUTION REVOLUTION
  1951. ---------------------
  1952.      I've mentioned this one before but it's so handy and so 
  1953. simple it bears repeating again.  To find out what resolution the 
  1954. program is currently in, use our old friend XBIOS(4):
  1955.  
  1956.           res%=XBIOS(4)
  1957.  
  1958.      If res%=0 you are in LOW resolution; 1=medium and 3=high.  
  1959. Yes, you can even change the resolution if you wish although it 
  1960. may cause you fits if you are using GEM routines in your program.  
  1961. I told you how to do this back in PART ONE of this series so dig 
  1962. it out or get a copy from the ACE BBS or PD Librarian if curious.
  1963.  
  1964.  
  1965. CHECK OUT?() THE PRINTER
  1966. ------------------------
  1967.      Have you written or used a program that requires use of a 
  1968. printer?  What does the program do if you try to print something 
  1969. from it and you forgot to turn the printer on?  Does it give you a 
  1970. nice error message (politely of course) or does it just sit there 
  1971. waiting for the ST to realize something went wrong?  Well you can 
  1972. ensure the former and avoid the latter with a very simple but 
  1973. often overlooked GFA command called OUT?().  All it does is send a 
  1974. single byte to a specified peripheral (your printer, keyboard, 
  1975. RS232 port, MIDI port, monitor, etc) and determines its status.  A 
  1976. returned value of -1 (meaning TRUE) indicates the peripheral is 
  1977. ready.  A value of 0 (FALSE) means it is not ready.  Here's an 
  1978. example routine:
  1979.  
  1980.           PROCEDURE check_printer
  1981.           ' *** Makes sure printer is turned on and online
  1982.             REPEAT
  1983.               IF OUT?(0)=0
  1984.                 ALERT 3,"| Please place your | | printer on-
  1985. line.|",1," OK | CANCEL ",d%
  1986.               ENDIF
  1987.             UNTIL OUT?(0)=TRUE OR d%=2
  1988.           RETURN
  1989.  
  1990.      The OUT?() command has a sister command known as INP?().  
  1991. Logically enought,the INP?() command READS a single byte from a 
  1992. peripheral device.  It's most common use is shown below:
  1993.  
  1994.           PRINT AT(1,1);"Please press any key"
  1995.           ~INP(2)
  1996.           PRINT AT(1,3);"Thank you"
  1997.  
  1998.      The "~" symbol is short for "VOID".  What this means is to 
  1999. read the value and then throw it away.  Sounds dumb at first but 
  2000. remember, we didn't care WHAT key the user pressed.  We just 
  2001. wanted to know WHEN he did so!  What do the numbers in parentheses 
  2002. following the OUT? and INP? commands mean?  Glad you asked.  They 
  2003. represent the device number according to the chart shown below:
  2004.  
  2005.                0    Printer
  2006.                1    RS232 Serial Port
  2007.                2    Keyboard
  2008.                3    MIDI Port
  2009.                4    Keyboard Processor
  2010.                5    Monitor
  2011.  
  2012.  
  2013. ACE[NSW] BULLETIN BOARD SYSTEM
  2014. ------------------------------
  2015.      If you own a MODEM and have not checked out the ACE[NSW] BBS 
  2016. then you are definitely missing out!  Andrew Davies and Swavek 
  2017. Jabrzemski and several others have put a lot of effort into the 
  2018. system to make sure it offers something for everyone.  It's 
  2019. available 24 hours a day; has the latest PD software available for 
  2020. downloading; local, national and international message areas; on-
  2021. line games; trading post and much, much more.  We even have a 
  2022. special section just for programming hints.  Give the system a 
  2023. call at (02) 664-1303 right now and check it out!
  2024.  
  2025.      If you don't have a MODEM, then GET one.  It's the only way 
  2026. to have the most fun you'll ever get for a 30 cent phone call! 
  2027.  
  2028.  
  2029. MENU BUILDER UTILITY
  2030. --------------------
  2031.      Back in 'Inside Info #44' in 'GFA Part 6' we discussed an 
  2032. easy way to create drop-down GEM menus in GFA BASIC.  Well, Mr. 
  2033. W.J. Sanderson of Haymarket, NSW asked if there was a utility 
  2034. available to make menu creation just a little bit easier.  I'm 
  2035. happy to report that indeed there is such a utility!  It's called 
  2036. 'MENU BUILD' and was written by David Plotkin, a frequent 
  2037. contributor to Antic's START magazine.  Although somewhat limited 
  2038. in the number of menu items it supports, it is extremely easy to 
  2039. use.  It is available on the ACE[NSW] BBS or from Cathy Tuck, the 
  2040. club PD software librarian.  There is a wealth of superb public 
  2041. domain programs available in the library.  Be sure to check out 
  2042. the update in this issue and see or call Cathy for more info.  You 
  2043. can even order your PD selections through the mail by using the 
  2044. order form on this disk.  Make use of the PD library!
  2045.  
  2046.  
  2047.      Til next month... keep on hackin'!
  2048.  
  2049.                              <HUTCH>
  2050.  
  2051.             **********************************************
  2052.  
  2053.  
  2054.                      Using GFA BASIC - Part 9
  2055.  
  2056.                         by John Hutchinson
  2057.  
  2058.  
  2059. GREETINGS
  2060. ---------
  2061.      News from Germany is that a whole new series of GFA BASIC
  2062. modules is about to be released from GFA Data Media, the European
  2063. distributor for all GFA products.  Unsure at this time if a
  2064. totally revamped version of GFA BASIC itself will be forthcoming
  2065. but it wouldn't surprise anyone if it did appear.  Rumour has it
  2066. that the "new" GFA will contain much improved commands and
  2067. functions for accessing the special sounds and graphics
  2068. capabilities of the STe machines as well as earlier STs.  Hmmm,
  2069. rather sounds like a STOS competitor doesn't it?  When we we see
  2070. these goodies here in Australia?  Well, I'm not holding my breath
  2071. but I hope it will be soon.
  2072.  
  2073. READING A DISK DIRECTORY
  2074. ------------------------
  2075.      GFA includes a number of handy commands and functions to help
  2076. you deal with disk directories, pathnames, and such stuff.  If
  2077. your program needs to write a large data file to a floppy,
  2078. wouldn't it be nice to check to see if the file will FIT on the
  2079. disk BEFORE attempting to write to it?  You can easily check to
  2080. see how much free space exists on a given disk using the DFREE(n)
  2081. command where n=the number of the drive you wish to check.  You
  2082. can set n to a value from 0 to 15 where 0 is the standard drive
  2083. and 1 to 15 is for disk drives A through O.
  2084.  
  2085.      Other directory related commands that come in very handy are
  2086. CHDRIVE (changes the current drive); DIR$(n) (shows the current
  2087. path of a disk); CHDIR (changes the current directory); DIR and
  2088. FILES (show or print the contents of the current drive); MKDIR and
  2089. RMDIR (make and remove directories/folders from a disk); EXIST(n$)
  2090. (looks to see if a given filename exists on the disk);  NAME
  2091. (names/renames disk files); and KILL (deletes disk files).
  2092.  
  2093.      These commands are all well and good but what if you need to
  2094. read a disk directory into a string for later display or
  2095. manipulation?  Sorry, but the commands DIR$ and DIR don't do that.
  2096. Perhaps the next version of GFA will include a simple one-shot
  2097. command but for now, you can make use of a GEMDOS function and the
  2098. ~FSETDTA() command.  Whenever you need to read (and store) the
  2099. contents of a given disk directory, just use the routine
  2100. demonstrated in the following example:
  2101.  
  2102.  DIRSTRNG.LST
  2103.  
  2104.  This program demonstrates the use of ~FSETDTA [GEMDOS(26)] to
  2105.  read a disk directory into a character string.
  2106.  
  2107. dir("A:\","*.*")              !  Specify the path & mask you want
  2108. PRINT "Files:"'file_count&
  2109. FOR count&=1 TO file_count&
  2110.   PRINT file$(count&),length%(count&)
  2111. NEXT count&
  2112.  
  2113. PROCEDURE dir(path$,mask$)
  2114.   DIM file$(300),length%(300)
  2115.   ABSOLUTE length%,BASEPAGE+154
  2116.   ~GEMDOS(26,L:BASEPAGE+128)
  2117.   search$=path$+mask$+CHR$(0)
  2118.   finished&=GEMDOS(78,L:V:search$,0)
  2119.   DO UNTIL finished&
  2120.     file$=CHAR{BASEPAGE+158}
  2121.     INC file_count&
  2122.     file$(file_count&)=file$
  2123.     length%(file_count&)=length%
  2124.     finished&=GEMDOS(79)
  2125.   LOOP
  2126. RETURN
  2127.  
  2128.  
  2129. AND A FOND FAREWELL...
  2130. ----------------------
  2131.      That's all from my end, folks.  Try as I might to keep a low
  2132. profile, my ruse has been discovered and I am being recalled back
  2133. to work in the United States.  My membership in A.C.E. has been
  2134. but one of the highlights of my all too short stay in this
  2135. fabulous land we lovingly call Oz.  Many thanks to all those
  2136. friends and associates who have made me feel so welcome here, and
  2137. taught me what "mateship" was really all about.  I hope this
  2138. column has been of some minor help (or at least amusement) to
  2139. those interested in GFA BASIC.
  2140.  
  2141.      Last but not least, enjoy your Atari computer, but don't
  2142. forget your families in the process... ya gotta have your
  2143. priorities in the right place!
  2144.  
  2145.      And remember... keep on hackin'!
  2146.  
  2147.                              <HUTCH>
  2148.  
  2149.  
  2150.            ****************************************
  2151.  
  2152.