Skip to main content

 "You owe everything an apology."
                    Marcy, addressing Al, "Married with Children"


                YOUR SECOND GFA BASIC 3.XX MANUAL
                             - or -
        HOW I LEARNED TO STOP WORRYING AND LOVE GFA-BASIC
                             PART 22
               CHAPTER TWENTY - GRAPHICS (PART 2)
                          by Han Kempen

VQT_EXTENT

 The function VQT_EXTENT can be used if you would like to draw  a
rectangle around a text-string:

     ~VQT_EXTENT(txt$,x1,y1,x2,y2,x3,y3,x4,y4)

 The  coordinates of the four corners depend on the angle of  the
text (0, 90, 180 or 270 degrees) and of course on the size of the
text. The point (x1,y1) is the lower left corner of the imaginary
rectangle  around  the  text and the other  points  are  arranged
anticlockwise  around the text-string.  Because the text  rotates
around  the TEXT-coordinates (start of the  Base-Line),  it  will
take  some trial and error to determine the correct  position  of
the  rectangle if the angle is not 0 degrees.  In  the  following
table you'll find the "true" origin of the rectangle,  the  width
and the height of the rectangle,  and also the actual position of
the lower left corner of the text-block (x1,y1):

     angle     position (x1,y1)    origin    width     height
        0         lower left        x1,y1     x2         y4
      900         lower right       x4,y4     x1         y3
     1800         upper right       x3,y3     x4         y2
     2700         upper left        x2,y2     x3         x4

 The coordinates of the origin are (0,0),  so with an angle of  0
degrees both x1 and y1 are 0.  The rectangle rests on the x-axis,
while  the  left  side  coincides with  the  y-axis.  This  is  a
"mathematical" y-axis,  not a "screen" y-axis.  This means you go
upwards  for  positive y-values.  For an angle of 0  degrees  the
coordinates will be:

     (x4,y4).           .(x3,y3)
            . TEXTBLOCK .
     (x1,y1)             (x2,y2)

 If  you  understand the table,  you should be surprised  by  the
height 'x4' instead of 'y1' at an angle of 270 degrees. I think I
discovered  a  bug  in GEM here.  Correct  GEM  by  changing  the
following variables if an angle of 270 degrees is used:

     y1=x4
     SWAP x4,y4

 Now,  the height is 'y1' as you suspected.  Clever, aren't we? I
have not been able to confirm my discovery. None of my reference-
books  mention  the  bug.   Perhaps  it's  not  a  bug,   but  my
imagination.

 And  then  there is a terrible GFA-bug as well:  in  a  compiled
program all coordinates are 0.  Sigh.  If you use the alternative
VQT_EXTENT-command   you'll   find  the   coordinates   both   in
interpreted and in compiled programs:

     ~VQT_EXTENT(txt$)
     x1=PTSOUT(0)
     y1=PTSOUT(1)
     x2=PTSOUT(2)
     (...)
     y4=PTSOUT(7)

Line-A

 The  Line-A  commands  are faster than  the  corresponding  VDI-
commands in GFA-Basic.  Commands such as PSET, PTST and HLINE are
two  to  three times faster than the  corresponding  VDI-commands
PLOT, POINT and LINE. The difference should be even greater after
loading GDOS.  The syntax of Line-A commands is more complicated,
but that's no problem for us GFA-experts. Line-A commands use the
SETCOLOR-index, not the VDI colour-index (see paragraph 'SETCOLOR
and VSETCOLOR' in this chapter). Because GFA uses Line-A commands
for sprites,  you need a SETCOLOR-index for sprites as well  (see
paragraph 'SPRITE')

 Of  course it's completely legal to use Line-A  commands.  Atari
has  sworn  an oath that you always will be able  to  use  Line-A
commands.  Until the world ends, or they change their mind. Atari
now recommends to avoid all the  hardware-specific  TOS-routines,
including Line-A commands. Remember their other promise, that the
BIOS system-variables (&H400 - &H4FF) are cast in  concrete?  Let
us pray they don't dump these variables in a lake. Amen.

HLINE

 An additional advantage of the commands HLINE,  ARECT and APOLY,
apart  from the gain in speed,  is that you don't have to  change
the DEFFILL-parameters in the main program.  For solid horizontal
lines, use:

     pattern&=-1
     adr%=V:pattern&
     HLINE x1,y,x2,color,mode,adr%,0

 You  can't  use &X1111111111111111 (16 bits)  for  the  pattern,
because  bit  15  of a word-variable is a  flag  for  a  negative
number.  Yes,  that's  why the largest positive word is 2^15 -  1
(32767).  The solution to this little problem is to assign -1  to
the word-variable.  You have my word,  now all 16 bits are 1. Use
BIN$ if you don't believe me.  That's an insult, I gave you my 16
bits, didn't I?

 For very complicated patterns you could use a word-array:

     DIM pattern&(i)
     adr%=V:pattern&(0)
     (...)               ! put fill-pattern in pattern&(0)
                              to pattern&(i)
     HLINE x1,y,x2,color,mode,adr%,i

ACHAR and ATEXT

 It's  difficult to combine the Line-A commands ACHAR  and  ATEXT
with  TEXT.  The coordinates used with ACHAR and ATEXT  determine
the position of the left upper corner of the (first)  letter-box.
That's the Top-Line, not the Base-Line (see paragraph 'DEFTEXT').

 With TEXT you can use GRAPHMODE,  but you can't select a graphic
mode for ACHAR and ATEXT.

 You  can't  use  the text-style underlined (8)  with  ACHAR  and
ATEXT. Probably a GFA-bug.

SGET and SPUT

 A  regular  ST-screen  (32,000 bytes  in  High,  Medium  or  Low
resolution)  fits  in a string,  but larger screens  can  not  be
handled.  SGET  and  SPUT  are useless if the  screen  is  larger
because  a  string  can't contain  more  than  32767  bytes.  TT-
programmers have to MALLOCate their own solution to this problem.

GET and PUT

 You can save any rectangular part of the screen as a file:

     GET x1,y1,x2,y2,pic$          ! a GET-picture
     BSAVE file$,V:pic$,LEN(pic$)  ! use the extension PUT in
                                         the filename

 Later,  you  could put the saved GET-picture back on the  screen
with:

     OPEN "I",#1,file$
     LET bytes%=LOF(#1)            ! how many bytes needed?
     CLOSE #1
     picture$=SPACE$(bytes%)       ! reserve some space,
     BLOAD file$,V:picture$        ! load the GET-picture
     PUT x,y,picture$              ! careful: insensitive to CLIP-settings

 Loading/saving several GET-pictures not only takes time,  but it
also  wastes  a lot of valuable space on  your  disk.  Each  file
occupies at least 1 K,  e.g. 10 small GET-rectangles occupy 10 K!
If  you  create  an array of the GET-pictures you  can  save  the
entire array in one file.

 Loading a file is very boring for the user,  so you should avoid
it if possible.  You can avoid the loading of a GET-picture,  but
you have to do some extra work.  Don't start complaining, because
that's  what you're paid for as a programmer.  Transfer the  GET-
picture to an INLINE-line in your program.  If you then BMOVE the
picture  to  a  string you can PUT the picture  anywhere  on  the
screen.  I'll  assume  you have a GET-picture in a  file  with  a
length  of 2000 bytes.  After loading the file in an  INLINE-line
you can use the following method:

     INLINE picture%,2000
     picture$=SPACE$(2000)              ! create string for pic
     BMOVE picture%,V:picture$,2000     ! put picture in string
     PUT x,y,picture$                   ! show the picture

 A  disadvantage  of this method is that the  picture  is  stored
twice in memory:  in the INLINE-line and in the string.  Why  not
assign  a  string-variable  to the picture  in  the  INLINE-line?
Sounds easy,  but it isn't.  I'll assume you have the same  2000-
byte picture as a file.  Add 10 to this length for the descriptor
(6 bytes) and backtrailer (4 bytes) of the string we are going to
create. Load the picture and run this:

INLINE picture%,2010
BMOVE picture%,picture%+6,2000      !# make room for descriptor
' Alternative method if the pic is available as GET-string pic$:
BMOVE V:pic$,picture%+6,2000        !# move pic from GET-string
LONG{picture%}=picture%+6           !# address of string
WORD{picture%+4}=LEN(pic$)          !# string-length
LONG{picture%+LEN(pic$)+6}=picture% !# backtrailer
picture$=""                         !  create string-variable
ABSOLUTE picture$,picture%          !  assign GET-pic to string

 After  this operation you can delete all lines marked with  '#'.
The GET-picture is now immediately available in the program:

     PUT x,y,picture$

 A  GET-string starts with two words for the x- and  y-coordinate
of  the lower right corner (relative to the upper left corner  at
0,0)  and  one word for the number of bitplanes.  The  number  of
bitplanes  is determined by the resolution:  1 for  High,  2  for
Medium  and 4 for Low.  The three-word header of a GET-string  is
contructed as follows:

     header$=MKI$(x)+MKI$(y)+MKI$(bitplanes)

 These  three words are followed by the actual picture as a  list
of words.  As the picture-width is not necessarily a multiple  of
16,  any bits beyond the right border will be ignored by the PUT-
command.  These bits are not 0, there's random garbage beyond the
border. If you need a 'clean' GET-string for some special purpose
you could proceed as follows:

     GET x1,y1,x2,y2,pic$          ! create GET-string
     pic$=STRING$(LEN(pic$),0)     ! clear the string
     GET x1,y1,x2,y2,pic$          ! 'clean' GET-string

 Here is the connection between GRAPHMODE and PUT-mode:

     GRAPHMODE                         PUT-mode
         1 (Replace)                     3 (default)
         2 (Transparent)                 7
         3 (Xor)                         6
         4 (Reverse Transparent)        13

 In the paragraph 'GRAPHMODE' you have found a method to invert a
rectangular part of the screen with PBOX.  Here is an alternative
method with GET/PUT:

     GET x1,y1,x2,y2,block$
     PUT x1,y1,block$,12                ! invert block
     (...)
     PUT x1,y1,block$,12                ! normal again

 I have encountered a few programs in GFA-Basic 2.0 where PUT was
used just outside the screen (I know:  bad,  bad,  bad).  In GFA-
Basic 3.0 the program didn't work. The same occurred in a program
where a picture was BLOADed a few bytes before the screen-RAM.  I
don't understand why GFA-Basic 3.0 doesn't accept this,  as there
is some unused space there (read the paragraph 'RAM'),  but  I've
learned  to correct this when I convert a program from  GFA-Basic
2.0 to version 3.0.

Degas-Pictures

 I declare Degas as the standard picture-format for GFA-Basic.  A
Degas  picture-file  contains not only the actual  picture  (same
format  as  SGET-picture),  but also the  colour-palette  of  the
picture  and  the resolution.  The original  Degas-files  have  a
length of 32034 bytes:

     1 word         - resolution
     16 words       - palette
     16000 words    - picture data

 You can check the resolution-word for the correct resolution  (0
=  Low,  1  = Medium,  2 = High),  but you can also look  at  the
extension of the filename (PI1/PI2/PI3 for  Low/Medium/High).  In
the  second  Degas-version (Degas Elite),  16 words  for  colour-
animation can be added after the picture data. Files with colour-
animation  have a length of 32066 bytes,  but Degas  Elite  files
without  colour-animation  are exactly the same as  the  original
files.

 A  Degas  Elite picture can (and really should!) be saved  in  a
compressed  format.  The  extensions  PC1/PC2/PC3  are  used  for
Low/Medium/High  resolution.   Also,   the  highest  bit  of  the
resolution-word is set as a flag for a compressed  picture.  With
the  proper  unpack-routines  you can show  a  compressed  Degas-
picture reasonably fast on the screen.

 If you have created a picture for one specific GFA-program,  you
should  put  it in an INLINE-line.  The GFA-program  will  become
larger,  but the picture is immediately available in the  program
and you can't lose the separate Degas-file.  You shouldn't  throw
the  Degas-file away,  just in case you accidentally corrupt  the
INLINE-line.  Assuming  there is no colour-animation,  you  could
proceed  as follows.  Load the uncompressed Degas-picture  in  an
INLINE-line.  Before  you show the Degas-picture you  change  the
palette (don't forget to save the current palette first) and then
you BMOVE the picture to the monitor:

     INLINE degas%,32034
     ~XBIOS(6,L:degas%+2)               ! change palette
     BMOVE degas%+34,XBIOS(2),32000     ! show pic on physical
                                              screen

Other Picture-Formats

 Although  I  declared Degas as the standard  picture-format  for
GFA-Basic,  there  are  many other formats.  GEM  bitmap  (.IMG),
Neochrome  (.NEO),  Tiny (.TN?) and Deluxe Paint(.IFF)  are  some
widely used picture-formats.  Don't try to load all these formats
in  your  GFA-programs,  but  use a (Public  Domain)  program  to
convert these pictures to Degas.  Try to find conversion-programs
such as IFFCNV or PicSwitch.  The GEM bitmap format is a  serious
candidate for a standard format,  but only for High resolution as
there  is no standard method to include the palette in  the  IMG-
file.

BMOVE and RC_COPY

 BMOVE  can  be  used to move blocks  of  memory  (e.g.  complete
number-arrays,  as described in the paragraph 'BMOVE' in  chapter
4). It is the first choice if you are going to move a screen-wide
block  of  the  physical  or the  logical  screen  (one  or  more
scanlines). In the paragraph 'Resolutions' you could already find
the length of a scanline in the three resolutions:

                               scanline
     High resolution           80 bytes
     Medium resolution        160 bytes
     Low resolution           160 bytes

 If  the screen-block is narrower than the screen-width you  have
to use the slower RC_COPY-command. And you can always use GET/PUT
if you don't mind the slower speed compared to BMOVE and RC_COPY.
With GET/PUT you are restricted to the logical screen,  but  with
BMOVE  and RC_COPY you can use physical  screen,  logical  screen
and/or  a  screen-buffer.  In  the following  example  the  three
methods  are used to move the first 16 scanlines of  the  logical
screen  (High  resolution)  16  scanlines  down.   The   original
scanlines remain unaltered, so this actually is a copy-method:

     GET 0,0,639,15,block$       ! upper 16 scanlines of
                                    logical screen
     PUT 0,16,block$,3           ! place block 16 scanlines down
     '
     RC_COPY XBIOS(3),0,0,640,16 TO XBIOS(3),0,16,3    ! faster
     '
     BMOVE XBIOS(3),XBIOS(3)+16*80,16*80               ! fastest

 With a narrower block you can't use BMOVE:

     GET 0,0,99,15,block$        ! block is 100 pixels wide
     PUT 0,16,block$,3
     '
     RC_COPY XBIOS(3),0,0,100,16 TO XBIOS(3),0,16,3    ! fastest

VSYNC

 The  VSYNC-command is useful if you want to  prevent  irritating
blinking  during  animation.  Always VSYNC before drawing  a  new
picture  in an animation sequence  (including  SPRITE-animation).
The  program  is slowed down of course,  because it waits  for  a
vertical  blank interrupt before starting to draw.  But it  looks
much nicer.

BITBLT

 BITBLT is supposed to be suitable for experienced  professionals
only.  Actually there are two BITBLT-commands available: one uses
VDI and the other Line-A.

 The VDI BITBLT-command needs three integer-arrays with a lot  of
parameters.  Twenty-one  parameters sounds  frightening,  but  14
parameters  are  more or less fixed,  so you only have  to  think
about 7 parameters.  That's 4 parameters for the source-rectangle
(x1,y1,x2,y2), 2 parameters for the destination-rectangle (x1,y1)
and 1 parameter for the copy-mode (same as PUT-mode). Sounds easy
now, doesn't it? Unfortunately this also means you can use BITBLT
for  exactly the same operations as BMOVE and  RC_COPY.  All  the
extra parameter-handling makes BITBLT even slower than BMOVE  and
RC_COPY.   You  might  as  well  forget  the  VDI  BITBLT-command
completely.  I don't understand why GFA calls this a VDI-command,
but you already forgot about this command,  so I won't bother you
with that.

 The  Line-A BITBLT-command is a different cup of tea.  Here  you
need 22 parameters (preferably in one integer-array), but this is
reduced to about 9 parameters that really matter.  This time  the
command offers more possibilities than BMOVE or RC_COPY,  but you
have  to understand everything about scanlines  and  byte-offsets
first.  If you do, you can use elements 10 and 16 of the integer-
array  to  do clever things.  And you can use elements  18-21  to
create  complicated  fill-patterns.   I'll  leave  that  to   the
professionals.

 Both BITBLT-commands are insensitive to any (A)CLIPping and  are
quite happy to blit bits everywhere in memory.  So be careful and
expect  your program to crash any time you test  your  thoroughly
debugged program.

ACLIP

 Line-A  commands  are 'CLIP-sensitive',  although they  are  not
supposed  to  be.  Just in case you forgot you  used  some  CLIP-
command  somewhere  else,  you should always use  an  appropriate
ACLIP-command  before  a Line-A  command.  The  following  Line-A
commands are not influenced by ACLIP though:  ALINE, HLINE, PSET,
PTST and BITBLT.

Blitter

 The  Blitter-TOS (1987) allows you to switch the Blitter  on/off
from GFA-Basic with the function XBIOS 64 (Blitmode).

                     Procedures (CHAPTER.20)

Bitblt_a_screen_init                           \BITBLT_A\SCR_INIT
Bitblt_a
                                                 BITBLT_A
 Copy a rectangle to the physical screen:
     @bitblt_a_screen_init(source.screen%)
     @bitblt_a(100,100,150,150,0,0,3,80,80)       ! for High res
 In  this case the box (100,100,150,150) from  the  source-screen
(usually an invisible second screen) is copied to position  (0,0)
on  the physical screen,  using PUT-mode 3.  For both source  and
destination  the  80  byte length of one scanline  is  used  (for
Medium or Low resolution you need 160 bytes). Special effects are
possible by changing these offsets.  Procedure Bitblt_a uses  the
Line-A BITBLT-command.

Bitblt_get_init                                  \BITBLT\GET_INIT
Bitblt_screen_init                                       SCR_INIT
Bitblt
                                                     BITBLT
 Copy a rectangle to the physical screen:
     @bitblt_screen_init(source.screen%)
     @bitblt(100,100,150,150,0,0,3)
 This  has  the same effect as the  previous  example,  but  it's
faster.  Procedure  Bitblt uses the VDI(?)  BITBLT-command.  It's
also possible to manipulate (a part of) a GET-string:
     @bitblt_get_init(block$,destination.screen%,x2,y2)
     @bitblt(50,50,x2,y2,0,0,3)
 Here  the rectangle (50,50,x2,y2) is copied from the  GET-string
to (0,0) on the destination-screen.  The GET-rectangle itself has
the coordinates (0,0,x2,y2).

Bitblt_                                           \BITBLT\SCROLL\
 back_reverse,curtain,iris,merge_all
                                   BACK_REV CURTAIN IRIS MERG_ALL

 merge_leftright,merge_topdown                   MERG_LR  MERG_TD
 put_modes
,random,roll_down            PUT_MODE  RANDOM  ROLLDOWN  
 roll_downup
,roll_right,roll_rightleft  ROLLDNUP  ROLL_R  ROLL_RL
 shrink,sliders,spiral4,vertical_blind
                                SHRINK  SLIDERS  SPIRAL4  V_BLIND
 These  are  all  scroll-Procedures that have  to  be  used  with
Procedures Bitblt_screen_init and Bitblt:
     @bitblt_screen_init(invisible.screen%)
     ' Put a picture on the invisible (logical) screen
     @bitblt_back_reverse               ! uses Procedure Bitblt

Blend                                                       BLEND
 Fade-over picture to the screen (several effects possible):
     ' Picture at address pic%
     @blend(pic%,effect,delay)          ! delay determines speed
 Best results in High resolution.

Blitter                                                   BLITTER
 Switch Blitter on or off (with Blitter-TOS only):
     @blitter(TRUE)                     ! switch Blitter on

Box_dimmer                                                BOX_DIM
 Dim a box (e.g. to tell the user that an option is unavailable):
     @box_dimmer(100,100,200,150)       ! box greyed out
     ' Do something
     @box_dimmer(100,100,200,150)       ! normal again

Box_reverse                                               BOX_REV
 Invert box (e.g. to tell user that an option has been selected):
     @box_reverse(100,100,200,150)      ! box inverted
     ' Do something
     @box_reverse(100,100,200,150)      ! normal again

Busy                                                         BUSY
 Fill  the entire High resolution screen with bees and  tell  the
user that we're very busy right now:
     @busy

Color_cycle and Cycle_every                              COLRCYCL
 Cycle colours from VDI colour-index c1 to c2 every ticks  (1/200
s):
     @color_cycle(c1,c2,200,TRUE)       ! cycle every second
     ' Do something else
     @color_cycle(c1,c2,200,FALSE)      ! switch cycling off

Colors_dim                                               COLORDIM
 Dim colours with VDI colour-index c1 to c2:
     @colors_dim(c1,c2)

Cube                                                         CUBE
 Draw a cube in High or Low resolution:
     @cube(x,y,width,color,fill)

Degas_inline_med_low                               \DEGAS\INL_LOW
 Show   a  Degas-picture  (stored  in  an  INLINE-line)  in   Low
resolution from a program running in Medium resolution:
     @degas_inline_med_low(picture1%,0)     ! waits for key/click
     @degas_inline_med_low(picture2%,5)     ! wait 5 seconds

Degas_inline_show                                 \DEGAS\INL_SHOW
 Show a Degas-picture that is stored in an INLINE-line:
     @degas_inline_show(picture%)
 A better idea than loading an uncompressed Degas-picture.

Degas_load                                            \DEGAS\LOAD
 Load a Degas-picture and the palette in strings:
     @degas_load(file$,picture$,palet$,ok!)
     IF ok!
       ' Degas-picture now available as SPUT-string picture$
     ELSE
       ' Something went wrong
     ENDIF
 The  Procedure  loads both uncompressed  and  compressed  Degas-
pictures. Colour-animation data are ignored.

Degas_load_show                                   \DEGAS\LOADSHOW
 Same  as  Degas_load,   but  now  the  Degas-picture  is   shown
immediately on the physical screen:
     @degas_load_show(file$,ok!)
     IF NOT ok!
       ' Something went wrong
     ENDIF

Degas_save                                            \DEGAS\SAVE
 The logical screen is saved as an uncompressed Degas-picture:
     @degas_save(file$,ok!)

Fill_border                                        \FILL\FILLBORD
 Fill an area within a coloured boundary:
     @fill_border(100,100,red)          ! stop FILLing at red
                                              boundary

Fill_1_high_init and Fill_high_creation             \FILL\FILL_HI
 Create a Fill-pattern for High resolution:
     @fill_1_high_init(pattern$)        ! create Fill-pattern
     DEFFILL ,pattern$                  ! activate pattern
     FILL 10,10                         ! use pattern

Fill_1_low_init and Fill_low_creation              \FILL\FILL_LOW
 Create a Fill-pattern for Low resolution.

Fill_1_med_init and Fill_med_creation              \FILL\FILL_MED
 Create a Fill-pattern for Medium resolution.

Fill_init                                          \FILL\FILLINIT
 Load a Fill-pattern from an INLINE-line in a string:
     @fill_init(adr%,pattern$)

Gem_image_load_show                             \PICTURE\IMG_SHOW
 Show a GEM bitmap picture (*.IMG) on the screen:
     @gem_image_load_show(file$,ok!)    ! High resolution only

Line                                                         LINE
 Let user draw a line on the screen and return the coordinates:
     @line(x1,y1,x2,y2)

Magnify                                                   MAGNIFY
 Put  a  magnified rectangular part of the  TOS-screen  somewhere
else on the screen:
     @magnify(0,0,10,10,100,0,8)        ! 8 times magnified
                                             at (100,0)

Message                                                   MESSAGE
 Show a centered message in reverse on the TOS-screen:
     @message(" This is a message ",25,TRUE)      ! on line 25
     ' Do something
     @message("",25,FALSE)                        ! restore scrn

Message_any_key                                          MESS_KEY
 Show  message "Press any key or mouse-button..." in  reverse  on
bottom line of TOS-screen and wait:
     @message_any_key

Message_time                                             MESS_TIM
 Show message in reverse on bottom line of TOS-screen and wait:
     @message_time("Read this",5)       ! show for 5 seconds

Mirror                                                     MIRROR
 Return mirror-image of a GET-string:
     @mirror(source$,0,mirror$)         ! vertical (1=horizontal)

Neochrome_load_show                             \PICTURE\NEO_SHOW
 Show a Neochrome-picture on the monitor:
     @neochrome_load_show(file$,ok!)
     IF NOT ok!
       ' Something went wrong
     ENDIF

Palet                                                \PALET\PALET
 Show current palette in a rectangle ('spectrum'):
     @palet(100,100,10,10)
 In  this  case  the left upper corner of  the  rectangle  is  at
(100,100)  and  both height and width of each  colour-box  is  10
pixels.

Palet_low                                         \PALET\PALETLOW
 Install a new Low-palette:
     @palet_low                         ! palette stored in
                                             DATA-lines

Palet_medium                                      \PALET\PALETMED
 Install a new Medium-palette:
     @palet_medium                      ! palette stored in
                                             DATA-lines

Palet_save_int and Palet_change_int                \PALET\PAL_INT
 Save  current palette in an integer-array and restore the  saved
palette later:
     @palet_save_int(palet%())          ! save palette
     ' Do something
     @palet_change_int(palet%())        ! restore palette

Palet_save_str and Palet_change_str                \PALET\PAL_STR
 Save current palette in a (Degas-compatible) string and  restore
the saved palette later:
     @palet_save_str(palet$)            ! save palette
     ' Do something
     @palet_change_str(palet$)          ! restore palette

Palet_string                                      \PALET\PALSTRNG
 Create a palette-string from DATA-lines:
     RESTORE this.palet
     @palet_string(palet$)              ! make palette-string
     @palet_change_str(palet$)          ! activate the palette

Picture_init                                              PICTURE
 Prepare a picture on an invisible logical screen and return  the
picture as a GET-string:
     RESTORE picture.data
     @picture_init(picture$)            ! uses Screen2_init
                                              & _restore
     PUT 50,50,picture$
     picture.data:
     DATA BOX,0,0,80,80
     DATA LINE 0,0,80,80
     DATA END
 This  Procedure recognizes  the  following  commands:   DEFLINE,
DEFTEXT, LINE, DRAW, BOX, RBOX, TEXT and END (=last command)

Point                                                       POINT
 Let user pick a point on the screen with the mouse:
     @point("Click on point",x,y)

Rectangle                                      \RECTNGLE\RECTNGLE
 User cuts GET-rectangle from TOS-screen:
     @rectangle(part$,x,y)           ! left upper corner at (x,y)
     CLS
     PUT 0,0,part$

Rectangle_array_load                           \RECTNGLE\REC_AR_L
 Load an array of GET-rectangles from disk:
     @rectangle_array_load(file$,ok!,picture$())
     IF ok!
       PUT 10,10,picture$(0)
       PUT 10,100,picture$(1)
     ENDIF

Rectangle_array_save                           \RECTNGLE\REC_AR_S
 Save an array of GET-rectangles on disk:
     @rectangle_array_save(file$,picture$())

Rectangle_flash                                \RECTNGLE\REC_FLSH
 Flash  a rectangle several times (especially suitable for  text-
boxes):
     @rectangle_flash(50,50,200,150,5)  ! flash 5 times

Rectangle_load                                 \RECTNGLE\REC_LOAD
 Load a GET-rectangle from disk:
     @rectangle_load(file$,ok!,clip$)
     IF ok!=TRUE
       PUT 50,50,clip$
     ENDIF

Rectangle_save                                 \RECTNGLE\REC_SAVE
 Save a GET-rectangle on disk:
     @rectangle_save(file$,picture$)

Rectangle_shadow                               \RECTNGLE\REC_SHDW
 Draw a rectangle with a shadow (3D-effect):
     @rectangle_shadow(30,30,100,100)

Res_low_medium and Res_medium_low                        RESLOMED
 Switch temporarily from Low to Medium resolution,  e.g.  to show
text:
     @res_low_medium("000","770","700","007",palet$)
     PRINT "This is a medium screen, shown from a program
                running in Low!"
     PRINT "In this example we use yellow letters on a black
                    screen."
     ~INP(2)
     @res_medium_low(palet$)       ! back to Low
                                         (restore palette too)

Screen_cls_down                                    \SCRN_CLS\DOWN
 Clear screen by scrolling the screen downwards:
     @screen_cls_down(2,black)     ! steps of 2 scanlines;
                                              make black

Screen_cls_luxaflex                            \SCRN_CLS\LUXAFLEX
 Clear the screen with a luxaflex-effect:
     @screen_cls_luxaflex

Screen_cls_scroll                                \SCRN_CLS\SCROLL
 Clear  the  screen with an upwards scrolling  rectangle  in  the
current foreground-colour (usually black):
     @screen_cls_scroll

Screen_cls_shrink                                \SCRN_CLS\SHRINK
 Clear  the screen with a shrinking rectangle in the  foreground-
colour (usually black):
     @screen_cls_shrink

Screen_cls_up                                        \SCRN_CLS\UP
 As Screen_cls_down, but screen scrolls upwards.

Screen_convert                                   \SCREEN\SCRNCONV
 Convert  picture  on logical screen (from wrong  resolution)  to
current  resolution (especially suitable to show a Medium or  Low
picture in High):
     ' Load Medium picture in logical screen
     @screen_convert(1)                 ! convert picture to High

Screen_dimmer                                    \SCREEN\SCRN_DIM
 Dim  entire screen,  e.g.  to indicate that some  time-consuming
action is going on):
     @screen_dimmer(black,TRUE)         ! use black colour
     ' Do something
     @screen_dimmer(black,FALSE)        ! restore screen

Screen_fill                                      \SCREEN\SCRN_FIL
 Fill High screen with a Fill-pattern:
     @screen_fill(adr%)

Screen_invert                                    \SCREEN\SCRN_INV
 Invert entire High screen:
     @screen_invert(TRUE)               ! invert screen
     ' Do something
     @screen_invert(FALSE)              ! restore screen

Screen_shrink                                    \SCREEN\SCRSHRNK
 Shrink screen,  e.g.  to be able to show small copies of several
pictures together on one screen:
     @screen_shrink(2,physbase%,physbase%,pic$)   ! quarter size

Scroll_init                                      \SCROLL\SCR_INIT
Scroll_cover
,drop,luxaflex,middle   COVER  DROP  LUXAFLEX  MIDDLE
 middlepush,random
,rolldown,slider
                                MIDPUSH  RANDOM  ROLLDOWN  SLIDER
 spiral,strips,uncover,up,venetian
                            SPIRAL  STRIPS  UNCOVER  UP  VENETIAN
 Scroll second screen on physical screen:
     @scroll_init        ! activate invisible second screen
     ' Put something nice on the invisible logical screen
     @scroll_cover       ! scroll down, covering current
                              monitor-picture

Scroll_text_down                                         SCRLTXTD
 Scroll text-lines one line down on the TOS-screen:
     @scroll_text_down(1,5)             ! scroll line 1 - 5 one
                                             line down
 This  is much faster than rePRINTing lines 1 - 5 again one  line
down.

Scroll_text_up                                           SCRLTXTU
 Scroll text-lines one line up on the TOS-screen:
     @scroll_text_up(2,8)               ! scroll line 2 - 8 one
                                              line up

Spectrum_load_show   )                          \PICTURE\SPECSHOW
 Put a Spectrum 512 picture on the screen:
     @spectrum_load_show(file$,ok!)     ! press a key to continue
 Not all (old) ST's are able to show 512 colours.

Sprite_init_1 and Sprite_creation                          SPRITE
 Create a sprite from DATA-lines:
     @sprite_init_1(sprite1$)

Text_3d                                             \TEXT\TEXT_3D
 Create 3D-letters with TEXT:
     @text_3d(10,10,"3D",black,26,0)    ! size 26, angle 0

Text_at                                             \TEXT\TEXT_AT
 Same effect as PRINT AT(column,line), but uses TEXT:
     @text_at(1,5,"Printed with TEXT at column 1, line 5")
 You can use this Procedure to mix PRINTed text with TEXT-effects
such as bold, underlined, italics, etc.

Text_box                                           \TEXT\TEXT_BOX
 Put a text in a box:
     @text_box(column,line,3,black,black,"Text in a box")
 The start-position of the box is determined by column and  line.
In  this case the line-width of the box is 3 (if width  is  0,  a
double line is drawn) and black is used both for the box and  the
text.

Text_box_center                                    \TEXT\TEXT_CEN
 Put a text in a centered box:
     @text_box_center(3,black,black,"Text in a centered box")
 Same  as  Procedure Text_box,  but now the box  appears  in  the
middle of the screen.

Text_box_invert                                    \TEXT\TXET_BOX
 Put inverted text (standard size) in a box:
     @text_box_invert(x1,y1,x2,y2," Inverted text in a box ")
 By the way,  the filename is indeed TXET_BOX (inverted TEXT, get
it?)

Text_extent  5)                                    \TEXT\TEXT_EXT
 Return width and height of a TEXT-string:
     TEXT 50,50,"Measure this text"
     @text_extent("Measure this text",width,height)
 You  can now draw a rectangle around the text,  although  that's
not easy.

Text_parameters                                    \TEXT\TEXT_PAR
 Return current DEFTEXT-parameters:
     @text_parameters(colour,attributes,angle,height)

Text_shadow                                        \TEXT\TEXT_SHD
 Create large letters (size 26) with shadow-effect:
     @text_shadow(50,100," S H A D O W S ")

Textstyle_alert                                    \TEXT\TEXTSTYL
 Change text-style for ALERT (and FILESELECT):
     @textstyle_alert(1)
     ALERT 1,"A bold Alert-box",1,"OK",k

Tiny_load_show                                  \PICTURE\TINYSHOW
 Show a Tiny picture on the monitor:
     @tiny_load_show(file$,ok!)
 Too slow!

                     Functions (CHAPTER.20)

Digital$                                                  DIGITAL
 Return a number with 'LCD'-digits:
     TEXT 50,100,@digital$("128")

Rgb_value$                                                RGB_VAL
 Return RGB-string of a VDI colour-index:
     PRINT "Background-colour is: &H";@rgb_value$(0)
     PRINT "PRINT-colour is: &H";@rgb_value$(1) 

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.