Skip to main content
? Erik 'ES of TEX' Simon, 1989

 "Mark,"  complained  a mother to her  son,  "every  time  you're
naughty, I get another gray hair!"
 "Gee,  Mom," the little darling replied,  "you must have been  a
terror! Just take a look at Grandma!"


                YOUR SECOND GFA BASIC 3.XX MANUAL
                             - or -
        HOW I LEARNED TO STOP WORRYING AND LOVE GFA-BASIC
                             PART 9
                 CHAPTER EIGHT - KEYBOARD INPUT
                          by Han Kempen

INKEY$

 All  keypresses are saved in the keyboard-buffer.  If  you  want
INKEY$  to  forget old keypresses,  you should  first  clear  the
buffer:

     REPEAT
     UNTIL INKEY$=""          ! clear keyboard-buffer
     key$=""                  ! clear variable key$
     REPEAT
       key$=INKEY$
     UNTIL key$<>""           ! wait for new keypress

 An  alternative way to clear the keyboard-buffer uses  XBIOS  14
(Iorec):

     {ADD(XBIOS(14,1),6)}=0   ! clear keyboard-buffer

 In  the following table you'll find a few useful decimal  ASCII-
codes  you can use after 'key$=INKEY$'.  In the third column  the
hexadecimal scan-code of the key is also mentioned (see paragraph
'KEYGET').

     key                   ASC(key$)       scancode
     <Backspace>               8             &H0E
     <Tab>                     9             &H0F
     <Return> and <Enter>     13             &H1C and &H72
     <Esc>                    27             &H01
     <Delete>                127             &H53

     key               ASC(RIGHT$(key$))   scancode
     <F1>                     59             &H3B
     <F10>                    68             &H44
     <Shift> <F1>             84             &H54
     <Shift> <F10>            93             &H5D
     <Help>                   98             &H62
     <Undo>                   97             &H61
     <Insert>                 82             &H52
     <ClrHome>                71             &H47
     <Left Arrow>             75             &H4B
     <Right Arrow>            77             &H4D
     <Up Arrow>               72             &H48
     <Down Arrow>             80             &H50

 Keys  in  the second part of this table return  a  2-byte  value
after INKEY$,  although the high byte is always &H00  (e.g.  <F1>
returns  &H003B).  This is important if you would like to  define
one of these keys as a variable:

     help$=CHR$(0)+CHR$(98)   ! high byte is &H00
     key$=INKEY$
     IF key$=help$
       (...)                  ! user pressed <Help>
     ENDIF

 Of course, you could also use the following method:

     key$=INKEY$
     IF ASC(RIGHT$(key$))=98
       (...)                  ! <Help>
     ENDIF

 It's  impossible  to detect a <Shift> <Arrow>  combination  with
INKEY$,  because  a  one-byte  value of an existing  (!)  key  is
returned: CHR$(50), (52), (54) and (56) for <Shift> <Down Arrow>,
<Left Arrow>,  <Right Arrow> and <Up Arrow>.  You'll need  KEYGET
(page  8-5)  or  ON  MENU  (page  21-3)  to  detect  these   four
combinations.

 If you are just waiting for any keypress,  you could use  either
of the following methods (clear the keyboard-buffer first):

     ~INP(2)             ! my favourite (unless EVERY is active)
     '
     KEYGET code%        ! perhaps this is clearer in a listing
     '
     REPEAT              ! a loop is also possible
     UNTIL LEN(INKEY$)

 The  loop-method  could  be  used if you  are  waiting  for  any
keypress or any mouse-click :

     {ADD(XBIOS(14,1),6)}=0        ! clear keyboard-buffer
     WHILE MOUSEK                  ! mouse-buttons released?
     WEND
     REPEAT                        ! wait for any keypress or
                                                      mouse-click
     UNTIL LEN(INKEY$) OR MOUSEK

INPUT

 If you don't want the question mark to appear after INPUT, use:

     LOCATE col,lin
     INPUT "",txt$

 The  nullstring and the comma are essential.  Most of  the  time
you'll probably use something like:

     LOCATE col,lin
     INPUT "Enter your name: ",name$

 If  the instruction is not on the same line as  the  INPUT-line,
use:

     PRINT AT(col1,lin1);"Enter your name:"
     LOCATE col2,lin2
     INPUT "",name$

 The 'Alternate-method' can be used to input character-codes 128-
255  on a (LINE) INPUT line.  In the following table you'll  find
some important characters with the decimal ASCII-code:

character ASCII-code  character ASCII-code  character ASCII-code

   á    -    160         é    -    130         í    -    161
   à    -    133         è    -    138         ì    -    141
   ä    -    132         ë    -    137         ï    -    139
   â    -    131         ê    -    136         î    -    140

   ó    -    162         ú    -    163         ÿ    -    152
   ò    -    149         ù    -    151         ß    -    158
   Ö    -    148         ü    -    129
   ô    -    147         û    -    150

   ?    -    224         ?    -    240         ½    -    171
   ?    -    225         ±    -    241         ¼    -    172
   ?    -    235         ?    -    242
   µ    -    230         ?    -    243         ²    -    253
   ?    -    227         ÷    -    246
   ?    -    231         ?    -    247         °    -    248

   ¢    -    155         ©    -    189
   £    -    156         §    -    221
   ƒ    -    159

 I hope your printer-driver could digest this table.  If you want
to  use one of these characters after (LINE)  INPUT,  you  should
hold <Alternate> down,  enter the code,  and release <Alternate>.
In a compiled program you have to incorporate '$I+' if you  would
like to be able to use the Alternate-method.

 You can use the following keys on a (LINE) INPUT line:

     <Insert>       - toggle between Overwrite- and Insert-mode

     <Backspace>    - delete character before cursor
     <Delete>       - delete character under cursor
     <Esc>          - erase entire input-line

     <Left Arrow>   - cursor one position to left
     <Right Arrow>  - cursor one position to right
     <Up Arrow>     - cursor to start of input-line
     <Down Arrow>   - cursor to current end of line (after last
                      character)

 The  <Up  Arrow> and <Down Arrow> are sadly missing if  you  use
Find or Replace in the editor.

 Both  INPUT and LINE INPUT use a special cursor,  so it  doesn't
make  much  sense  to  use XBIOS 21  (Curscon)  to  do  something
interesting with the TOS-cursor.

 If you enter something illegal on an INPUT-line (e.g. "A" if you
should  enter a number),  a bell-sound warns you that you made  a
mistake. TOS will now wait for a correct entry, but unfortunately
a linefeed is executed first! Therefore I advise the use of INPUT
with  strings only (or the use of LINE INPUT) so you can  trap  a
user-error yourself.
 As  you know you have to use LINE INPUT instead of INPUT if  the
user is allowed to enter a comma as part of the input-string.

INPUT-bug

 INPUT  and LINE INPUT use the underscore (_) as the cursor in  a
window.   After  you  press  <Return>,   the  underscore  is  not
completely erased:  the rightmost pixel remains visible.  I think
this is a GEM-bug.

INPUT$

 For  the  input of a secret password,  you could  use  something
like:

     PRINT "Type password (5 characters): ";
     code$=INPUT$(5)

 The password does not appear on the screen.

FORM INPUT

 If you use FORM INPUT with a default-string,  the cursor appears
on the first character of the string:

     PRINT "Need some input here: ";
     default$="example"
     FORM INPUT 20 AS default$

 By  pressing  <Down Arrow> you jump to the end of  the  default-
string, but I find it more convenient to let the program do that:

     KEYPRESS &H500000             ! press <Down Arrow>
     FORM INPUT 20 AS default$

KEYTEST

 The  KEYTEST-function does not respond to keys such  as  <Help>,
<Undo>, etc.

KEYGET

 KEYGET waits for a keypress, just like INP(2). But KEYGET is far
more  flexible,  because it returns the ASCII-code and the  scan-
code  of any key and also the state of the special keys  <Shift>,
<Control>,  <Alternate> and <CapsLock>.  Consult your manual  for
tables  of ASCII-codes and scan-codes (in the paragraph  'INKEY$'
you already encountered some important codes on page 8-1).  Study
the  following example to get an impression of the easy  way  you
can examine all keypresses with KEYGET:

     ABSOLUTE ascii|,V:get.code%+3 ! ASCII-code in first byte of
                                                          integer
     ABSOLUTE scan|,V:get.code%+1  ! scan-code in third byte
                                                     (2nd byte=0)
     ABSOLUTE status|,V:get.code%  ! status of special keys in
                                                        last byte
     '
     DO
       KEYGET get.code%            ! wait for keypress
       @keyget                     ! process keypress there
                                                   (not included)
     LOOP

 You  will have to write your own Keyget-Procedure  though.  It's
usually  a good idea to clear the keyboard-buffer (again)  before
leaving  your  Keyget-Procedure.  You  can check if  any  of  the
special keys has been pressed with BTST(status|,bit):

     bit 0 = Right <Shift>
     bit 1 = Left <Shift>
     bit 2 = <Control>
     bit 3 = <Alternate>
     bit 4 = <CapsLock>

 You  could  discover  if the user had  pressed  <Control>  <Down
Arrow> with:

     IF scan|=&H50 AND BTST(status|,2)
       (...)
     ENDIF

 If you are only interested in monitoring the five special  keys,
you  could  use BIOS 11 (Kbshift) and use the same  bit-table  to
test if bit 0-4 is set:

     status|=BIOS(11,-1)

 In  most cases the scan-code of a key is the same,  whether  you
pressed  a special key (except <Control>) simultaneously or  not.
Watch out for the following exceptions:

     <Shift>
     For  <Shift>  <F1> to <Shift> <F10> the scan-codes  &H54  to
     &H5D are returned (not &H3B to &H44).  On an MS-DOS computer
     these codes are used for the keys <F11> to <F20>.

     <Control>
     <Control>  can  be  used to simulate  other  keys  with  the
     'regular' keys, e.g. <Control> <i> = <Tab> and <Control> <h>
     =  <Backspace>.  That's  a  relic  from  a  long  time  ago.
     <Control>   <ClrHome>  has  code  &H77   (not   &H47).   The
     combinations  <Control>  <Left Arrow> (&H73)  and  <Control>
     <Right Arrow> (&H74) also have special codes. Blame MS-DOS.

     <Alternate>
     The combinations <Alternate> <1> to <Alternate> <=> have the
     special codes &H78 to &H83.  That's 'ALT1' to 'ALT=' for MS-
     DOS.  <Alternate> <ClrHome> is intercepted by TOS and  leads
     to a screendump.  <Alternate> in combination with  <Insert>,
     <ClrHome>  or  one  of the arrows is  also  intercepted  and
     results in movement of the mouse-pointer on the screen  (see
     paragraph 'MOUSE').

 A  disadvantage  if the described KEYGET-method is  that  you'll
have to ignore the mouse completely.  If you want to monitor both
the keyboard and the mouse you'll have to use INKEY$ (and  MOUSE)
instead  of KEYGET.  An alternative approach is described in  the
paragraph 'ON MENU KEY' in chapter 21.

KEYLOOK-bug

 KEYLOOK  does not function properly with TOS 1.0,  but seems  to
work with later TOS-versions.

KEYPRESS

 KEYPRESS uses the same 4-byte format as KEYGET:  &Hccss00aa.  In
it you will recognize the ASCII-code (&Haa), the scan-code (&Hss)
and the code for the special keys (&Hcc). If you want to simulate
the pressing of a key in an Alert box, you will have to send both
the  ASCII-code and the scan-code.  Use &H1C000D to simulate  the
pressing  of  <Return>.   Or  &H04620062  for  <Control>  <Help>,
although that certainly won't help in an Alert box.  If you don't
need the scan-code (e.g. with INPUT), use KEYPRESS &Haa.

KEYDEF

 
The editor always uses KEYPAD &X101110,  so you will have to set
bit 4 yourself (e.g. KEYPAD &X10000) before you can use KEYDEF in
your program. Switch KEYDEF off with KEYPAD 0.

Keyboard

 As far as I know,  there are four different keyboards available:
USA  (QWERTY),  English  (QWERTY),  German  (QWERTZ)  and  French
(AZERTY).  Perhaps there is a Spanish keyboard, but I don't think
there exists one in the Atari-world.  The key with scan-code &H2B
(to  the  right of <Return>) has a different ASCII-code  in  each
version:

     version   ASCII-code     character
     USA        &H5C (92)         \
     English    &H23 (35)         #
     German     &H7E (126)        ~
     French     &H40 (64)         @

 You  could  use  XBIOS 16 (Keytbl) to  determine  the  keyboard-
version:

     SELECT PEEK(LPEEK(XBIOS(16,L:-1,L:-1,L:-1))+&H2B)
     CASE &H5C
       usa.keybrd!=TRUE
     CASE &H23
       english.keybrd!=TRUE
     CASE &H7E
       german.keybrd!=TRUE
     CASE &H40
       french.keybrd!=TRUE
     ENDSELECT

 You  should  take  into  account  the  differences  between  the
keyboard-versions  if you are writing a program that  should  run
smoothly  in any country.  With certain scan-codes you should  be
very  careful (see table on next page).  It's not nice to  ask  a
German  user to press <Y>,  but test for scan-code &H15  in  your
program...

 In  the following table I have gathered all keys that  have  not
the same meaning on the four keyboard-versions:

     scancode      USA     English    German    French
       &H0C         -         -         ß         )
       &H0D         =         =         -         '
       &H10         Q         Q         Q         A
       &H11         W         W         W         Z
       &H15         Y         Y         Z         Y
       &H1A         [         [         Ü         [
       &H1B         ]         ]         +         ]
       &H1E         A         A         A         Q
       &H27         ;         ;         ö         M
       &H28         '         '         Ä         \
       &H29         `         `         #         `
       &H2B         \         #         ~         @
       &H2C         Z         Z         Y         W
       &H32         M         M         M         ,
       &H33         ,         ,         ,         ;
       &H34         .         .         .         :
       &H35         /         /         -         =
       &H60        none       \         <         <

 If  you insist on doing things the hard way,  you can  find  the
ASCII-value  that is assigned to a key with  XBIOS  16.  Actually
there  are three tables:  one for a normal keypress,  one  for  a
shifted key and one for a keypress with CapsLock on:

     keytbl%=LPEEK(XBIOS(16,L:-1,L:-1,L:-1))
     shift%=keytbl%+&H80
     capslock%=shift%+&H80

 Now you can find the ASCII-code for any scan-code (< &H80):

     ascii=PEEK(keytbl%+scancode)       ! normal key
     ascii=PEEK(shift%+scancode)        ! shifted key
     ascii=PEEK(capslock%+scancode)     ! CapsLock on

 You  can use XBIOS 16 also to install your  own  keyboard-table.
Fill  three  128-byte strings with the  proper  ASCII-values  and
activate with:

     ~XBIOS(16,L:V:keytbl$,L:V:shift$,L:V:capslock$)

 The standard keyboard-table can be activated again with XBIOS 24
(Bioskeys):

     ~XBIOS(24)

 Please  reactivate the standard keyboard-table before  the  user
exits your program!

Key-click, Key-repeat and CapsLock

 Normally,  you  need  the  key-click  as  an  audible  feedback.
Sometimes  you have to switch the key-click off,  e.g.  while  an
XBIOS 32 song is playing.  That's possible if you clear bit 0  of
the system-variable conterm (at address &H484):

     SPOKE &H484,BSET(PEEK(&H484),0)     ! keyclick on
     SPOKE &H484,BCLR(PEEK(&H484),0)     ! keyclick off

 If your program reacts a bit slow after a keypress, you probably
have to switch the key-repeat temporarily off.  That can be  done
by clearing bit 1 of the same system-variable:

     SPOKE &H484,BSET(PEEK(&H484),1)     ! key-repeat on
     SPOKE &H484,BCLR(PEEK(&H484),1)     ! key-repeat off

 If  you  don't switch key-repeat off,  it  could  become  active
before the user has released a key.  Of course you should  always
restore both key-click and key-repeat to their original  settings
before exiting your program.

 It's  possible  to change the key-wait time and  the  key-repeat
time with XBIOS 35 (Kbrate):

     ~XBIOS(35,wait|,repeat|)

 Both  wait-  and  repeat-time  can  have  values  0-255   (byte-
variables).  Divide  the value by 50 to find the actual  time  in
seconds.  E.g.  wait|=50 means the keyboard will wait one  second
after you pressed a key before the key-repeat is  activated.  And
repeat|=50  means that a keypress is registered every  second  if
you  hold  a  key down.  The default values on  my  computer  are
wait|=15 (15/50 s) and repeat|=2 (2/50 s).

 You can switch CapsLock on or off in your program by using  BIOS
11 (Kbshift) to set/clear bit 4 of the keyboard-mode:

     ~BIOS(11,BSET(BIOS(11,-1),4))       ! CapsLock on
     ~BIOS(11,BCLR(BIOS(11,-1),4))       ! CapsLock off

 You can also press the CapsLock-key,  but it's a shame that  you
can't  tell  if it's on or off (a small status-light  would  have
been nice).

                     Procedures (CHAPTER.08)

Choice_2                                                 CHOICE_2
 Use a mouse-click to pick one of two choices:
     @choice_2(10,"CapsLock","On","Off",choice)   ! on line 10
 Either  1  (first  choice:  On) or 2  (second  choice:  Off)  is
returned in choice&.  If you clicked the right mouse-button, 0 is
returned.

Choice_3                                                 CHOICE_3
 
Use a mouse-click to pick one of three choices:
     @choice_3(10,"Choose number","one","two","three",choice)
 Either 1, 2 or 3 is returned in choice&, unless the user pressed
the right button (0).

Choice_table & Choice_table_init                         CHOICTBL
 Combination of Choice_2 and Choice_3 for a number of items.  The
text for each item and the button-text for each choice must first
be loaded in the Procedure Choice_table_init. Of course you could
create more than one table.
     @choice_table_init(table.1$(),choices.1())
     @choice_table(5,table.1$(),choices.1())      ! start on line
                                                                5

Cursor                                                     CURSOR
 The  TOS-cursor can be switched on and off and it can be  steady
or blinking:
     @cursor(TRUE,TRUE,-1)  ! switch TOS-cursor on, blinking on
 Can't be used with (LINE) INPUT as GFA uses another cursor.

Dial_number Dial_number_help                           DIAL_NUM
 Dial a number with the mouse:
     @dial_number(10,"How much:",5,5,100,1,10,FALSE,money)
 On line 10 you'll see the default-number (5).  You can vary this
number from 5 to 100.  You can increase or decrease the number in
steps  of  1 (left mouse-click) or 10  (right  mouse-click).  The
numbers are not cyclic (flag is FALSE).  The number you picked is
returned in the variable money&. If you press <Help> you'll get a
small manual. If I'm baffled by a program I usually press <Help>.
Of  course in most programs absolutely nothing will  happen,  but
that  doesn't stop us from adopting the good habit of  using  the
<Help>-key.

Input_text                                               INP_TEXT
 A nice way to input text:
     @input_text(TRUE,FALSE,"",20,text$)
 20  dots  (first flag TRUE) mark the input-line (a box  is  also
possible: second flag). The input is returned in text$. <Help> is
available.  The arrows have no function in this Procedure  (yet).
In  this  case the default-string was  the  null-string.  Examine
Procedure Line_input if you need more bells and whistles.

Key_caps                                                 KEY_CAPS
 Switch CapsLock on or off:
     @key_caps(TRUE)     ! CapsLock on

Key_click                                                KEY_CLIK
 Switch key-click on or off:
     @key_click(FALSE)   ! key-click off

Key_repeat                                               KEY_REPT
 Switch key-repeat on or off:
     @key_repeat(FALSE)  ! key-repeat off

Key_wait_repeat                                          KEY_WAIT
 Change key-wait and/or key-repeat time:
     @key_wait_repeat(50,-1,w&,r&)      ! activate key-repeat
                                                        after 1 s
     INPUT txt$
     @key_wait_repeat(-1,50,d&,d&)      ! repeat pressed key
                                                     every second
     INPUT txt$
     @key_wait_repeat(w&,r&,d&,d&)      ! restore default values

Keyget_init                                                KEYGET
 Prepare  for  a Keyget_processor-Procedure by  declaring  a  few
important global variables:
     @keyget_init        ! asci|, scan|, stat| and keyget.code%
                                                          defined
     DO
       KEYGET keyget.code%
       @keyget_processor ! use above variables there
     LOOP

Keypress                                                 KEYPRESS
 Simulate keyboard-input by user:
     @keypress("this text is used",TRUE)
     INPUT "No chance for you: ",t$
 Because the flag is TRUE, the text is terminated with <Return>.

Line_input                                                 LINPUT
 The ultimate line-input routine:
     @line_input(flag%,10,4,20,1,"_","","","",in$,curs&,ret&)
 In  this  case  the  input-line  starts  at  (10,4)  and  is  20
characters long.  The cursor starts at (relative) position 1. The
underscore is used for the input-field (other obvious  candidates
are  "  " and ".").  The cursor-sprite is  not  defined,  so  the
Procedure uses the default-cursor | (thin vertical  line).  There
is no default-string in this case (the second ""). All characters
are  valid  (the third ""),  but you can supply a list  of  valid
characters (e.g. "yYnN"). The input-string is returned in in$ and
the last cursor-column can be found in curs&.  The variable  ret&
contains  flag-bits that tell you how the user exited the  input-
line (e.g.  by pressing <Return>).  The variable flag% makes this
Procedure very flexible,  but also somewhat complicated. Take you
time  to  study  and  use  this  Procedure!  And  make  this  the
penultimate line-input routine by improving the Procedure.

Macro_init                                                  MACRO
 Install macro-strings for the Function-keys:
     @macro_init         ! KEYPAD &X10000 is executed to activate
                                                          macro's
 You'll have to define the strings yourself.

Pop_choice                                               POPCHOIC
 A table of on/off-switches is presented:
     @pop_choice_init(table.1$()    ! create table of choices
     @pop_choice(10,10,table.1$(),choices.1!())
 On-line  <Help> is available.  The choices are returned  in  the
Boolean array choices.1!().

Return_key                                                 RETURN
 Wait until user presses <Return>:
     @return_key(TRUE,FALSE)
 The  word  '<Return>' will blink to catch the eye  of  the  user
(first  flag).  If you would like to catch his ear as  well,  the
second flag should be TRUE.

Special_characters                                       SPEC_CHR
 Show table with all special characters (ASCII-code > 127):
     @special_characters(50,30,code)         ! corner at position
                                                          (50,30)
     IF code>0
       PRINT code
     ENDIF
 A  character can be picked by clicking the mouse or by  entering
the  3-digit ASCII-code.  A click outside the table (or  entering
"0") means the user didn't pick a special character (code&=0).

Special_vowels                                           SPEC_VWL
 Show all special vowels (ASCII-code > 127) on three lines:
     @special_vowels(23)                     ! on line 23-25
     LOCATE 1,10
     LINE INPUT "Enter an exotic name: ";n$
 A special vowel must be entered with the 'Alternate-method'.

                     Functions (CHAPTER.08)

Any_key (page 8-2)                                        ANY_KEY
 Wait until user presses any key or mouse-button:
     PRINT "Press any key or mouse-button..."
     ~@any_key
 The Function returns -1, but you can ignore that.

Ascii_scan
                                               ASC_SCAN
 Return  the ASCII-code that is assigned to a  certain  scan-code
(usually a key on your keyboard):
     PRINT @ascii_scan(&H2B)       ! could be 92, 35, 126 or 64

Ascii_scan_shift          )                              ASC_SHFT
 As Ascii_scan, but with <Shift>-key pressed down:
     PRINT @ascii_scan_shift(&H2B)

Ascii_scan_caps                                          ASC_CAPS
 As Ascii_scan, but with CapsLocks on:
     PRINT @ascii_scan_caps(&H2B)

Input_yes_no                                              INP_YES
 User must choose between yes and no:
     PRINT "Do you want to continue: ";
     IF @input_yes_no         ! TRUE or FALSE
       ' yes
     ELSE
       ' no
     ENDIF
 A blinking "y/n" makes clear what is expected,  but the user may
also press <Return> for yes or click a mouse-button (left is yes,
right is no).  After input either "YES" or "NO" is printed at the
cursor-position and TRUE or FALSE is returned.

Key$                                                          KEY
 Wait for a valid key-press:
     PRINT "Press ""Y"" or ""N"": ";
     char$=@key$(FALSE,"yn")            ! Y,y,N,n accepted
     char$=@key$(TRUE,"YN")             ! only Y,N accepted
 The  flag  determines  if  the  Function  distinguishes  between
lower/upper case.

Keyboard_version$                                        KEYB_VER
 Return keyboard-version:
     PRINT "You have a ";@keyboard_version$;"." 

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.