
     ICTARI USER GROUP             ISSUE 23                     June 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. 01425-474415
     =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

                              INDEX FOR ISSUE 23
                              ==================

     ASSEMBLY        Overscan routines.
                     STE 8 way hardware scrolling routines.
                     Blitter routines using A line $0007 call.

     C               Tim Oren GEM Tutorial. Part 12. GEM Events.
                     Replacement standard library functions with Alcyon C.

     GFA             Hi Rez format program.
                     Library Creator for GFA programmers.

     STOS            Menu Shell code.
                     Screen saver code.
                     STOS Extension selector.

     MISC            GDOS information file.
                     Character conversion tables (in Protext format).
                     Current membership list.

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

     ASSEMBLY        Floating Point routines.

     C               Bouncing Ball demo program.
                     Tim Oren GEM Tutorial. Part 13. GEM Events.

     GFA             Formatting program.

     STOS            Variable to string converter code.

     MISC            Chain program.
                     Using the Atari clipboard.

     ---------------------------------------------------------------------
                                   EDITORIAL
                                   =========
     UNIVERSAL PRINTER DRIVER
     ------------------------
     The response to my proposal for  a  Universal Printer Driver has been
     pretty underwhelming, only two members  expressed any support for the
     idea. Anyway, I still  think  it  will  be  useful  so  I am going to
     continue with the project in  the  hope  that  some more members will
     help out later. I have included a draft specification for the Printer
     Driver at the end of this  document,  please  let me know if you have
     any comments. Perhaps all members  could  check their own printers to
     see if the Printer Driver facilities will cater for their printer and
     let me know if there should  be  any  amendments to the specs, if you
     don't tell me what you  want  don't  blame  me  if you can't use your
     printer with it when it is the established standard.

     CHARACTER CONVERSION
     --------------------
     Please note that we have  left  the Character Conversion article from
     Mrten Lindstrm in Protext format  since  it  contains a lot of non-
     standard characters which  may  not  display  correctly  on some text
     editors.
     ---------------------------------------------------------------------
                                CORRESPONDENCE
                                ==============
     To: *.*
     From: Martyn Wells

     Hi there, can anybody help me  with  a  routine to print in colour on
     a Star LC-240C 24 pin colour printer. I can print graphics OK in mono
     but can't get them to  print  in  colour.  I  normally program in GFA
     Basic but any code in another language would be OK.

     */ Perhaps you could send us a  copy of the Star printer manual (just
     the graphics printing section).  ICTARI /*
     ---------------------------------------------------------------------
     To: ICTARI
     From: Raymond Reid

     The idea for the  printer  program  is  good,  will  try and sort out
     various sources for this if I can get time.
     ---------------------------------------------------------------------
     To: ICTARI
     From: Simon Rigby

     ATTENTION ALL (SPEEDO)GDOS PROGRAMMERS!

     ***AS FAR AS I KNOW, THIS INFORMATION IS NOT AVAILABLE IN ANY BOOK***

     The new breed of printer drivers have  a button on the CPX panel that
     dictates whether or not the driver  has Print Area Offsets. What this
     means in English is that if  this  button  is set to On, V_opnwk will
     return the size of the  Page  in  pixels,  NOT the Printable Area. If
     your program uses this  value  (as  most  will)  to  find the maximum
     number of pixels to print to,  then  you  will find that some of your
     image will be lost in the  non-printable  area. If Print Area Offsets
     are turned off, then v_opnwk will return the correct printable area.

     SOLUTIONS TO PROGRAMMERS
     The big question is:-
     How can I tell whether v_opnwk returns the true printable area or the
     page size?
     The answer is that vq_extnd has been extended to do just this:
     The extra extended enquire values are :-
             intout(19) = 1 for Print Area Offsets ON , else 0
             ptsout(0) = Top Left X Co-ord of Printable Area
             ptsout(1) = Top Left Y Co-ord of Printable Area
             ptsout(2) = Bottom Right X Co-ord of Printable Area
             ptsout(3) = Bottom Right Y Co-ord of Printable Area
             ptsout(4) = 0
             ptsout(5) = ? - I think it is print buffer size but don't
                         know

     To: Steve Gale

     Please find included an article  on  the  clipboard format. I hope it
     helps.  */ See next month.  ICTARI /*

     To: Tony Harris

     The LineA functions are still  available  on  the Falcon and do still
     work in ST compatible modes. They  actually  work in most other modes
     too, but there are a  couple  of  functions  that  fall apart in some
     Falcon specific modes (get/putpix as I recall, but don't take my word
     for that). All STE's/STFM's that  DO  NOT have special graphics cards
     on them will work with LineA.

     I'm beginning to wish my books were accessible (in the attic while we
     decorate!) but what you  need  to  do  is  find  the TimerB interrupt
     priority and  make  it  a  higher  priority  than  the mouse/keyboard
     interrupt.

     To: Terry King

     The Form_dial only redraws the  screen  if  the  area covered is less
     than a quarter of the screen  size  (and sometimes not then). What it
     does do is to send window redraw  messages to anything it covered. If
     that is the desktop, the desktop  redraws  its window (#0) which puts
     the green background on your screen. I  assume that you are not using
     windows, so you are not processing redraw requests.

     Your slider code does not appear to  take account of the width of the
     slider button, which should make  your  total  travel (slider width -
     button width). It should travel with its  left edge from 0 to (slider
     width-button width-1).

     PRINTER DRIVERS
     ---------------
     I will be commenting on your printer  driver text in the order that I
     come across things, so this will  be best read alongside the original
     article. In a simple world,  it  would  be straightforward to do text
     attributes for the printer fonts.  However, most printers have access
     to a number of internal fonts  and  some of these are proportional or
     scaleable. This means that the  driver  must  know  the width of each
     letter to know how much  it  can  get  on  each line. Selecting bold,
     italic, etc can change the  width  of  each letter. Are you seriously
     thinking of holding  font  width  information  for  all printer fonts
     within its driver? How do you  pass  internal font information to the
     application. How does the application show it (if at all)?

     Graphics routines are a fair bit easier,  in my view, and I have only
     come across a limited  number  of  ways  of  sending  image data to a
     printer. Microline spacing is not as simple as you make out, however,
     as to print on a 9-pin at 216 dpi (vertically) you send bytes made up
     of eight scan lines  each  spaced  3  lines  apart  (i.e. the data is
     interleaved) requiring 3 passes per 24  scan lines, each pass one dot
     lower than the last and a 21/216 linefeed at the end of each 3 lines.

     I think  resolution  (and  aspect  ratio)  should  be  passed  to the
     application on opening the driver in the  form of X-dpi and Y-dpi (is
     there any application that  doesn't  use  dpi?  GDOS uses microns but
     could be  converted  from  the  info  given.)  I  also  think  that a
     universal printer driver should be able  to  have a GDOS driver (even
     if it is only used as a means of passing image data to the printer).

     The only printers I know of are mono, RGB, CYM & CYMK. If screens are
     to be viewed as a form of  printer, we get more complicated. The most
     common are mono and  CYM(K).  Colour  should  be  represented on mono
     printers as brightness levels.

     As far as I know,  only  HP  use  compressed data streams. Certainly,
     none of the Epson  modes  compress  data.  The  only compression that
     could be applied is not to send empty tails on scanlines.

     I would envisage a printer driver to  work on two levels; the printer
     driver itself would have  an  open (get-info), close (free-resources)
     and send-data (pixel/line/block  of  lines)  routines.  It should tie
     into a higher level set of routines similar to GDOS for graphic text,
     line drawing & image printing.  The  way  that  GDOS works is for the
     driver to look like a program  (without  any  mshrink, etc) and it is
     loaded in by a pexec but not run. The program is then run like a sub-
     routine by repeatedly calling it with d0 containing the op-code (like
     any VDI routine).  Only  Text  is  handled  by  calls  back into GDOS
     itself.

     Please note that  9-pin  require  up  to  24  lines  per pass. 24-pin
     require up to  48  lines.  I  think  that  printer  codes  should use
     [esc][control-code][...][esc] if you are going  to use text, allowing
     the full range of ASCII codes. [esc][esc]  should be used to send the
     [esc] code to the printer.

     I personally think that  an  extension  or  alternative  to GDOS is a
     better way forward and do not think  ASCII and graphics can easily be
     mixed on  the  same  page.  I  think  graphics  output  only  is  the
     reasonable approach to take.

     I should also warn you that  I  looked  at the wider problems of this
     and left it as a backburner  problem  (although some code was written
     and tested).

     I wish you luck and will be glad to provide any routines you require.

     */ I think that any utility  program which calls itself Universal has
     to be a compromise to greater or lesser extent. As you say it is very
     difficult  to  combine  text  printing   and  graphics  images  in  a
     comprehensive way such as a DTP  program  would  do. I think the best
     that we could achieve is a mixture  of  both  in much the same way as
     First Word Plus did, that is some  text followed by an image (if that
     is what the programmer wants). If a  programmer wanted to make a true
     DTP style program then the  text  would  have  to be formatted as bit
     mapped images (using  Calamus  fonts  maybe,  ICTARI  20) and printed
     entirely in graphics mode. Regarding font sizes, as you will see from
     the article at the end of  this  document,  I only intended using the
     printers internal character  set  (albeit  at  a  number of different
     pitches) for text only type  print-outs.  If  the programmer wants to
     use a much wider range of character  sizes he would again have to use
     graphics modes and construct  a  bit  image  to  be  printed. I would
     certainly be interested in  the  colour  printing modes you mentioned
     although if the programmer  allows  the  end  user  to print a colour
     image on a monochrome printer  I  think  it  is his responsibility to
     render the colours  into  black  and  white  shading  rather than the
     printer driver  program.  Some  of  your  other  observations  may be
     answered by the article later,  please  send  any further comments in
     when you have studied it.  PDH /*
     ---------------------------------------------------------------------
     To: Terry King
     From: Mrten Lindstrm

     RESTORING THE SCREEN WITH FORM_DIAL
     -----------------------------------
     All that FORM_DIAL(3, ...) does  is  to  issue redraw requests to the
     GEM process(es) responsible for the piece of screen in question.

     And a GEM application isn't considered to be responsible for anything
     else than the contents of  windows  opened  by it. Everything else is
     handled by the screen manager of the  AES, which will do the desktop,
     menu and any window borders. (The green  box that you get is probably
     simply  a  piece  of  desktop  that   the  screen  manager  tries  to
     "restore".)

     I thus suspect that your  (or  another?)  program is using the screen
     without having opened a (well-behaved) AES window onto it.

     (After you have defined  and  opened  a  window  with WIND_CREATE and
     WIND_OPEN you must wait  for  window-related messages with EVNT_MULTI
     (or EVNT_MESAG) or in GFA Basic  you  might alternatively use the "ON
     MENU" command, which I assume  makes  an internal call of EVNT_MULTI.
     Every time you get the redraw  message  (20)  for a window you should
     redraw the contents of the  window  concerned  -  see more about this
     below.)

     Alert boxes, on the other  hand,  are evidently physically saving and
     restoring the used screen  memory  rather  than using FORM_DIAL calls
     for their restore, and this method could,  of course, be used in your
     own customised routines too. The advantage  is  not only that you may
     make non-window output work (which shouldn't  be used in a 100% clean
     program anyway) but that you gain speed as well. The drawback is that
     it requires memory. (I think alert boxes use the same internal memory
     buffer as used by menu dropboxes.) A  solution for a clean program is
     to allocate memory only when  it's  needed  for  the save and free it
     afterwards - calling FORM_DIAL  when  there  isn't enough memory. The
     100% clean way of saving/restoring image  blocks is with the VDI call
     VRO_CPYFM (or in GFA Basic terms BITBLT with THREE parameters).

     By the way: FORM_DIAL(0, ...)  should  always  be  used before a code
     section after which you intend to  use  FORM_DIAL(3, ...) to tidy up,
     but this is purely for future compatibility reasons. (I could imagine
     these calls in the future to  cause  the  screen to be actually saved
     and restored to/from a  secret  memory space.) Presently FORM_DIAL(0,
     ...) performs no function at all and thus cannot be the cause of your
     problem.


     UPDATING PARTIALLY COVERED WINDOWS
     ----------------------------------
     Updating a window that is  partially  covered  by other windows isn't
     really  much  more  difficult  than  updating  a  topped  (completely
     uncovered) window.

     There is no need  to  keep  track  of  the  positions  and extents of
     windows and which ones are covering which,  since the AES will do all
     that for you.

     The secret is WIND_GET with modes 11  and  12 which will give you all
     visible rectangles of a window. (If  the  window is topped there will
     be only one rectangle, and if  completely  covered there will be none
     of course.) When you get a rectangle  with both width and height = 0,
     this means there aren't any more visible rectangles to draw.

     For each rectangle you  get,  you  should  normally  first  set a VDI
     clipping rectangle according to  it  (with  VS_CLIP  or in GFA Basic:
     CLIP), before drawing.  Neglecting  this  might  earn  you some speed
     though you must then of course be certain that you don't draw outside
     the rectangle.

     If the updating is to be done  in response to a redraw message (which
     may, for instance,  have  been  caused  by  a  FORM_DIAL(3, ...) from
     someone then in order to  cut  down  on  the drawing work you should,
     before drawing each  visible  rectangle,  calculate  its intersection
     with the redraw area given with the redraw message. (There even seems
     to be a GFA Basic command RC_INTERSECT for this.)

     I think a window updating routine  in GFA Basic should look something
     like this (though the variables I've  called handle and x,y,w,h could
     more efficiently be renamed  handle&  and  x&,y&,w&,h&  for GFA Basic
     WORD format):

     ~WIND_UPDATE(1)    ! Request permission from the AES to start drawing
     ~GRAF_MOUSE(256,0) ! Hide mouse to avoid corrupting drawing
     ~WIND_GET(handle,11,x,y,w,h) ! Get first visible rectangle
     WHILE w OR h <> 0
     ' If in response to redraw msg. insert intersection calculation here.
       CLIP x,y,w,h  !Other languages require coordinate conversion to VDI
     ' Do the drawing here
       WIND_GET(handle,12,x,y,w,h) ! Get next visible rectangle
     WEND
     ~GRAF_MOUSE(257,0) ! Show mouse
     ~WIND_UPDATE(0)    ! Allow other processes access to screen again

     For the drawing itself to turn out  right, you need of course to know
     the coordinates not only of the  visible  rectangle but of the window
     itself, which you may  get  from  WIND_GET(handle,4,x,y,w,h) (for the
     work area i.e. excluding borders). In  fact  you  can, as long as you
     are using VDI for output,  completely disregard the visible rectangle
     and always draw as if  on  the  full  window area, since the clipping
     will make sure  that  only  the  visible  rectangle  is affected. For
     faster output you may  have  to  make  some calculations to determine
     what and where there actually  needs  to  be  drawn in the particular
     visible rectangle.

     NOTE: In a well-behaved GEM  program  ANY  window updating routine is
     REQUIRED to cope with partially covered windows.


     CAN THE MEMORY OF A RESIDENT PROGRAM BE FREED?
     ----------------------------------------------
     The answer to this question  is  generally  NO.  As  far as GEMDOS is
     concerned a program and its memory  is completely and utterly gone as
     soon as PTERMRES has been executed.

     Under MiNT  however,  a  would-be  resident  program  could  -  as an
     alternative to PTERMRES - start a background child process making use
     of the same memory as itself and then terminate itself with PTERM.

     I have no personal experience of MiNT  but have an article on this by
     Julian Reschke in  the  German  "ST  Magazin"  3/93.  If  somebody is
     interested I could possibly try  to  get  more  details  out of the C
     source given with this article, but the  general idea is to use PEXEC
     with modes 5 and (MiNT specific)  104  to  reserve a basepage for and
     launch the child without waiting for its return.

     The child should set the stack pointer and then go about its business
     such as redirecting vectors (cleanly  with  use  of XBRA protocol and
     SETEXC) etc. Finally it should use  (the  MiNT call) Psignal to set a
     termination routine for the SIGTERM (=15)  signal, mask out all other
     signals with Psigsetmask(L:1<<15) and  start  waiting  with (the MiNT
     call) Pause() for its termination.

     The termination routine  of  the  child  could  for  instance  try to
     restore any redirected vectors and  exit  with PTERM if this succeeds
     or PTERMRES if  it  fails  (because  some  jerk  has  messed with the
     vectors without using XBRA).

     To: Mark Baker

     Thank you very much for your info and  example on how to use the MiNT
     "_CLP" semaphore to avoid clashes on the clipboard. This is something
     that so far had completely  escaped  me.  When looking into the Atari
     Compendium I furthermore found it very brief indeed on the subject of
     MiNT semaphores, describing how to use them alright but not what for,
     and not naming a single system defined semaphore.

     Are there perhaps other standard MiNT semaphores - such as "_PRN" and
     "_AUX" to avoid clashes on the printer and serial device?

     I imagine that MiNT (or  MultiTOS)  isn't  used  by  more than a tiny
     fraction of today's TOS users (or  even  of Falcon users perhaps?), I
     personally haven't really got the  computer  for  it  yet, and I have
     zero experience of actually  programming  for  it.  But  on the other
     hand, if I - by squeezing in  the  odd  MiNT  call - can make my code
     slightly more future-proof and  compatible  this  is something I very
     much would like to do.

     Your idea - to write any internal  memory clipboard buffer to the GEM
     disk clipboard each time a  program  is  ended or its window untopped
     (which I assume means when it is receiving a WM_UNTOPPED (=30) window
     message, or perhaps also if/when  it  is  "bottoming" or iconifying a
     window?) - is excellent I  think.  If  the program maintains a "dirty
     flag" for the internal memory buffer (set when the internal buffer is
     updated and cleared when the disk clipboard  is) so that it can avoid
     unnecessary disk accesses, then I  cannot see why everybody shouldn't
     use it whenever a memory buffer  is  implemented. I still think there
     may be a point in offering exclusive use of the disk-based clipboard,
     through a "Use  clipboard"  toggle  menu  option,  or/and  a one-shot
     "Update clipboard" option for those  (us)  who  are using the old AES
     which never sends any WM_UNTOPPED.


     To: *.*

     As Mark Baker  could  tell  in  Ictari  22,  clashes during clipboard
     accesses can possibly be avoided by the following MiNT calls:

     In C:
     -----
      Psemaphore(2,'_CLP',-1);  /* Request access to Clipboard ! */
      /* Access here */
      Psemaphore(3,'_CLP',0);   /* Clipboard free for others to use */

     I find this such a useful piece of knowledge that I (with the help of
     the Atari Compendium) immediately made  the translations of this into
     assembler and GFA Basic, which I would like to share:

     In assembler:
     -------------
        pea     -1.W             ; ( Wait indefinitely )
        move.l  #'_CLP',-(SP)    ; Request access to Clipboard !
        move.l  #$1340002,-(SP)  ; ( Psemaphore, mode 2 )
        trap    #1
        lea     12(SP),SP
     * Access here
        clr.l   -(SP)            ; ( Dummy longword )
        move.l  #'_CLP',-(SP)    ; Clipboard free for others to use
        move.l  #$1340003,-(SP)  ; ( Psemaphore, mode 3 )
        trap    #1
        lea     12(SP),SP

     And in GFA Basic:
     -----------------
      ~GEMDOS(308,2,L:CVL("_CLP"),L:-1) ! Request access to Clipboard !
      ' Access here
      ~GEMDOS(308,3,L:CVL("_CLP"),L:0)  ! Clipboard free for others to use


     NOTE: The above calls will work only under MiNT but I can see no real
     harm in just making them  and  hope  there  is someone there who will
     understand them. The old  TOS  will  simply  return  a -32 = "Invalid
     function number" and no harm will have been done.
     (If you absolutely have to know  that  MiNT  is there to react on the
     calls, you should check for the  presence  of a "MiNT" cookie and, if
     you are really paranoid, that the value (long) of the cookie is  $92
     - for MiNT v0.92+. That  would  bypass  the  theoretical problem of a
     GEMDOS extension other  than  MiNT  intruding  on  the  MiNT function
     numbers, but this is something that  only  an old and obsolete system
     would do, since MiNT  is  THE  official  successor  of GEMDOS and any
     future extensions will have to build from there.)

     To: *.*

     PICPAC - THE NEXT GENERATION
     ----------------------------
     I have now  added  GIF  and  TIFF  unpacking  to  my PICPAC assembler
     library and adapted it to  be  usable  with  GFA  Basic too. But I am
     convinced it must be possible to use with other languages as well. (I
     noticed that there was an interest  among Ictari C programmers for an
     IMG packing routine.)

     Since my  ST  programming  experience  is  more  or  less  limited to
     assembler and GFA Basic, however, I have refrained from dabbling with
     bindings for C or anything else. I  merely  send in the source for an
     object file to be linked with C  or  other programs, plus info on the
     format of the calls, and I very  much  hope that someone will be able
     to make something out of that,  perhaps comparing and translating the
     GFA Basic bindings.

     The PICPAC routines are tailored for  use  in clean GEM programs (but
     with supplementary routines for non-GEM use) and can presently:-

     PACK -  IMG (including  XIMG  colour)  and  IFF  ILBM  (uncompressed,
             Packbits compressed OR vertical word compressed).

     UNPACK -ditto (plus HyperPaint IMG) plus GIF, TIFF, Degas and NEO.
             The GIF and TIFF routines also sort palettes of 256 colours
             to be (more or less) usable on ST screens with 16 colours.

     CONVERT between palette formats: 24-bit, VDI and ST(E) hardware.
             Associated routines given with  the  assembler  and GFA Basic
             bindings can set  and  get  palettes  cleanly  under  GEM and
             translate palette indexes to  VDI  pen  number on any palette
             colour screen, also with graphics cards.

     I would be very grateful indeed  for  any views and comments on this.
     How well does it work. What functions are missing, etc.

     THE 'BEST' PICTURE FILE FORMAT
     ------------------------------
     By the way, I hope that no-one  has  become too excited about the LZW
     compression used  in  GIF  and  TIFF.  It  is  a  very  clever little
     compression scheme  indeed,  amazingly  good  at  compressing  simple
     pictures such as maps  and  charts  (and  the  LZW  unpacking code in
     itself not taking up much space either; it is only a minor part of my
     GIF and TIFF routines). But LZW is not all that impressive with near-
     photographic images, which I think are the most common type among GIF
     and TIFF images. I even  came  across  one or two LZW-compressed 256-
     colour images LARGER than  when  uncompressed  -  something much less
     likely to occur with the  simpler  compression  types  of IMG and IFF
     ILBM. The "Deluxe Paint IFF" vertical word compression in particular,
     comes close if not beating  GIF/TIFF  LZW  with most "normal" images.
     Unpacking of GIF and TIFF unavoidably  also takes more space and time
     than of the image formats native to the ST (and Amiga).
     So, in short, be happy with IMG  or IFF ILBM! (Except for the purpose
     of importing PC images.)


     */ The articles mentioned above will  be published in later issues of
     ICTARI. /*
     ---------------------------------------------------------------------
     To : All
     From: Paul Pickering

     If any of the members would like  to make regular contacts with me by
     letter to swap ideas, tips and  advice  on software and hardware they
     would be most  welcome.  Also  if  any  members  have  any  ST Format
     Magazine issues Nos 1 to 58 with  disks  I  could copy or buy or swap
     please contact me. My name and  address  is listed in the MEMBERS.TXT
     file. I also have some software I would  like to swap or sell. I have
     listed them below.

     Another World            #5 inc P&P or swap for Lemmings
     Pirates                  #5 inc P&P or swap for Cruise for a Corpse
     Dragons Of Flame         #3 inc P&P or swap for GemView (PD)
     Flames Of Freedom        #5 inc P&P or swap for Thunderhawk AH-73M
     Gods                     #5 inc P&P or swap for F-29 Retaliator
     Hero Quest               #5 inc P&P or swap for DEVPAC or GFA Basic
     Maupiti Island           #5 inc P&P or swap for Super Space Invaders
     Panza Kick Boxing        #3 inc P&P or swap for 3D Pool
     Populous II              #5 inc P&P or swap for Stereo Master

     Rick Dangerous           #3 inc P&P or swap     Atari ST 3D Graphics
     Strider II               #3 inc P&P all three   Programming by Braun
     Terminator 2             #3 inc P&P for         book

     Indiana Jones            #3 inc P&P or swap     Musical Applications
     Moonwalker               #3 inc P&P both for    of the Atari ST'S

     Their Finest Hour        #5 inc P&P or swap for Streetfighter 1 or 2
     The Killing Cloud        #5 inc P&P or swap for Your second Manual
                                                     To the Atari ST
                                                     (book or disc)
     ---------------------------------------------------------------------
     To: *.*
     From: J Chapman, 95 Heathfield Rd, Ferndown, Dorset, BH22 0DE.
           Tel. 01202 895613

     For Sale :-

     Atari 520 STFM with 1Mb, Seikosha 9 pin printer, Colour Monitor/TV
     Software- Timeworks, Flexidump, Protext, IMPrint.
     Books-    'Your Second Manual' + disk, 'Get the best from your ST'
     Mag disks-ST Format cover disks + PD, Clip Art, etc

     150 or near offer for the lot.

     +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                           UNIVERSAL PRINTER DRIVER
                           ========================

                              DRAFT SPECIFICATION
                              -------------------
     GENERAL
     -------
     The object  of  the  Universal  Printer  Driver  (UPD)  is  to  allow
     programmers to write a program which  requires a printed output (text
     or graphics) without having to write  their own printer code, the UPD
     program handles all printing  operations.  This makes writing printer
     dependent applications much easier and has the big advantage that the
     program will then work with any  type  of printer providing a printer
     driver text file has been written for the printer concerned.

     UPD PROGRAM
     -----------
     The UPD system consists of two main parts, the UPD program itself and
     a Printer Driver  Text  file  for  the  printer  being  used. The UPD
     program is a  machine  code  program  which  is  supplied  as  a pre-
     assembled  binary  file  (UPD_V100.BIN)  and  is  'included'  in  the
     programmers code using  one  of  two  methods.  The  simplest way for
     example, in a machine code  program  is  to simply include the binary
     file at the 'upd_driver' label with the 'incbin' pseudo-op :-

     upd_driver      incbin          UPD_V100.BIN

     For other computer languages a  similar  method will be required. The
     second method is to allocate a  RAM  buffer and make the applications
     program load the UPD_V100.BIN file from disk  at start up time in the
     same way as a Resource file  is  loaded. This method is slightly more
     involved but has the advantage  that  if  a  later version of the UPD
     program is issued, the end user  can  use  it by substituting the new
     program for the old one on disk.

     When the user application is up  and  running, the program should ask
     the program user to  load  in  a  Printer  Driver  Text file which is
     appropriate for the  printer  he/she  is  about  to  use. The program
     should load the driver file into a temporary buffer and then call the
     UPD routine in Initialise mode. The UPD  code scans the text file and
     builds a table in RAM which  holds  the graphics information and text
     attribute control code strings. The  routine returns with the address
     of this table in  register  d0  which can  then  be  used by the main
     program, when required. The  Printer  Driver  Text  file  data in the
     temporary buffer can then be discarded  as  it is no longer needed by
     the UPD program.

     Access to the UPD code is  similar  to the GEM system, any parameters
     are pushed onto the stack and  the  UPD  code called as a sub-routine
     using the label at the buffer  address. An error code (if applicable)
     is returned in register d0. For  example, using the machine code case
     shown above, a typical call would be as follows :-

                     move.l          #$0200,-(sp)            ;reset code
                     move            #UPD_TEXT,-(sp)         ;text mode
                     bsr             upd_driver              ;call S/R
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error ?
                     bmi             error                   ;bra if error
                     ...

     The  UPD  routine  has   just   the   one   entry  point  (the  label
     'upd_driver'), the required function is passed to the code along with
     any other parameters via the  stack.  At  present there are six basic
     functions which are described below  with their associated parameters
     as follows :-

     Value   Mnemonic        Parameter_1     Parameter_2     Function

       0     UPD_INIT        Driver_addr     UPD_file_addr   Initialise
       1     UPD_TEXT        Value+Control                   Send text
       2     UPD_SGM         Length+Rez                      Start graphic
       3     UPD_SGD         Graph_addr                      Send graphics
       4     UPD_EGM                                         End graphics
       5     UPD_DELAY       Period                          Set delay

     A brief description of each function is shown below.

     INITIALISATION
     --------------

     When the UPD program  and  the  Printer  Driver  Text files have been
     loaded into memory the UPD code  should first be initialised. The UPD
     program scans the UPD program code  itself and relocates any absolute
     addresses in the code  using  the  'upd_driver'  address  as the base
     address which is  passed  to  it  as  the  second  parameter. It then
     generates a look up table in RAM which it uses to access the graphics
     and text attribute strings whenever  data  is  passed to the printer.
     The RAM buffer for  the  look  up  table  is  allocated using the GEM
     function Malloc so  the  application  program  should  make sure that
     there is sufficient RAM left  in  the  TPA  for this buffer. If there
     were no errors the routine returns  with  the  address of the look up
     table in register  d0  which  should  be  stored  by the applications
     program for later use. In machine code, the initialisation call would
     look like this :-

             move.l          #upd_file,-(sp)         ;address of text file
             move.l          #upd_driver,-(sp)       ;address of pgm code
             move            #UPD_INIT,-(sp)         ;Initialise code
             bsr             upd_driver              ;execute
             add             #10,sp                  ;correct stack
             tst.l           d0                      ;chk for error
             bmi             error                   ;branch if error
             move.l          d0,upd_buff             ;save upd table addr
             ...

     where   #UPD_INIT equals 0.
             #upd_driver is the address of the UPD driver program.
             #upd_file is the address of the UPD text file.

     If another printer driver  is  to  be  used,  the  RAM  for the first
     printer should first be freed by  using  the  GEM Mfree call with the
     address stored in 'upd_buff'. Also,  when  the program is exited, the
     RAM should first be freed.

     The layout of the look up table is described in more detail below.

     TEXT ATTRIBUTES
     ---------------
     When the  UPD  code  has  been  initialised,  text  characters,  text
     attributes or graphics data can be  printed  out via the UPD routine.
     To send a normal text character to  the printer the character code is
     pushed on the stack and the  routine  called  in a similar way to the
     GEM Bconout function. The main difference is that a long word is used
     to store the data  to  make  the  code  easier  to use. The character
     should be stored in the low word and any additional values are stored
     in the high word (see later for more details). For example, to output
     the letter 'A' to the printer use the following code :-

                     move.l          #'A',-(sp)              ;chr A
                     move            #UPD_TEXT,-(sp)         ;text mode
                     bsr             upd_driver              ;execute
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error
                     ...

     The character code should be in  the  range 0-255 ($00-$FF) with bits
     8-15 set to zero. The high  word  (bits 16-31) are ignored for normal
     output of text characters. The  character  code  is  passed on to the
     printer port without any  further  processing  with  the Bconout BIOS
     function using Device No 0 (parallel port).

     To output a text attribute  code  to  the  printer, use the same code
     except that all attribute  codes  are  in  the range $0200-$FF00. For
     example, to start underline mode  in  machine  code use the following
     code :-

                     move.l          #$1800,-(sp)            ;Underline on
                     move            #UPD_TEXT,-(sp)         ;text mode
                     bsr             upd_driver              ;execute
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error
                     ...

     Although it  is  not  absolutely  necessary  to  check  for  an error
     condition every time the routine  is  called, it is advisable because
     if the printer should  go  off-line  during  a printing session, some
     printed data could be lost.

     The high bits of the data longword  sent  to the printer can be used,
     for some attributes, as an  additional  value. For example, the Print
     Multiple Copies (PMC) attribute (used  mainly on Laser printers) also
     requires a numeric value  for  the  number  of  copies to be printed.
     Obviously this value cannot be stored in the Printer Driver Text file
     so it is passed to the printer  by  the program together with the PMC
     attribute code. In the Printer  Driver  Text  file, the control codes
     include a hash (#) character  which  tells  the  UPD  code to use the
     additional value in the high word of the attribute code. For example,
     the PMC code in  the  Printer  Driver  Text  file  will  be stored as
     follows :-

       PMC=27,38,108,#,88                         ;Print multiple copies

     To use this particular attribute a typical machine code program would
     look like this :-

                     move            #5,d0                   ;5 copies
                     swap            d0                      ;move to high
                     move            #$1E00,d0               ;PMC code
                     move.l          d0,-(sp)                ;Send code
                     move            #UPD_TEXT,-(sp)         ;text mode
                     bsr             upd_driver              ;execute
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error
                     ...

     The UPD code will send  the  codes  27,38,108,5,88 to the printer and
     then return.

     The complete list of  current  attribute  codes  is  shown below, see
     later for graphics modes.

     HEX       ATTR            FUNCTIONS
     CODE      CODE

     0200      RES             Reset printer
     0400      BLD1            Bold text enable
     0600      BLD0            Bold text disable
     0800      ITA1            Italics text enable
     0A00      ITA0            Italics text disable
     0C00      PPT1            Proportional text enable
     0E00      PPT0            Proportional text disable
     1000      SUB1            Subscript text enable
     1200      SUB0            Subscript text disable
     1400      SUP1            Superscript text enable
     1600      SUP0            Superscript text disable
     1800      ULN1            Underline text enable
     1A00      ULN0            Underline text disable
     1C00      CPB             Clear printer buffer
     1E00      PMC             Print multiple copies #
     2000      UNI1            Unidirectional printing on
     2200      UNI0            Unidirectional printing off
     2400      LP6             Print 6 lines per inch
     2600      LP8             Print 8 lines per inch
     2800      C05             Print 5 chars per inch
     2A00      C06             Print 6 chars per inch
     2C00      C09             Print 9.5 chars per inch
     2E00      C10             Print 10 chars per inch
     3000      C12             Print 12 chars per inch
     3200      C15             Print 15 chars per inch
     3400      C17             Print 17 chars per inch
     3600      C20             Print 20 chars per inch
     3800      NLQ1            Near Letter Quality enable
     3A00      NLQ0            Near Letter Quality disable
     3C00      GR0             Graphics resolution group 0
     3E00      GR1             Graphics resolution group 1
     4000      GR2             Graphics resolution group 2
     4200      GR3             Graphics resolution group 3
     4400      GR4             Graphics resolution group 4
     4600      GR5             Graphics resolution group 5
     4800      GR6             Graphics resolution group 6
     4A00      GR7             Graphics resolution group 7
     4C00      MF0             MicroLine feed group 0
     4E00      MF1             MicroLine feed group 1
     5000      MF2             MicroLine feed group 2
     5200      MF3             MicroLine feed group 3
     5400      MF4             MicroLine feed group 4
     5600      MF5             MicroLine feed group 5
     5800      MF6             MicroLine feed group 6
     5A00      MF7             MicroLine feed group 7
     5C00      COL             Select colour code #
     5E00      HLF             Half Line Feed

     GRAPHICS MODES
     --------------
     The graphics system has been designed to be as simple as possible for
     the programmer. All the programmer  needs  to  do is to construct the
     image to be printed in a suitable  RAM  buffer and then send the data
     to the printer via the UPD one  raster  line  at a time. The UPD code
     will convert the data into a suitable format for the printer and pass
     it on to the printer in the correct format.

     The graphics control codes  are  arranged  in  three functions, Start
     Graphics Mode, Send Graphics Data  and  End  Graphics Mode. To send a
     graphics  bit  image  to  the  printer  the  image  should  first  be
     constructed in a buffer of which the  width (in bytes) and the height
     (in scan lines) is known. For  example,  to print the screen image in
     standard monochrome mode the width would  be  80 bytes and the height
     400 scan lines. To print  the  image  the applications program should
     first determine  the  printer  resolution  required  which  will,  of
     course, depend on  the  resolutions  available  in  the  printer. The
     resolutions available can be obtained  from  the  look up table which
     has been built by the UPD program (see below for table layout).

     To start graphics mode the Start  Graphics Mode (SGM) control code is
     first sent to the UPD routine  together  with the resolution code and
     the width of the bit image  in  bytes.  Assuming that an image on the
     high rez screen is to be printed  at printer resolution group 1 for a
     HP LaserJet printer the call in machine code would look like this :-

                     move            #80,d0                  ;80 bytes
                     swap            d0                      ;move to high
                     move            #1,d0                   ;Rez group 1
                     move.l          d0,-(sp)                ;Send data
                     move            #UPD_SGM,-(sp)          ;SGM mode
                     bsr             upd_driver              ;execute
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error
                     ...

     The width of the  image  in  bytes  is  placed  in  the  high word of
     register d0 and the resolution of  the  printer  is placed in the low
     word. The resolution code is a value  between 0 and 7 and defines the
     printing resolution of the printer. For example, in the HP LaserJet 3
     driver shown  below  there  are  four  possible  resolutions,  75*75,
     100*100, 150*150 and 300*300 dpi which are  defined as groups 0, 1, 2
     and 3 with the codes GM0,  GM1,  GM2  and  GM3. By using a resolution
     group code of 1 the  applications  program  is telling the printer to
     print the image at 100*100 dpi.  In  this example, since our image is
     640 pixels wide by 400 pixels  high,  the  printed image will be 6.4"
     wide by 4" high. Since these  figures  can  be  read from the look up
     table, the applications program  can  determine  what size the images
     will be and format the image data accordingly.

     The SGM function also determines the  type of graphics printing being
     used which is defined by  the  graphics  ident code which immediately
     follows the GM code in the printer  driver text file. For example, in
     the HP Laser  driver  the  ident  code  is  51  which  defines the HP
     LaserJet method of printing. Each type of printer has its own code as
     shown below :-

             1       9 pin Epson mode.
             2       9 pin Microline mode.
             11      16 pin Epson mode.
             21      24 pin Epson mode.
             31      48 pin Canon BJ mode.
             41      HP InkJet mode.
             51      HP LaserJet mode.

     As can be seen from the codes  there  are plenty of spare codes which
     may be added at a later date for any other types of graphics printing
     modes. The SGM function also allocates some memory (with Malloc) from
     the TPA as a  temporary  image  buffer  store.  The programmer should
     ensure that some RAM is still available to the UPD code when graphics
     images are being printed. The  actual  amount  needed varies with the
     type of printer being used. HP Laser/InkJet printers use least and 48
     pin printers need most because for 9/16/24/48 pin printers the single
     raster lines are stored in the  buffer  until enough have been stored
     to be output to the printer.

     It is essential in this case  to  check  for  an error on return from
     this function to make sure that there is sufficient memory available,
     that the graphics mode is valid and that the printer is on line.

     To output the image to the  printer,  the applications program sets a
     pointer to the start of the  image  and  then calls the Send Graphics
     Data (SGD) function for each  raster  line.  For example, to send the
     screen image to the printer the following code would be used :-


                     move.l          #screen_addr,a0         ;fetch addr
                     move            #400-1,d1               ;400 lines

           loop      move.l          a0,-(sp)                ;Send addr
                     move            #UPD_SGD,-(sp)          ;SGD mode
                     bsr             upd_driver              ;execute
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error

                     add             #80,a0                  ;next line
                     dbra            d1,loop                 ;repeat
                     ...

     When the complete image has been sent to the printer (or if the print
     has been aborted because an error was detected) the End Graphics Mode
     (EGM) function must be used. This  function resets various stores and
     releases the temporary memory buffer that was allocated in the TPA. A
     typical example is as follows :-

                     move            #UPD_EGM,-(sp)          ;EGM mode
                     bsr             upd_driver              ;execute
                     add             #2,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error
                     ...

     These three functions make the printing  of graphics images very easy
     for the programmer, the only difficult  part is generating the images
     in the first place at the required resolutions.

     PRINTER ON-LINE DELAY
     ---------------------
     Within the UPD program code the  text/graphics  data is output to the
     printer via the GEM Bconout function  using the parallel port (Device
     Number 0). Before each value is sent to the port the Bcostat function
     is called to check whether the printer  is  on line. If it is not on-
     line the output is suspended and  a  delay  period is started. If the
     delay period expires with  the  printer  still  off-line, the routine
     returns an error code in register d0.

     Since this delay period can cause  problems for some printers with or
     without internal printer buffers, it  can  be changed from within the
     applications program with the UPD_DELAY  function. The delay is based
     on the Vsync BIOS function and so will vary slightly depending on the
     type of monitor  being  used  (because  of  the  different frame sync
     periods). It defaults to approximately 40  seconds for a TV and about
     28 seconds when used in Hi Rez monochrome mode which corresponds to a
     value of 2000. To  change  the  delay  period  the  Delay function is
     called with a value in the range 1-4000 as follows :-

                     move.l          #200,-(sp)              ;200 * Vsync
                     move            #UPD_DELAY,-(sp)        ;DELAY mode
                     bsr             upd_driver              ;execute
                     add             #6,sp                   ;correct stk
                     tst.l           d0                      ;chk error
                     bmi             error                   ;bra if error
                     ...

     The printer is normally  sent  to  Device  Number  0 (parallel port),
     however the applications program may  want  to  send  the data to the
     serial port (or even the screen).  This  can  be done by changing the
     Device Number which is stored in  the  UPD look-up table at offset 48
     as shown in the look up table below.

     PRINTER DRIVER TEXT FILE
     ------------------------
     The Printer Driver Text (PDT) file itself is an ASCII text file which
     can be written using most  text  editors  such as Mortimer, Harlekin,
     etc. The file  information  consists  of  a  number  of  three letter
     mnemonics followed by  an  'equals'  sign  and  then  the appropriate
     control codes. The attribute  definitions  can  be placed anywhere in
     the text file but all letters must  be in capitals. Any numeric value
     may be written in  decimal  or  hexadecimal notation. Decimal numbers
     may have any number of digits and hexadecimal values must have one or
     two digits  and  be  preceded  by  a  dollar  sign.  For  example the
     following values are all valid :-

             10, 0010, $A, $0A

     Two typical attribute definitions could be written as follows :-

     LP6=27,38,108,54,68                        ;6 Lines/inch
     LP8=$1B,$26,$6C,$38,$44                    ;8 Lines/inch

     which defines the codes  for  setting  the  printer  to print six and
     eight lines to the inch. LP6/LP8 are the mnemonics and the decimal or
     hex codes follow the 'equals'  sign,  each  code being separated by a
     comma (actually almost any  non-alphanumeric  character will do). The
     semicolon denotes an optional comment,  all  text after the semicolon
     is ignored. Space characters ($20), tab characters ($09) and linefeed
     characters ($0A) are ignored by the UPD program when the text file is
     processed. A Carriage Return character ($0D) must terminate each line
     and a NUL character ($00) must terminate the file.

     The list of text attributes is more or less similar to the list shown
     above with the following  exceptions.  In  order  to simplify the PDT
     file a bit any attributes which  operate  in pairs are written on the
     same line and separated  by  a  'colon'.  For  example, the BOLD type
     attribute is written as :-

     BLD=27,40,115,51,66 : 27,40,115,48,66      ;Bold on/off

     The first group of codes turns  the  function on and the second group
     turns the same function off and  is equivalent to the attribute codes
     BLD1 and BLD0 respectively. The only  other 'reserved' symbol used in
     these text files is the hash sign (#)  which is used to denote that a
     numeric value is passed  to  the  UPD  routine  when  the function is
     invoked. For example, on some printers  a  colour code can be sent to
     the printer to start printing in  colour.  This would be written down
     as follows :-

     COL=27,114,#                            ;Colour code

     When this function is used the PDT file will supply the control codes
     and the  applications  program  will  provide  the  colour  number as
     described earlier.

     In addition to the text attributes listed above there are a number of
     other codes which can (and in some cases must) be used in a PDT file.
     These are as follows :-

     UPD=1
     This code identifies the text  file  as  a  valid Printer Driver Text
     file and must be present somewhere  in the file. The number following
     the equals sign should be the digit 1  to denote version 1 of the UPD
     program. This value may  be  used  at  a  later date to differentiate
     between later versions of the  UPD  program.  If  the UPD code is not
     present the  driver  will  return  with  an  error  code  during  the
     initialisation phase.

     PTS='string'
     This code defines the  Printer  Title  String  and  is followed by an
     ASCII string within single quotes which  gives the full title/name of
     the printer. The string can be  any  length  but should be limited to
     less than 35 characters  and  could  be  used   by  the  applications
     program  to  display  a  full  description  of  the printer on screen
     when the file has been loaded.

     GCM=2
     Some modern HP printers can receive graphics data into the printer in
     compressed mode which speeds  up  the  data  transfer. If the printer
     supports this option this code is  included  in the PDT file followed
     by the compression  code  used.  At  present  only  mode  2 (TIFF) is
     supported by the UPD program although other modes may be added later.

     GM0-GM7
     These codes define which graphics modes and resolutions are available
     in the printer, a maximum of  eight  can be used. Most printers allow
     more than one graphics resolution and some printers can even print in
     different graphics modes, i.e. 8  pin,  24  pin and 48 pin. Obviously
     the UPD program has to know which  resolution is to be used and which
     graphics mode it needs to use.  This  group of codes defines the mode
     and resolutions (in dpi) that are available.

     For example, the Canon BJ300 Ink  Jet  printer can simulate 9 pin, 24
     pin and 48 pin graphics  at  various  resolutions, the Graphics Modes
     would be written like this :-

             GM0=1,120*72                            ;120*72 dpi, 8 pin
             GM1=1,240*72                            ;240*72 dpi, 8 pin
             GM2=21,180*180                          ;180*180 dpi, 24 pin
             GM3=21,360*180                          ;360*180 dpi, 24 pin
             GM4=31,120*360                          ;120*360 dpi, 48 pin
             GM5=31,180*360                          ;180*360 dpi, 48 pin
             GM6=31,240*360                          ;240*360 dpi, 48 pin
             GM7=31,360*360                          ;360*360 dpi, 48 pin

     The graphics modes (1, 21 and 31) are stored in the look up table and
     are used by  the  UPD  program  to  determine  the  method of sending
     graphics data to the printer.  The  resolutions (120*72, 240*72, etc)
     are also stored in the look  up  table  and although these values are
     not used by the UPD program,  they  are available to the applications
     program which can find out what  graphics resolutions can be used and
     from that, what size any image will  be  when printed out. To print a
     graphics  image  the  applications   program   will  first  choose  a
     resolution code from the list (usually one which has the x and y axes
     the same such as 180*180 or 360*360)  and uses the associated GM code
     (say 2 or 7 for 180*180 or 360*360).

     GR0-GR7
     In addition to the GM codes above,  there are also a similar group of
     Graphics Resolution codes (GR0-GR7)  which  define the actual control
     codes required for each graphics resolution.  There must be a GR code
     for each GM code  and  they  define  the  control  codes used for the
     corresponding  graphics  mode  usually  followed   by  a  hash  which
     indicates the data stream for  dot  matrix printers. Laser and InkJet
     printers are slightly different, in  this  case the codes will define
     the graphics resolution codes (see two examples below).

     MF0-MF7
     For dot matrix printers it  is  necessary  to move the print carriage
     down a number of microlines after each line of graphics is printed so
     that the image is continuous in the vertical axis. Since these may be
     different for different resolutions,  there  is  a MicrolineFeed code
     for each resolution (MF0-MF7). HP  Laser  and  InkJet printers do not
     need this facility and so they can be omitted for these printers.

     Two typical Printer Driver Text files are shown below.

     Typical Printer Driver text file for a Laser printer.
     ---------------------------------------------------------------------
     UPD=1                                      ;Version 1

     PTS='HP LaserJet 3'                        ;Printer type

     GM0=51,75*75                               ;75*75 dpi
     GM1=51,100*100                             ;100*100 dpi
     GM2=51,150*150                             ;150*150 dpi
     GM3=51,300*300                             ;300*300 dpi
     GCM=2                                      ;Compression mode 2

     RES=27,69                                  ;Reset
     BLD=27,40,115,51,66 : 27,40,115,48,66      ;Bold on/off
     ITA=27,40,115,49,83 : 27,40,115,48,83      ;Italics on/off
     PPT=27,40,115,49,80 : 27,40,115,48,80      ;Proportional on/off
     SUB=27,38,97,43,48,46,50,53,82 : 27,38,97,45,48,46,50,53,82   ;Subscr
     SUP=27,38,97,45,48,46,50,53,82 : 27,38,97,43,48,46,50,53,82   ;Super
     ULN=27,38,100,48,68 : 27,38,100,64         ;Underline on/off
     PMC=27,38,108,#,88                         ;Print multiple copies
     LP6=27,38,108,54,68                        ;6 Lines/inch
     LP8=27,38,108,56,68                        ;8 Lines/inch

     C10=27,38,107,48,83                        ;10 cpi
     C12=27,38,107,52,83                        ;12 cpi
     C17=27,38,107,50,83                        ;16.67 cpi

     GR0=27,42,116,55,53,82                     ;75*75 dpi
     GR1=27,42,116,49,48,48,82                  ;100*100 dpi
     GR2=27,42,116,49,53,48,82                  ;150*150 dpi
     GR3=27,42,116,51,48,48,82                  ;300*300 dpi

     HLF=26,61                                  ;Half Line Feed
     ---------------------------------------------------------------------


     Typical Printer Driver text file for a 24pin printer.
     ---------------------------------------------------------------------
     UPD=1                                      ;Version 1

     PTS='Epson LQ2500 24 pin'                  ;Printer type

     GM0=21,60*180
     GM1=21,120*180
     GM2=21,90*180
     GM3=21,180*180
     GM4=21,360*180

     RES=27,64                                  ;Reset
     BLD=27,69 : 27,70                          ;Bold
     ITA=27,52 : 27,53                          ;Italics
     PPT=27,112,1 : 27,112,0                    ;Proportional
     SUB=27,83,1 : 27,84                        ;Subscript
     SUP=27,83,0 : 27,84                        ;Superscript
     ULN=27,45,1 : 27,45,0                      ;Underline
     NLQ=27,120,1 : 27,120,0                    ;NLQ
     UNI=27,85,1 : 27,85,0                      ;Unidirectional
     LP8=27,48                                  ;8 Lines/inch
     LP6=27,50                                  ;6 Lines/inch

     C05=27,87,0,18,27,80,27,87,1               ;5 cpi
     C06=27,87,0,18,27,77,27,87,1               ;6 cpi
     C10=27,87,0,18,27,80                       ;10 cpi
     C12=27,87,0,18,27,77                       ;12 cpi
     C15=27,87,0,18,27,103                      ;15 cpi
     C17=27,87,0,18,27,80,15                    ;17 cpi
     C20=27,87,0,18,27,77,15                    ;20 cpi

     GR0=27,42,32,#                             ;60*180 dpi
     GR1=27,42,33,#                             ;120*180 dpi
     GR2=27,42,38,#                             ;90*180 dpi
     GR3=27,42,39,#                             ;180*180 dpi
     GR4=27,42,40,#                             ;360*180 dpi
     MF0=27,51,24                               ;Microfeed 24*180"
     MF1=27,51,24                               ;Microfeed 24*180"
     MF2=27,51,24                               ;Microfeed 24*180"
     MF3=27,51,24                               ;Microfeed 24*180"
     MF4=27,51,24                               ;Microfeed 24*180"
     ---------------------------------------------------------------------

     UPD LOOK UP TABLE
     -----------------
     When the UPD program is first  initialised  it scans the PDT file and
     generates a look-up table in a  memory  buffer in which it stores all
     the relevant information required  to  print  text and graphics data.
     The start address of this table  is  returned  by the UPD routine and
     should be stored for  later  use.  The  applications program can then
     read the data from the table to find the printer name, determine what
     graphics  resolutions  are  available,   which  text  attributes  are
     available, etc.

     The table is made up of three sections, section 1 holds miscellaneous
     information, section 2 holds a list of  offset values for each of the
     text/graphics attributes and section 3  holds the control strings for
     each attribute. The table layout is  shown  below with a (very) brief
     description of each  store,  later  documentation  will  go into more
     detail on this.

     Offset from    Store    Ref     Function.
     start address. size.

     Section 1. Miscellaneous control information.

             0       W       -       Offset to section 2.
             2       W       PTS     Offset to Printer Title String.
             4       B       GM0     Graphics Group Mode 0
             5       B       GM1     Graphics Group Mode 1
             6       B       GM2     Graphics Group Mode 2
             7       B       GM3     Graphics Group Mode 3
             8       B       GM4     Graphics Group Mode 4
             9       B       GM5     Graphics Group Mode 5
             10      B       GM6     Graphics Group Mode 6
             11      B       GM7     Graphics Group Mode 7
             12      L       GM0     Graphics Resolution Group 0  x*y
             16      L       GM1     Graphics Resolution Group 1  x*y
             20      L       GM2     Graphics Resolution Group 2  x*y
             24      L       GM3     Graphics Resolution Group 3  x*y
             28      L       GM4     Graphics Resolution Group 4  x*y
             32      L       GM5     Graphics Resolution Group 5  x*y
             36      L       GM6     Graphics Resolution Group 6  x*y
             40      L       GM7     Graphics Resolution Group 7  x*y
             44      W       GCM     Graphics Compression Mode (0 or 2)
             46      W       UPD     Printer Driver Version code (1)
             48      W       -       Output Device Number (0)
             50      W       -       Printer Off-line delay period (2000)
             52      W       -       }
             54      W       -       }
             56      W       -       }Spare
             58      W       -       }

     Section 2. Attribute stores.
     Each store contains a 16 bit offset  value (from the start address of
     the file) to the associated control  code  string  in section 3. If a
     store contains zero, the attribute is not supported by the printer.

             0       W       -       Not used
             2       W       RES     Reset printer
             4       W       BLD1    Bold text enable
             6       W       BLD0    Bold text disable
             8       W       ITA1    Italics text enable
             10      W       ITA0    Italics text disable
             12      W       PPT1    Proportional text enable
             14      W       PPT0    Proportional text disable
             16      W       SUB1    Subscript text enable
             18      W       SUB0    Subscript text disable
             20      W       SUP1    Superscript text enable
             22      W       SUP0    Superscript text disable
             24      W       ULN1    Underline text enable
             26      W       ULN0    Underline text disable
             28      W       CPB     Clear printer buffer
             30      W       PMC     Print multiple copies #
             32      W       UNI1    Unidirectional printing on
             34      W       UNI0    Unidirectional printing off
             36      W       LP6     Print 6 lines per inch
             38      W       LP8     Print 8 lines per inch
             40      W       C05     Print 5 chars per inch
             42      W       C06     Print 6 chars per inch
             44      W       C09     Print 9.5 chars per inch
             46      W       C10     Print 10 chars per inch
             48      W       C12     Print 12 chars per inch
             50      W       C15     Print 15 chars per inch
             52      W       C17     Print 17 chars per inch
             54      W       C20     Print 20 chars per inch
             56      W       NLQ1    Near Letter Quality enable
             58      W       NLQ0    Near Letter Quality disable
             60      W       GR0     Graphics resolution group 0
             62      W       GR1     Graphics resolution group 1
             64      W       GR2     Graphics resolution group 2
             66      W       GR3     Graphics resolution group 3
             68      W       GR4     Graphics resolution group 4
             70      W       GR5     Graphics resolution group 5
             72      W       GR6     Graphics resolution group 6
             74      W       GR7     Graphics resolution group 7
             76      W       MF0     MicroLine feed group 0
             78      W       MF1     MicroLine feed group 1
             80      W       MF2     MicroLine feed group 2
             82      W       MF3     MicroLine feed group 3
             84      W       MF4     MicroLine feed group 4
             86      W       MF5     MicroLine feed group 5
             88      W       MF6     MicroLine feed group 6
             90      W       MF7     MicroLine feed group 7
             92      W       COL     Select colour code #
             94      W       HLF     Half Line Feed
             96      W       -       Spare
             98      W       -       Spare

     Section 3. Control code strings.
     This section consists of a group  of  control code strings, the first
     byte of each string defines the  length  of the string minus one. The
     strings for each attribute may  be  in  any  order depending on where
     they are situated in the PDT file.

             100     B       05,1B,3E,4D,44,97,A0
             107     B       03, etc, etc, etc

     The exact size of  the  table  will,  of  course,  depend on how many
     attributes are used and how long the control code strings are.

     ERROR CODES
     -----------
     When any UPD function is called  the routine normally returns a value
     of zero in register d0 (except  for the initialisation function which
     returns the look-up table start address).  If an error is detected, a
     negative error code is returned in d0 as shown below :-

     -101    Invalid printer driver text file.
     -102    Printer off-line.
     -103    Invalid function code.
     -104    Unused attribute code.
     -105    Invalid attribute code.
     -106    Insufficient RAM available or invalid address.
     -107    Graphics mode not initialised correctly.
     -108    Mismatch on multiple codes.
     -109    Graphics mode already initialised.
     -110    Invalid resolution requested.
     -111    Invalid printer off-line delay period requested.

     More details  of  these  error  codes  will  be  published  in future
     documentation.

     CONCLUSION
     ----------
     The above notes are a brief  description  of  the work I have done on
     the Printer Driver so far.  I  have  written  the  code to handle the
     facilities listed and successfully tried the program out with several
     dot matrix and Laser printers in  machine  code. When the program has
     been finalised I will (with the help  of some members I hope) provide
     examples in other languages, i.e. C,  GFA, STOS, Modula 2, Pascal and
     Basic.

     I have also written a test program  which prints a test print of each
     attribute and graphics mode at all available resolutions. One notable
     omission from the current version is  colour. I don't know how modern
     ink jet colour printers work so if you want that option added, please
     let me know how to do  it  or  at  least  how colour printers work. I
     could be wrong but I  suspect  that  dot matrix colour printers would
     not be capable of printing  'proper'  colour  pictures. When the test
     program is complete I will  put  it  on  a  future  disk so that each
     member can write a driver file for their own printer/s.

     Also I have not taken into account any foreign (non English) users. I
     would assume that a printer working in a non English speaking country
     would already be set  up  to  print  the  extra  characters and so no
     changes would need  to  be  made  to  the  driver  code. One possible
     exception could be the  resolution  definitions, presumably in Europe
     these are defined as dots per centimetre.

     If you have any comments on these notes please let me know as soon as
     possible, I would like to finalise to code as quickly as possible and
     issue it 'officially'.  PDH.

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