

     ICTARI USER GROUP              ISSUE 19                 February 1995

         ___   ______     ___       _________   _________   ___
         \__\  \   __\    \  \__    \______  \  \   _____\  \__\
           ___  \  \       \  __\     _____\  \  \  \         ___
           \  \  \  \       \  \      \  ____  \  \  \        \  \
            \  \  \  \_____  \  \____  \  \__\  \  \  \        \  \
             \  \  \       \  \      \  \        \  \  \        \  \
              \__\  \_______\  \______\  \________\  \__\        \__\

                     *   m   a   g   a   z   i   n   e   *

     =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                       I C T A R I   U S E R   G R O U P
       63 Woolsbridge Road, Ringwood, Hants, BH24 2LX   Tel. 0425-474415
     =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

                              INDEX FOR ISSUE 19
                              ==================

     ASSEMBLY        Various Falcon specific assembler routines.
                     Joystick reading routines.
                     'Thermometer' progress display code.

     C               GEM Tutorial by J White. Part 9.
                     Text packing using Huffman coding.

     GFA             AutoZest (GFA Interface Creation Utility)
                     GFA Programming Tricks and Tips.

     STOS            Mad Bomber game code.
                     Routines to draw Alert boxes and work out time/date.

     PASCAL          More small programs.

     MISC            Desktop .INF file information.
                     More information on GIF image format.
                     Current membership list.

     In next months issue of ICTARI (this may change) :-

     ASSEMBLY        Using Calamus fonts in user programs.
                     Screen raster routines.
                     Making CPX accessory files.

     C               GEM Tutorial by J White. Part 10.
                     Questions and Answers file.

     GFA             Football game.

     BASIC           Disabling some menu items from Basic.

     STOS            STOS fix code for different TOS versions.

     PASCAL          Miscellaneous example programs.

     MISC            GIF/TIFF file information.


     For future issues :-

     Polyline drawing routines in machine code.
     Bezier curve drawing routines.
     Picture compression routine for IMG pictures.
     HP DeskJet/LaserJet compression routines (Mode 2 TIFF).
     Picture switching techniques.
     Printer driver code for printing mono/colour images.
     Sorting algorithms.
     Using the BitBlit routines.
     Code for using the File Selector.
     Overscan techniques.
     STOS sprites.
     ----------------------------------------------------------------------
                                   EDITORIAL
                                   =========
     ARTICLE FORMATS
     ---------------
     As we have had quite a few  more  members in recent months I thought I
     would just mention again for their benefit  that if you send in a text
     file for publication it would  help  me  if  it  was in Protext format
     since that is the WP I  use  to  compile  these  disks. If this is not
     possible then a standard ASCII file will be quite OK.

     CORRECTIONS
     -----------
     The GEM Macro information file (ICTARI  18) should be amended as shown
     below.

     The 'rsrc_obfix' function  in  the  AES  Resource  Library  section is
     incorrect, the ENTRY parameter 'object' should read as follows : -

             object = The number of the object to be converted

     Thanks to John Logan for  that.  Also  in  the VDI Attribute Functions
     section, the vsl_udsty heading should read :-

             Set user defined line style.

     but I'm sure you had already worked that one out.

     TELEPHONE NUMBERS
     -----------------
     As you all know everyones telephone number changes on April 16th. Most
     codes just have a 1 inserted  after  the initial 0 although some codes
     will change completely. I will  update  the membership list next month
     but if your number is  one  that  changes radically, perhaps you could
     let me know.

     ----------------------------------------------------------------------
                                CORRESPONDENCE
                                ==============
     To:  Peter Hibbs
     From: Keith Baines

     Disabling menu entries when an accessory is opened.

     I don't know how  the  HiSoft  editors  handle  this;  they have other
     non-standard features like  sub-menus  as  well.  However,  there is a
     fairly straightforward way  of  checking  whether  a  program's window
     is on top, which is as follows:

     -   include a short (e.g. 10 millisecs) timer event in the
         evnt_multi call.

     -   whenever this is called, use wind_get sub-function 10 to get
         the handle of the current top window, compare this with the
         program's own window handle(s) and adjust the menu as necessary.

     I've  included  a  short  example   program  (MENUDEMO.BAS).  This  is
     written in HiSoft Basic,  but  uses  the  AES  window functions rather
     than  the  built-in  Basic   window   system,   so  should  be  easily
     translated into other languages.

     There are two extra tricks:

     -   we can ignore timer events which happen in the same evnt_multi
         call as another event.

     -   the program uses a flag to keep track of whether it thinks its
         window is on top; this cuts down the processing done for the
         timer event.

     */ Thanks for the info, more on this subject next month.  ICTARI /*
     ----------------------------------------------------------------------
     To: Dick Teuber
     From: Keith Baines

     Embedded Resource Files

     In assembler, the obvious way to embed a resource file in a program is
     simply to include it as a binary (the INCBIN directive in Devpac 3).

     The problem with this  is  that  it  needs  some  quite tricky code to
     find and fix up all  the  pointers  (which  start  off as offsets from
     the start of the file).  An  easier  way  is  to  convert the RSC file
     into assembler source code (mainly  lots  of  DC.W statements) and let
     the assembler deal  with  the  addresses.  This  also produces shorter
     code.

     The only other fixup needed is to convert object co-ordinates from the
     character/offset format in which they are  stored in the RSC file into
     screen positions for  the  current  resolution.  GEM  provides the AES
     function rsrc_obfix for this purpose;  it  has  to  be called once for
     each object in the resource file.

     I've included a simple  example  program  to  show  how a conventional
     program with an external  resource  file  can  be  converted to use an
     embedded resource.

     demo1.s is the conventional program with an external resource
     demo2.s includes its resource data as assembler source

     I wrote a utility to  convert  RSC  files  into  assembler a while ago
     and have included a copy with its (HiSoft Basic) source.

     */ Thanks, we will be publishing this code later. ICTARI /*
     ----------------------------------------------------------------------
     To: Dick Teuber
     From: J I Logan

     INCORPORATION OF  *.RSC FILES INTO *.PRG FILES

     OUTLINE

     1. Insert the RSC file into the programme source file.

     2. At run-time, convert pointers  in  the  RSC file (which are offsets
     relative to  the  beginning  of  the  RSC  file)  to  absolute  memory
     addresses.

     3. At  run-time,  convert  object  heights  and  widths  from  the RSC
     dimensions of  character heights and widths to screen pixels.


     DETAILS

     INSERTING THE RSC FILE. You cannot simply import a large hex file into
     a source file. It  must  be  formatted  in  some  way  e.g. using dc.w
     statements in assembler or defining it as an array. Examples:

     label    dc.w    $0000,$0042,$0042,$0042,   etc (assembler)

     rsc[0]:=0; rsc[1]:=66; rsc[2]:=66; rsc[3]:=66; etc. (Modula-2)

     Clearly it would be very  laborious  to  construct these statements by
     hand. Chris Greening  has  written  CONVERT.PRG   (available on Ictari
     disk 18) which converts any  file  into dc.w statements. C programmers
     will have to determine the format best suited to that language.


     ADJUSTING THE POINTERS. I do not  intend  to  explain the working of a
     RSC file in detail but the  RSC  file has four consecutive components.
     The first is the header consisting  of  the first 18 words (numbered 0
     to 17). The second is the  data area containing secondary and tertiary
     structures (tedinfos, bltblks, strings,  graphic  data etc). The third
     is the object list and  the  last  is  the  tree  list. The data area,
     object list and tree list are not of fixed size.

     Each file contains at least one  tree  and each tree contains at least
     one primary structure called an  object.  There are thirteen different
     types of object. Each object is 12  words long (numbered 0 to 11). The
     type number is found in the low  byte  of  word 3 (ie byte 7). In most
     objects, longword 3 (ie words 6 and 7) points to a secondary structure
     in the data area of the RSC file. This secondary structure may be self
     contained or may itself contain  pointers  to tertiary structures. The
     remaining objects are self contained and  object  words 6 and 7 do not
     contain a pointer  but  rather  information  such  as  colour etc. The
     object types are discussed below.

     Object types 20  (g_box),  25  (g_ibox)  and  27  (g_boxchar) are self
     contained and do not  point  to  any  other  structure. No changes are
     required.

     Object types 26 (g_button), 28 (g_string)  and 32 (g_title) point to a
     self contained secondary  structure  (their  text  string). The object
     pointer must be converted to an absolute address.

     Object  types  21  (g_text),  22  (g_boxtext),  29  (g_ftext)  and  30
     (g_fboxtext) point to a tedinfo  structure.  The first three longwords
     in the tedinfo structure point  to tertiary structures (text, template
     and validation strings).  The  object  pointer  and  the three tedinfo
     pointers must be converted to absolute addresses.

     Object type 23  (g_image)  points  to  a  bitblk  structure. The first
     longword in the bitblk structure  points  to a tertiary structure (bit
     image). The object pointer and the bitblk pointer must be converted to
     absolute addresses.

     Object type 31 (g_icon)  points  to  an  iconblk  structure. The first
     three longwords in the iconblk  structure point to tertiary structures
     (icon mask, icon data  and  text).  The  object  pointer and the three
     iconblk pointers must be converted to absolute addresses.

     Object type 24 (g_progdef)  points  to  an  applblk structure. The two
     longwords in  the  applblk  structure  point  to  tertiary  structures
     (programme code and parmblk). The  parmblk  has two longword pointers.
     The object pointer, the two  applblk  pointers  and presumably the two
     parmblk pointers must be converted to absolute addresses.

     Each of the above pointers contains an offset or displacement IN BYTES
     from the beginning of the RSC file. It is a simple matter to determine
     the absolute address of the  beginning  of  the  RSC file after it has
     been loaded at run-time. The addition  of  the absolute address of the
     beginning of the RSC file to the  offset from the beginning of the RSC
     file converts the pointers to absolute addresses. Because the absolute
     address is only known at run-time,  the programme must contain code to
     adjust the pointers.

     Since all the objects are grouped together, it is easy to start at the
     beginning of the object list and process each object in turn until the
     last object has been dealt with. I have listed below the outlines of a
     suitable procedure (FixObject). NOTE the pointers in the header should
     not be converted to absolute values.

     How do we know where the object list starts and how many objects there
     are? The header tells us. Word 1  of  the RSC file header contains the
     offset IN BYTES from the start  of  the  RSC  file to the start of the
     object list. Word 10 of the  RSC  file  header  tells us the number of
     objects in the list. The table gives  the function of each header word
     as far as I have been able to work them out.

     word 0    uncertain
     word 1    offset of start of object list IN BYTES
     word 2    offset of start of tedinfo list IN BYTES
     word 3    offset of start of iconblk list IN BYTES
     word 4    offset of start of bitblk list IN BYTES
     word 5    uncertain
     word 6    uncertain
     word 7    uncertain
     word 8    uncertain
     word 9    offset of start of tree list IN BYTES
     word 10   number of objects
     word 11   number of trees
     word 12   number of tedinfos
     word 13   number of iconblks
     word 14   number of bitblks
     word 15   uncertain
     word 16   uncertain
     word 17   size of RSC file IN BYTES

     The tree list also  needs  some  attention.  It  is  simply  a list of
     longwords, one for each tree. Each longword points to the first object
     in its respective  tree.  Each  longword  in  the  tree  list  must be
     adjusted by adding the  RSC_start_address  to  it.  The  offset of the
     start of the tree list IN BYTES is in RSC header word 9 and the number
     of trees is in RSC header word 11.

     Compute!'s Technical Reference Guide volume 2 (AES) page 136, mentions
     that when a non-incorporated  RSC  file  is  loaded using the rsc_load
     call, the operating system  adjusts  the  tree  list pointers and then
     stores the absolute address of the  beginning  of the tree list in the
     ap_ptree field of the application's  global  data array. It would seem
     sensible for us to do the same.


     ADJUSTING OBJECT DIMENSIONS. The reason RSC file object dimensions are
     given in character heights and widths is  that the one RSC file can be
     converted to work with different  ST/TT  resolutions at run-time. This
     saves writing different  versions  of  the  RSC  file  for each screen
     resolution.

     Object sizes are  converted  by  calling  the  operating  system using
     rsc_obfix. The call requires the  programmer  to pass both the address
     of the tree (ie the absolute address  of the first object in the tree)
     and the number of the object.  If  we  were to call rsc_obfix, tree by
     tree and object by object, we run into a minor problem of knowing when
     we get to the end of each  tree.  It is not possible to determine this
     by direct inspection of the  RSC  header.  The last_object in the tree
     hierarchy should have bit 5 of word 4  set and it should also have its
     first word (the ob_next field) set  to  0. This last_object may not be
     the last physical object in the tree object list. It would be possible
     to determine the length of the tree in bytes and divide the size by 24
     to get the number of objects in the tree.

     Fortunately I think it is likely  that  rsc_obfix only uses the object
     number to index forward  into  the  object  list  from  the tree start
     address and does not concern itself with the actual object numbers. If
     this is so then the whole object list can be treated as one tree. This
     would allow us to process pointers and sizes in the same procedure and
     simplifies our task.


     PSEUDOCODE

     Procedure FixObject;
     RSC_start_address := absolute RSC start address (bytes);
     Object_list_address := absolute object list start address (bytes);
     Object_address := Object_list_address (bytes);
     Number_of_objects := RSC file header word 10;
     Object_size := 24 (bytes);
     FOR N = 0 TO (Number_of_objects-1)
     DO
       Object_address := Object_address + (N * Object_size)
       Object_byte_7 := value of byte at (Object_address + 7)
       IF Object_byte_7 = 20 or 25 or 27 THEN
         no action required;
       END IF;
       IF Object_byte_7 = 26 or 28 or 32 THEN
         add RSC_start_address to object_longword_3;
       END IF;
       IF Object_byte_7 = 21 or 22 or 29 or 30 THEN
         add RSC_start_address to object_longword_3;
         use object_longword_3 to access tedinfo;
         add RSC_start_address to tedinfo_longword_0;
         add RSC_start_address to tedinfo_longword_1;
         add RSC_start_address to tedinfo_longword_2;
       END IF;
       IF Object_byte_7 = 23 THEN
         add RSC_start_address to object_longword_3;
         use object_longword_3 to access bitblk;
         add RSC_start_address to bitblk_longword_0;
       END IF;
       IF Object_byte_7 = 31 THEN
         add RSC_start_address to object_longword_3;
         use object_longword_3 to access iconblk;
         add RSC_start_address to iconblk_longword_0;
         add RSC_start_address to iconblk_longword_1;
         add RSC_start_address to iconblk_longword_2;
       END IF;
       IF Object_byte_7 = 24 THEN
         add RSC_start_address to object_longword_3;
         use object_longword_3 to access applblk;
         add RSC_start_address to applblk_longword_0;
         add RSC_start_address to applblk_longword_1;
         (may need to adjust the pointers in parmblk also);
       END IF;
       rsc_obfix (Object_list_address,N);
     END DO;
     END FixObject;

     NOTE Object types 23 and  31  contain  height  and width data in their
     secondary structures (bitblk  and  iconblk).  If  their  appearance is
     abnormal on the screen, try excluding them from rsc_obfix.

     GENERAL COMMENT. I dabbled with this  subject some years ago. I cannot
     guarantee the accuracy of this contribution but  I think it is more or
     less right. Any comments or  corrections  would  be welcome. If anyone
     gets it to work they  might  like  to  send  their  code to Ictari for
     publication.
     ----------------------------------------------------------------------
     To: Dick Teuber
     From: Iain McLeod

     In Reply to Dick Teuber's question  on  how to incorporate a .RSC file
     within a C file, Lattice C holds the answer.

     It has  a  utility  program  which  converts  the  .RSC  file  to  the
     equivalent structural information that it is  referenced by in C code.
     You simply pass the name  of  the  .RSC  file  to the 'RSC Decompiler'
     which does all this and also creates two functions:

     rsrc_init() - Call this function  at  the  start of your program which
     calls fix_tree(), passing all your Form Dialogs each time.

     fix_tree()  -  This  simply  then  calls  the  function  rsrc_obfix(),
     passing all  the  items  in  the  specified  Form  Dialog  to  fix its
     coordinates to pixels.

     So, as you can see, it is  quite  straightforward in that all you need
     to do is write the resource  in  by  hand (time consuming and you will
     need a book for reference - I recommend Atari   Compendium    or   the
     Lattice C Manual Book 1) and have  a  function to go through *all* the
     resource items and call rsrc_obfix() on  them all, (you will of course
     still need to #include the  .H  header  file). Writing the resource by
     hand isn't  the  most  efficient  way  (!)  so  if  you  use  the 'RSC
     Decompiler' utility (I would  expect  it's  copyrighted  to HiSOFT) or
     even if someone did their own Decompiler.

     I would expect the above  applies  to  .S  assembly files also in that
     simply using rsrc_obfix() and setting up  the Form Dialogs in a dc.b/w
     manner will achieve the same result.

     I always use my .RSC files  in  this  way  (- you never know what folk
     will want to do with your .RSC  files,  the Vandals!) and it makes for
     less files in a final executable program.
     ----------------------------------------------------------------------
     To: *.*
     From: Adrian Lovatt

     Plea - does anyone have a description of the CAD3D2 file format, I  am
     writing a program to  convert  CAD  objects  into  a  format usable by
     POVRAY, but really need the file info.  If anyone can help  or has any
     ideas please get in touch.

     Has any HiSoft Basic programmer out  there  ever  tried to put a Basic
     sub-program into the VBI list ?.
     ----------------------------------------------------------------------
     To: Jonathon White
     From: Mark Baker

     Your  comments  on  evnt_multi()  in   the  GEM  tutorial  are  rather
     misleading if not just wrong. Use  of evnt_multi() does not freeze the
     system until it returns.  It  only  freezes  your  program, and allows
     other programs to  continue  execution.  In  fact  other  programs can
     _only_ run during  evnt_multi()  in  co-operative multitasking systems
     such as Geneva. So far from  harming the multitasking, it is essential
     for a well behaved  program  to  spend  as  much  time  as possible in
     evnt_multi() or another event library call.


     Because they take the program  out  of  the evnt_multi(), timer events
     should be avoided if possible as  they slow down everything. Obviously
     if you have to have them do  so, but don't use any unnecessarily. When
     you should have timer events  is  on  their  own using an evnt_timer()
     call in the middle of a large block of processing.

     The real reason you can't access  the  menus  when there is a dialogue
     box on screen is that you do  a  wind_update() to turn them off before
     you draw the  dialogue.  This  is  done  deliberately  to simplify the
     dialogue code. evnt_multi() obviously  doesn't  turn  off the menus as
     that's what you normally use to detect menu events!

     Don't see this as an attack  on  your otherwise excellent series, it's
     just that I would hate to  see  anyone  following your advice on timer
     events.
     ----------------------------------------------------------------------
     To: *.*
     From: Tony Harris

     i)      I need the routines to play Quartet songs in assembly,
             this is very urgent!

     ii)     Does anyone know how to do sine waves in assembler?

     iii)    This is a little embarassing, but what the hell is overscan
             and have I got one in my 1Mb STE, if so, how do I use it,
             and if not, why not?

     */ AutoSwitch Overscan (as I understand it) is a hardware device which
     has to be fitted  to  the  computer  and  effectively makes the screen
     display larger. In the case of a monochrome monitor the screen area is
     changed to about 672 pixels wide by 480 pixels high and so can display
     more information on screen than a  normal display. Unfortunately a lot
     a of programs do not take  advantage  of  the  extra area so it is not
     much use on these programs. I think Calamus does make use of the extra
     area and I would guess that some  of the modern WordProcessors and CAD
     programs do, you would have to  check  before buying one. The hardware
     is available from Compo Software Ltd  in  Huntingdon for about 50 and
     there was a review published in  Issue  6 of ST Applications magazine.
     Whether it works on an STE I  don't  know  but Compo should be able to
     tell you.

     Another system works purely in  software  and allows the programmer to
     use the top, bottom and side borders  to  a certain extent and we will
     be publishing some routines  to  do  this  from  Diamond Software next
     month, but don't ask me how it  works because I still don't understand
     it. If anyone wishes to add more on  the subject, please send it in to
     us. ICTARI /*
     ----------------------------------------------------------------------
     To: ICTARI
     From: Martyn Wells

     I am writing a program which  uses  Videomaster format files i.e. VID,
     FLM, VSQ but I am  having  trouble  with  the  colours in the files as
     these are written in the  Amiga  format  xxxxrrrr/ggggbbbb. Is there a
     quick way of converting them to the Degas format without using  lookup
     tables as the film files are quite  large sometimes and I need to save
     as much memory space as possible.

     --------------------------- End of file ------------------------------
