               Thrustmaster Application Note AN-0001
          Advanced Key Programming Techniques for the FLCS
               Copyright (c) 1995 Thrustmaster, Inc.
                         All Rights Reserved

                     Revision 1.00  July 21, 1995

Introduction
------------

The FLCS provides a comprehensive set of key functions which directly
handle the majority of the keying requirements for most games by simply
listing the keystrokes required. Situations do arise, however, that 
require some non-standard handling. This note describes the built-in
functions in some detail, and also outlines the various techniques
that can be used when the built-in functions are not sufficient to 
handle the requirement at hand.

Keyboard Basics
---------------

Programming the FLCS to perform a particular function is basically a 
matter of getting it to send the right sequence of key codes to the PC. 
While the FLCS takes care of this for most of the standard keys and
functions, advanced techniques require a basic understanding of how 
the keyboard itself interacts with the PC.

The keyboard operates by sending 'Make' and 'Break' codes to the PC. 
These 'codes' are sequences of one or more data bytes. They are not
'ASCII Characters', but just indicate which keys have been moved. 
When you press a key, the 'Make' code is sent. When you release the 
key, the 'Break' code is sent. Each key on the keyboard has a unique 
sequence of codes assigned to it for its 'Make' and 'Break' sequences.

The PC can't actually determine whether a key is pressed or released 
at any particular time. Rather, it simply keeps track of the 'Make' 
and 'Break' codes. When it receives a 'Make' code, it flags the key 
as pressed until it receives the corresponding 'Break' code, at which 
time it flags the key as released. 

Since the sequencing of the 'Make' and 'Break' codes is important to 
the following discussion, it will be convenient to adopt some notation 
for them. In what follows, the '+' character will be used to indicate 
the 'Make' code for a key, and the '-' character will be used to 
indicate the 'Break' code. For instance:
                               +a -a

would indicate the press and subsequent release of the 'a' key.

Combinational Keypresses
------------------------

Generating single keypresses or strings of single keypresses with the 
FLCS is a straightforward process. The desired characters are simply 
listed in the BTN statement. There are several situations, though, that 
require that multiple keys be pressed simultaneously, and these can 
create problems. The correct programming method is often not clear as 
it depends on how the game processes the keystrokes. The remainder of 
this note will attempt to explain the different techniques available 
and when these techniques should be used.

SHF, ALT, and CTL
-----------------

The most common form of simultaneous keypress is when it is necessary 
to generate a modified key like CTRL-C, ALT-J, or even 'A', since the 
upper-cased character implies that the SHF key is held down while the 
key is pressed. It is generally a simple matter to program these 
combinations  with the FLCS, you simply precede the character with the 
appropriate modifier:

                        BTN S1 CTL c

Any time you specify an upper-case character, the FLCS generates the
SHF code for you, so;

                        BTN S1 A

is actually treated as:

                        BTN S1 SHF a

and the key sequence generated is:

                       +SHF +a -SHF -a

It is worth noting that only the SHF, CTL, and ALT keywords are 
treated as modifiers. The variations that specify particular keys, 
such as LALT and RSFT are treated as regular keys. So if you program 
something like:
                        BTN S1 LALT j

the sequence that is generated is:

                     +LALT -LALT +j -j

and an actual ALT-J combination does not occur. Programming it as:

                       BTN S1 ALT j

produces the desired:

                       +ALT +j -ALT -j

Simultaneous Groups
-------------------

As noted in the FLCS manual, if you enclose a set of characters in 
'curly brackets' it causes the ordering of 'Make' and 'Break' codes to 
be modified so that the keys in the group are pressed simultaneously:
                          
                          BTN S1 {a b c}

will send the sequence:
                         +a +b +c -a -b -c


This function is useful when two or more keys need to be pressed at 
the same time, but it does not hold the keys down for any appreciable 
length of time. They are pressed and then immediately released. The 
simultaneous group is also useful where a game requires a particular 
SHF or ALT key to be used. The normal SHF, ALT, and CTL modifiers 
always use the codes for the Left key, i.e. LSFT. If you needed 'Right 
Shift x' you could program it as:

                          BTN S1 {RSFT x}

and force the use of the Right Shift key. The generated sequence would
be:
                         +RSFT +x -RSFT -x


Repeating Keypresses
--------------------

It frequently becomes necessary in FLCS programming to generate keys 
that are 'held down' to achieve some particular function. Normally this 
can be done by just specifying a single character as a repeating key:

                             BTN S1 a

This generates a sequence of multiple 'Make' codes while the button 
is held down, and generates a single 'Break' code when the button is 
released. 

This is essentially what the keyboard does, but there is one fundamental 
difference. When another button is pressed and the FLCS sends another
character, the FLCS will send a 'Break' code for the repeating character,
even if the button (S1 in this example) is still held down. The keyboard
does not send the 'Break' code until the key is released. For example, 
if you programmed:
                             BTN S1 a
                             BTN S2 b

then pressed S1, pressed S2, released S2, and then released S1, the FLCS
would generate something like:

                   +a +a +a +a -a +b +b +b +b -b
                    
whereas if you did the same thing on the keyboard using the actual 'a' 
and 'b' keys, the sequence would look like this:

                    +a +a +a +a +b +b +b +b -b -a

The FLCS was coded this way on purpose. When you're using the keyboard, 
you are generally aware of which keys you've got pressed at any particular 
time, and inappropriate combinations don't occur very often. When you're 
using the FLCS, it's not always apparent what keys you are pressing. For 
example, look at the program segment:

                             BTN S1 A
                             BTN S2 b

If the FLCS actually emulated the keyboard, the generated sequence would
be:
                +SHF +a +a +a +a +b +b +b +b -b -SHF -a

if you pressed them in the order outlined for the first example. If you 
looked at this on the screen, you would see 'AAAABBBB', rather than the
'AAAAbbbb' that you would expect, since the SHF key has not been released.
Forcing the 'Break' when S2 is pressed changes the sequence to:

                +SHF +a +a +a +a -SHF -a +b +b +b +b -b

which is more in keeping with the intent of the program. This is a fairly
simple example, worse problems could occur. If S1 were defined as 'ALT a',
then so long as S1 were held, the PC would see every key coming at it as
having the ALT modifier added, i.e. you'd not only get 'ALT a' like you 
wanted, you'd get 'ALT b', too, since the ALT would still be down from 
the S1 press. Disastrous combinations could occur, consider what might 
happen if a program contained something like:

                          BTN S1 CTL a
                          BTN S2 ALT j
                          BTN S3 DEL

and all three buttons were pushed. The PC would see a simultaneous press 
of CTL-ALT-DEL, and would likely reboot. Probably not exactly what you 
wanted to happen.

Hold Codes
----------

In some circumstances, it is necessary to hold the key down even when 
other buttons are pressed. The most common examples are keys that move 
control surfaces, and situations that require multiple keys to be held 
to achieve a particular view. For instance, suppose you wanted to program 
a hat to control the rudders. You might try (assuming 'l' and 'r' are 
the left and right rudder keys respectively)

                           BTN H1L l
                           BTN H1R r

This would activate the rudders, but because of the way the repeating 
keys operate on the FLCS, as soon as you pushed another button the rudder 
would return to it's neutral position. The use of the /H code would get 
around the problem, since it does not generate a 'Break' until the Hat 
is released. The coding would look like this:

                          BTN H1L /H l
                          BTN H1R /H r

The /H codes are also slightly different in the way they appear on the 
screen. There is only a single 'Make' code generated, so you only see 
one character when you press the button. The PC will see the key as held, 
however, and in situations where the /H is required, the absence of the 
repeated 'Make' codes is of no consequence. The game will be looking 
only at the first 'Make' code in such situations, anyway.

Holding down multiple keys is simply a matter of adding them to the 
list. To hold down KP8 and KP5 for a combinational view, the program 
would look like this:

                      BTN H1U /H KP8 KP5

When the button was pressed, the sequence generated would be:

                           +KP8 +KP5

and when the button was released, the sequence would be:

                           -KP8 -KP5

Any characters generated by other buttons while H1U was held would be 
sent normally,

While /H codes are very useful, they are not without a few problems. 
First, as mentioned earlier in the discussion of repeating keys, it's 
generally not possible to use them for anything other than unmodified 
keys. The use of upper-case, SHF, ALT or CTL modifiers creates problems 
in that the PC will apply those modifiers to all characters transmitted 
while the /H is held down, i.e.

                           BTN S1 /H A

will upper-case all keys transmitted while S1 is pressed. Consequently,
the use of such modifiers must generally be avoided in /H groups.

A second limitation places on /H groups is that they cannot be used 
with the /I and /O, or the /U, /M, and /D modifiers. The reason for 
this is not immediately obvious, but to have allowed them to be used 
there would create a strong likelihood of 'stuck' keys during operation. 
Consider the following example:

                         BTN S1 /O /H a
                                /I /H b

Now suppose that during game play, you were to press S1, then press S3,
then release S1. Since S3 was not pressed initially, the /O side of the
definition would be in control. The initial press of S1 would send the
'Make' code for the 'a' as expected. When S3 was pressed, that would 
put the /I side of the definition in control. Subsequently releasing 
S1 would result in the 'Break' break code for the 'b' being sent. The 
sequence at the PC would be:
                              +a -b

The PC has seen the 'a' pressed, but never sees it released, so it will
consider it to be still pressed. The key is 'stuck', and will remain that 
way until a 'Break' for the 'a' is sent, either by hitting the 'a' on the 
keyboard, or sending a complete 'a' with the FLCS. It may remain stuck 
even if you exit the game.

The limitation on the /I, /O, /U, /M and /D codes can be overcome in a 
couple of ways. One is simply to come up with a scheme that doesn't need
them. The use of the /I and /O codes with held characters most commonly
shows up in view switching situations. One method that works in some
situations is to just use unmodified views on the hat, then add the 
modifier key to button S3. For example, suppose that the four basic
views are KP8, KP6, KP2, and KP4. Also assume that adding KP5 to these 
four will add the UP modifier, and that adding KP0 to them will add the
DOWN modifier, i.e. KP4 is Look Left and KP4 + KP5 is Look Up and Left. 
In that case, a setup like this:

                  BTN H1U /H KP8     rem Look Up
                  BTN H1L /H KP4     rem Look Left
                  BTN H1D /H KP2     rem Look Back
                  BTN H1R /H KP6     rem Look Right

                  BTN S3 /H KP5      rem Add UP Modifier
                  BTN S4 /H KP0      rem Add DOWN Modifier

may prove workable, giving 12 views via combinations of the hat and the
S3 and S4 keys.

If no suitable arrangement can be found using the standard keys, it is
possible to generate held keys within /I-/O and /U-/M-/D groups using
the RAW function.


RAW Data Codes
--------------

RAW data codes allow you complete control over what the FLCS sends to 
the PC. You specify the actual codes sent to the PC by their hex values. 
There are no real limits placed on the use of RAW codes, they can be 
used within the /I-/O and /U-/M-/D groups, and so you can generate any 
key sequence that you want to. A complete listing of the RAW sequences 
for the 'Make' and 'Break' codes on the 101-Key Keyboard is listed at 
the end of this note.

The RAW data function was designed for situations where the normal FLCS 
functions would not handle the task at hand. The most common use of 
them is to generate the so-called 'non-native' keys that the FLCS will 
not normally transmit. If you look over the RAW codes chart, you'll see 
that the majority of keys send a single RAW code for a 'Make', and send 
the value '#F0' followed by that same RAW code for the 'Break'. These 
are the 'native' keys, and they correspond roughly to the keys on the 
older 84-Key AT keyboards. The other 'non-native' keys are primarily 
associated with the 101-Key Keyboard, and usually have an extra '#E0' 
added to the sequence. These keys include the auxiliary 'T-Cursor' pad 
and the other keys in the section of the 101-Key Keyboard between the 
main keys and the numeric pad.

The other primary use of the RAW codes is to generate key combinations
that cannot normally be generated by the FLCS, such as the use of held
characters within /I-/O and /U-/M-/D Groups. The basic method for 
simulating a /H group is to generate a /P-/R set with the 'Make' codes
on the /P side and the 'Break' codes on the /R side. For instance:

                   BTN S1 /P RAW(#1C)
                          /R RAW(#F0 #1C)

produces the same output as:

                       BTN S1 /H a

with the 'Make' code sent when the button is pressed and the 'Break' 
code being sent when it's released.

As mentioned earlier, using RAW codes within the /I-/O and /U-/M-/D 
groups is permitted, but it does not get around the basic problem with 
the 'stuck' keys. You have to set the programming up so that the problem 
does not occur. The usual method is to include the 'Make' codes for a 
single function on the /P side, and to include the 'Break' codes for all 
possible functions on the /R side. This is generally possible since 
multiple 'Make' codes for a key generally do no harm, and 'Break' codes 
for keys that have not been 'Made' are generally ignored. For example. 
the program segment:

  BTN H1U /O /H f g
          /I /H KP5 KP8

would not compile, but the equivalent:

 BTN H1U /O /P RAW(#2B #34)                         rem Make 'f' and 'g'
            /R RAW(#F0 #2B #F0 #34)                 rem Break f, g 
         /I /P RAW(#73 #75)                         rem Make KP5 and KP8
            /R RAW(#F0 #73 #F0 #75)                 rem Break KP5 & KP8 

would compile just fine. This does not avoid the stuck key problem 
though. You need to 'Break' both possibilities on both sides, even 
though you will only 'Make' one of the codes:

 BTN H1U /O /P RAW(#2B #34)                         rem Make 'f' and 'g'
            /R RAW(#F0 #2B #F0 #34 #F0 #73 #F0 #75) rem Break f, g, KP5 & KP8 
         /I /P RAW(#73 #75)                         rem Make KP5 and KP8
            /R RAW(#F0 #2B #F0 #34 #F0 #73 #F0 #75) rem Break f, g, KP5 & KP8 

One thing to watch for here is that all those RAW codes take some time 
to send, about 50% longer than a regular /H group. The best thing to do 
is to set the RATE parameter down to 0, increase it only if you experience 
problems with the game in question. Most of the games will work just fine 
with a RATE of 0, the exceptions are games that only handle 1 key stroke 
per frame.

Keyboard Chart
--------------

The following chart shows the 'Make' and 'Break' for the keys on the 
standard 101-key keyboard. These are the codes necessary to use the RAW 
function in FLCS programming.

The keyboard modifies certain of the 'non-native' key code sequences 
depending on the Shift and NumLock states. These additions can normally be 
ignored when programming the FLCS and the normal non-shifted sequence used.

-----------------------------------------------------------------------------

           *** STANDARD 101-KEY KEYBOARD SCAN CODE SEQUENCES ***
             For Use with the FLCS 'RAW' Programming Function

                          ** Main Keyboard **
----------------------------------------------------------------------------
  Key         Make Code                       Break Code         Notes
----------------------------------------------------------------------------
  `              #0E                           #F0 #0E
  1              #16                           #F0 #16
  2              #1E                           #F0 #1E
  3              #26                           #F0 #26
  4              #25                           #F0 #25
  5              #2E                           #F0 #2E
  6              #36                           #F0 #36
  7              #3D                           #F0 #3D
  8              #3E                           #F0 #3E
  9              #46                           #F0 #46
  0              #45                           #F0 #45
  -              #4E                           #F0 #4E
  =              #55                           #F0 #55
  Backspace      #66                           #F0 #66

  Tab            #0D                           #F0 #0D
  Q              #15                           #F0 #15
  W              #1D                           #F0 #1D
  E              #24                           #F0 #24
  R              #2D                           #F0 #2D
  T              #2C                           #F0 #2C
  Y              #35                           #F0 #35
  U              #3C                           #F0 #3C
  I              #43                           #F0 #43
  O              #44                           #F0 #44
  P              #4D                           #F0 #4D
  [              #54                           #F0 #54
  ]              #5B                           #F0 #5B
  \              #5D                           #F0 #5D

  Caps Lock      #58                           #F0 #58
  A              #1C                           #F0 #1C
  S              #1B                           #F0 #1B
  D              #23                           #F0 #23
  F              #2B                           #F0 #2B
  G              #34                           #F0 #34
  H              #33                           #F0 #33
  J              #3B                           #F0 #3B
  K              #42                           #F0 #42
  L              #4B                           #F0 #4B
  ;              #4C                           #F0 #4C
  '              #52                           #F0 #52
  Enter          #5A                           #F0 #5A

  Left Shift     #12                           #F0 #12
  Z              #1A                           #F0 #1A
  X              #22                           #F0 #22
  C              #21                           #F0 #21
  V              #2A                           #F0 #2A
  B              #32                           #F0 #32
  N              #31                           #F0 #31
  M              #3A                           #F0 #3A
  ,              #41                           #F0 #41
  .              #49                           #F0 #49
  /              #4A                           #F0 #4A
  Right Shift    #59                           #F0 #59

  Left Ctrl      #14                           #F0 #14
  Left Alt       #11                           #F0 #11
  Space          #29                           #F0 #29
  Right Alt      #E0 #11                       #E0 #F0 #11
  Right Ctrl     #E0 #14                       #E0 #F0 #14
  ESC            #76                           #F0 #76
----------------------------------------------------------------------------


                          ** Function Keys **
----------------------------------------------------------------------------
  Key         Make Code                       Break Code        Notes
----------------------------------------------------------------------------
  F1             #05                           #F0 #05
  F2             #06                           #F0 #06
  F3             #04                           #F0 #04
  F4             #0C                           #F0 #0C
  F5             #03                           #F0 #03
  F6             #0B                           #F0 #0B
  F7             #83                           #F0 #83
  F8             #0A                           #F0 #0A
  F9             #01                           #F0 #01
  F10            #09                           #F0 #09
  F11            #78                           #F0 #78
  F12            #07                           #F0 #07
----------------------------------------------------------------------------


                            ** Numeric Pad **
----------------------------------------------------------------------------
  Key         Make Code                       Break Code         Notes
----------------------------------------------------------------------------
  NumLok         #77                           #F0 #77
  KP-            #7B                           #F0 #7B
  KP/            #E0 #4A                       #E0 #F0 #4A     Notes 1, 2
  KP.            #71                           #F0 #71
  KP*            #7C                           #F0 #7C
  KP+            #79                           #F0 #79
  KPEnter        #E0 #5A                       #E0 #F0 #5A

  KP0            #70                           #F0 #70
  KP1            #69                           #F0 #69
  KP2            #72                           #F0 #72
  KP3            #7A                           #F0 #7A
  KP4            #6B                           #F0 #6B
  KP5            #73                           #F0 #73
  KP6            #74                           #F0 #74
  KP7            #6C                           #F0 #6C
  KP8            #75                           #F0 #75
  KP9            #7D                           #F0 #7D
----------------------------------------------------------------------------


                           ** Auxiliary Pads **
----------------------------------------------------------------------------
  Key           Make Code                      Break Code        Notes
----------------------------------------------------------------------------
  Ins            #E0 #70                       #E0 #F0 #70    Notes 1, 2, 3
  Home           #E0 #6C                       #E0 #F0 #6C    Notes 1, 2, 3
  Pg Up          #E0 #7D                       #E0 #F0 #7D    Notes 1, 2, 3
  Del            #E0 #71                       #E0 #F0 #71    Notes 1, 2, 3
  End            #E0 #69                       #E0 #F0 #69    Notes 1, 2, 3
  Pg Dn          #E0 #7A                       #E0 #F0 #7A    Notes 1, 2, 3

  Up Arrow       #E0 #75                       #E0 #F0 #75    Notes 1, 2, 3
  Left Arrow     #E0 #6B                       #E0 #F0 #6B    Notes 1, 2, 3
  Right Arrow    #E0 #74                       #E0 #F0 #74    Notes 1, 2, 3
  Down Arrow     #E0 #72                       #E0 #F0 #72    Notes 1, 2, 3

  PrtSc          #E0 #12 #E0 #7C               #E0 #F0 #7C #E0 #F0 #12
  Ctl-PrtSc      #E0 #7C                       #E0 #F0 #7C
  Alt-PrtSc      #84                           #E0 #84
  ScrLk          #7E                           #F0 #7E
  Pause          #E1 #14 #77 #E1 #F0 #14 #77   None
  Ctrl-Break     #E0 #7E #E0 #F0 #7E           None

----------------------------------------------------------------------------


                                ** Notes **
----------------------------------------------------------------------------

  Note 1

     If Left Shift is Down:

        Make Sequence - #E0 #F0 #12 #** #**
       Break Sequence _ #** #** #** #E0 #12

  Note 2

    If Right Shift is Down:

        Make Sequence - #E0 #F0 #59 #** #**
       Break Sequence - #** #** #** #E0 #59

  Note 3

    If Num Lock is On:

        Make Sequence - #E0 #12 #** #**
       Break Sequence - #** #** #** #E0 #F0 #12

  The '#** #**' entry represents the Make Code and the '#** #** #**' entry
  represents the  Break Code specified for the character in the main chart
  and should be replaced with those sequences in actual use.

-----------------------------------------------------------------------------
                            -- End of Document --
