InSim.txt

From LFS Manual
Revision as of 09:22, 22 June 2009 by xergio (talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to navigationJump to search
#ifndef _ISPACKETS_H_
#define _ISPACKETS_H_
/////////////////////

// InSim for Live for Speed : 0.5Z

// InSim allows communication between up to 8 external programs and LFS.

// TCP or UDP packets can be sent in both directions, LFS reporting various
// things about its state, and the external program requesting info and
// controlling LFS with special packets, text commands or keypresses.

// NOTE : This text file was written with a TAB size equal to 4 spaces.


// INSIM VERSION NUMBER (updated for version 0.5X)
// ====================

const int INSIM_VERSION = 4;


// CHANGES in version 0.5Z (compatible so no change to INSIM_VERSION)
// =======

// NLP / MCI packets are now output at regular intervals
// CCI_LAG bit added to the CompCar structure


// TYPES : (all multi-byte types are PC style - lowest byte first)
// =====

/*
Pack
C is byte
A is CompCar
f is float
i is int
c4 is MSHT
A is NodeLap
A is PosId
s is short
I is unsigned
v is word

Unpack
C is byte
A is CompCar
f is float
i is int
A4 is MSHT
A is NodeLap
A is PosId
s is short
I is unsigned
v is word 
*/

// char            1-byte character
// byte            1-byte unsigned integer
// word            2-byte unsigned integer
// short        2-byte signed integer
// unsigned        4-byte unsigned integer
// int            4-byte signed integerz
// float        4-byte float

// RaceLaps (rl) : (various meanings depending on range)

// 0       : practice
// 1-99    : number of laps...   laps  = rl
// 100-190 : 100 to 1000 laps... laps  = (rl - 100) * 10 + 100
// 191-238 : 1 to 48 hours...    hours = rl - 190


// InSim PACKETS
// =============

// All InSim packets use a four byte header

// Size : total packet size - a multiple of 4
// Type : packet identifier from the ISP_ enum (see below)
// ReqI : non zero if the packet is a packet request or a reply to a request
// Data : the first data byte


// INITIALISING InSim
// ==================

// To initialise the InSim system, type into LFS : /insim xxxxx
// where xxxxx is the TCP and UDP port you want LFS to open.

// OR start LFS with the command line option : LFS /insim=xxxxx
// This will make LFS listen for packets on that TCP and UDP port.


// TO START COMMUNICATION
// ======================

// TCP : Connect to LFS using a TCP connection, then send this packet :
// UDP : No connection required, just send this packet to LFS :

struct IS_ISI // InSim Init - packet to initialise the InSim system
{
    byte    Size;        // 44
    byte    Type;        // ISP_ISI
    byte    ReqI;        // If non-zero LFS will send an IS_VER packet
    byte    Zero;        // 0

    word    UDPPort;    // Port for UDP replies from LFS (0 to 65535)
    word    Flags;        // Bit flags for options (see below)

    byte    Sp0;        // 0
    byte    Prefix;        // Special host message prefix character
    word    Interval;    // Time in ms between NLP or MCI (0 = none)

    char    Admin[16];    // Admin password (if set in LFS)
    char    IName[16];    // A short name for your program
};

// NOTE 1) UDPPort field when you connect using UDP :

// zero     : LFS sends all packets to the port of the incoming packet
// non-zero : LFS sends all packets to the specified UDPPort

// NOTE 2) UDPPort field when you connect using TCP :

// zero     : LFS sends NLP / MCI packets using your TCP connection
// non-zero : LFS sends NLP / MCI packets to the specified UDPPort

// NOTE 3) Flags field (set the relevant bits to turn on the option) :

#define ISF_RES_0        1    // bit 0 : spare
#define ISF_RES_1        2    // bit 1 : spare
#define ISF_LOCAL        4    // bit 2 : guest or single player
#define ISF_MSO_COLS    8    // bit 3 : keep colours in MSO text
#define ISF_NLP            16    // bit 4 : receive NLP packets
#define ISF_MCI            32    // bit 5 : receive MCI packets

// In most cases you should not set both ISF_NLP and ISF_MCI flags
// because all IS_NLP information is included in the IS_MCI packet.

// The ISF_LOCAL flag is important if your program creates buttons.
// It should be set if your program is not a host control system.
// If set, then buttons are created in the local button area, so
// avoiding conflict with the host buttons and allowing the user
// to switch them with SHIFT+B rather than SHIFT+I.

// NOTE 4) Prefix field, if set when initialising InSim on a host :

// Messages typed with this prefix will be sent to your InSim program
// on the host (in IS_MSO) and not displayed on anyone's screen.


// ENUMERATIONS FOR PACKET TYPES
// =============================

enum // the second byte in all packets is one of these
{
    ISP_NONE,        //  0                    : not used
    ISP_ISI,        //  1 - instruction        : insim initialise
    ISP_VER,        //  2 - info            : version info
    ISP_TINY,        //  3 - both ways        : multi purpose
    ISP_SMALL,        //  4 - both ways        : multi purpose
    ISP_STA,        //  5 - info            : state info
    ISP_SCH,        //  6 - instruction        : single character
    ISP_SFP,        //  7 - instruction        : state flags pack
    ISP_SCC,        //  8 - instruction        : set car camera
    ISP_CPP,        //  9 - both ways        : cam pos pack
    ISP_ISM,        // 10 - info            : start multiplayer
    ISP_MSO,        // 11 - info            : message out
    ISP_III,        // 12 - info            : hidden /i message
    ISP_MST,        // 13 - instruction        : type message or /command
    ISP_MTC,        // 14 - instruction        : message to a connection
    ISP_MOD,        // 15 - instruction        : set screen mode
    ISP_VTN,        // 16 - info            : vote notification
    ISP_RST,        // 17 - info            : race start
    ISP_NCN,        // 18 - info            : new connection
    ISP_CNL,        // 19 - info            : connection left
    ISP_CPR,        // 20 - info            : connection renamed
    ISP_NPL,        // 21 - info            : new player (joined race)
    ISP_PLP,        // 22 - info            : player pit (keeps slot in race)
    ISP_PLL,        // 23 - info            : player leave (spectate - loses slot)
    ISP_LAP,        // 24 - info            : lap time
    ISP_SPX,        // 25 - info            : split x time
    ISP_PIT,        // 26 - info            : pit stop start
    ISP_PSF,        // 27 - info            : pit stop finish
    ISP_PLA,        // 28 - info            : pit lane enter / leave
    ISP_CCH,        // 29 - info            : camera changed
    ISP_PEN,        // 30 - info            : penalty given or cleared
    ISP_TOC,        // 31 - info            : take over car
    ISP_FLG,        // 32 - info            : flag (yellow or blue)
    ISP_PFL,        // 33 - info            : player flags (help flags)
    ISP_FIN,        // 34 - info            : finished race
    ISP_RES,        // 35 - info            : result confirmed
    ISP_REO,        // 36 - both ways        : reorder (info or instruction)
    ISP_NLP,        // 37 - info            : node and lap packet
    ISP_MCI,        // 38 - info            : multi car info
    ISP_MSX,        // 39 - instruction        : type message
    ISP_MSL,        // 40 - instruction        : message to local computer
    ISP_CRS,        // 41 - info            : car reset
    ISP_BFN,        // 42 - both ways        : delete buttons / receive button requests
    ISP_AXI,        // 43 - info            : autocross layout information
    ISP_AXO,        // 44 - info            : hit an autocross object
    ISP_BTN,        // 45 - instruction        : show a button on local or remote screen
    ISP_BTC,        // 46 - info            : sent when a user clicks a button
    ISP_BTT,        // 47 - info            : sent after typing into a button
};

enum // the fourth byte of IS_TINY packets is one of these
{
    TINY_NONE,        //  0                    : see "maintaining the connection"
    TINY_VER,        //  1 - info request    : get version
    TINY_CLOSE,        //  2 - instruction        : close insim
    TINY_PING,        //  3 - ping request    : external progam requesting a reply
    TINY_REPLY,        //  4 - ping reply        : reply to a ping request
    TINY_VTC,        //  5 - info            : vote cancelled
    TINY_SCP,        //  6 - info request    : send camera pos
    TINY_SST,        //  7 - info request    : send state info
    TINY_GTH,        //  8 - info request    : get time in hundredths (i.e. SMALL_RTP)
    TINY_MPE,        //  9 - info            : multi player end
    TINY_ISM,        // 10 - info request    : get multiplayer info (i.e. ISP_ISM)
    TINY_REN,        // 11 - info            : race end (return to game setup screen)
    TINY_CLR,        // 12 - info            : all players cleared from race
    TINY_NCN,        // 13 - info            : get all connections
    TINY_NPL,        // 14 - info            : get all players
    TINY_RES,        // 15 - info            : get all results
    TINY_NLP,        // 16 - info request    : send an IS_NLP
    TINY_MCI,        // 17 - info request    : send an IS_MCI
    TINY_REO,        // 18 - info request    : send an IS_REO
    TINY_RST,        // 19 - info request    : send an IS_RST
    TINY_AXI,        // 20 - info request    : send an IS_AXI
    TINY_AXC,        // 21 - info            : autocross cleared
};

enum // the fourth byte of IS_SMALL packets is one of these
{
    SMALL_NONE,        //  0                    : not used
    SMALL_SSP,        //  1 - instruction        : start sending positions
    SMALL_SSG,        //  2 - instruction        : start sending gauges
    SMALL_VTA,        //  3 - report            : vote action
    SMALL_TMS,        //  4 - instruction        : time stop
    SMALL_STP,        //  5 - instruction        : time step
    SMALL_RTP,        //  6 - info            : race time packet (reply to GTH)
    SMALL_NLI,        //  7 - instruction        : set node lap interval
};


// GENERAL PURPOSE PACKETS - IS_TINY (4 bytes) and IS_SMALL (8 bytes)
// =======================

// To avoid defining several packet structures that are exactly the same, and to avoid
// wasting the ISP_ enumeration, IS_TINY is used at various times when no additional data
// other than SubT is required.  IS_SMALL is used when an additional integer is needed.

// IS_TINY - used for various requests, replies and reports

struct IS_TINY // General purpose 4 byte packet
{
    byte Size;        // always 4
    byte Type;        // always ISP_TINY
    byte ReqI;        // 0 unless it is an info request or a reply to an info request
    byte SubT;        // subtype, from TINY_ enumeration (e.g. TINY_RACE_END)
};

// IS_SMALL - used for various requests, replies and reports

struct IS_SMALL // General purpose 8 byte packet
{
    byte Size;        // always 8
    byte Type;        // always ISP_SMALL
    byte ReqI;        // 0 unless it is an info request or a reply to an info request
    byte SubT;        // subtype, from SMALL_ enumeration (e.g. SMALL_SSP)

    unsigned UVal;    // value (e.g. for SMALL_SSP this would be the OutSim packet rate)
};


// VERSION REQUEST
// ===============

// It is advisable to request version information as soon as you have connected, to
// avoid problems when connecting to a host with a later or earlier version.  You will
// be sent a version packet on connection if you set ReqI in the IS_ISI packet.

// This version packet can be sent on request :

struct IS_VER // VERsion
{
    byte    Size;            // 20
    byte    Type;            // ISP_VERSION
    byte    ReqI;            // ReqI as received in the request packet
    byte    Zero;

    char    Version[8];        // LFS version, e.g. 0.3G
    char    Product[6];        // Product : DEMO or S1
    word    InSimVer;        // InSim Version : increased when InSim packets change
};

// To request an InSimVersion packet at any time, send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_VER        (request an IS_VER)


// CLOSING InSim
// =============

// You can send this IS_TINY to close the InSim connection to your program :

// ReqI : 0
// SubT : TINY_CLOSE    (close this connection)

// Another InSimInit packet is then required to start operating again.

// You can shut down InSim completely and stop it listening at all by typing /insim=0
// into LFS (or send a MsgTypePack to do the same thing).


// MAINTAINING THE CONNECTION - IMPORTANT
// ==========================

// If InSim does not receive a packet for 70 seconds, it will close your connection.
// To open it again you would need to send another InSimInit packet.

// LFS will send a blank IS_TINY packet like this every 30 seconds :

// ReqI : 0
// SubT : TINY_NONE        (keep alive packet)

// You should reply with a blank IS_TINY packet :

// ReqI : 0
// SubT : TINY_NONE        (has no effect other than resetting the timeout)

// NOTE : If you want to request a reply from LFS to check the connection
// at any time, you can send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_PING        (request a TINY_REPLY)

// LFS will reply with this IS_TINY :

// ReqI : non-zero        (as received in the request packet)
// SubT : TINY_REPLY    (reply to ping)


// STATE REPORTING AND REQUESTS
// ============================

// LFS will send a StatePack any time the info in the StatePack changes.

struct IS_STA // STAte
{
    byte    Size;            // 28
    byte    Type;            // ISP_STA
    byte    ReqI;            // ReqI if replying to a request packet
    byte    Zero;

    float    ReplaySpeed;    // 4-byte float - 1.0 is normal speed

    word    Flags;            // ISS state flags (see below)
    byte    InGameCam;        // Which type of camera is selected (see below)
    byte    ViewPLID;        // Unique ID of viewed player (0 = none)

    byte    NumP;            // Number of players in race
    byte    NumConns;        // Number of connections including host
    byte    NumFinished;    // Number finished or qualified
    byte    RaceInProg;        // 0 - no race / 1 - race / 2 - qualifying

    byte    QualMins;
    byte    RaceLaps;        // see "RaceLaps" near the top of this document
    byte    Spare2;
    byte    Spare3;

    char    Track[6];        // short name for track e.g. FE2R
    byte    Weather;        // 0,1,2...
    byte    Wind;            // 0=off 1=weak 2=strong
};

// InGameCam is the in game selected camera mode (which is
// still selected even if LFS is actually in SHIFT+U mode).
// For InGameCam's values, see "View identifiers" below.

// ISS state flags

#define ISS_GAME            1        // in game (or MPR)
#define ISS_REPLAY            2        // in SPR
#define ISS_PAUSED            4        // paused
#define ISS_SHIFTU            8        // SHIFT+U mode
#define ISS_SHIFTU_HIGH        16        // HIGH view
#define ISS_SHIFTU_FOLLOW    32        // following car
#define ISS_SHIFTU_NO_OPT    64        // SHIFT+U buttons hidden
#define ISS_SHOW_2D            128        // showing 2d display
#define ISS_FRONT_END        256        // entry screen
#define ISS_MULTI            512        // multiplayer mode
#define ISS_MPSPEEDUP        1024    // multiplayer speedup option
#define ISS_WINDOWED        2048    // LFS is running in a window
#define ISS_SOUND_MUTE        4096    // sound is switched off
#define ISS_VIEW_OVERRIDE    8192    // override user view
#define ISS_VISIBLE            16384    // InSim buttons visible

// To request a StatePack at any time, send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_SST        (Send STate)

// Setting states

// These states can be set by a special packet :

// ISS_SHIFTU_FOLLOW    - following car
// ISS_SHIFTU_NO_OPT    - SHIFT+U buttons hidden
// ISS_SHOW_2D            - showing 2d display
// ISS_MPSPEEDUP        - multiplayer speedup option
// ISS_SOUND_MUTE        - sound is switched off

struct IS_SFP // State Flags Pack
{
    byte    Size;        // 8
    byte    Type;        // ISP_SFP
    byte    ReqI;        // 0
    byte    Zero;

    word    Flag;        // the state to set
    byte    OffOn;        // 0 = off / 1 = on
    byte    Sp3;        // spare
};

// Other states must be set by using keypresses or messages (see below)


// SCREEN MODE
// ===========

// You can send this packet to LFS to set the screen mode :

struct IS_MOD // MODe : send to LFS to change screen mode
{
    byte    Size;        // 20
    byte    Type;        // ISP_MOD
    byte    ReqI;        // 0
    byte    Zero;

    int        Bits16;        // set to choose 16-bit
    int        RR;            // refresh rate - zero for default
    int        Width;        // 0 means go to window
    int        Height;        // 0 means go to window
};

// The refresh rate actually selected by LFS will be the highest available rate
// that is less than or equal to the specified refresh rate.  Refresh rate can
// be specified as zero in which case the default refresh rate will be used.

// If Width and Height are both zero, LFS will switch to windowed mode.


// TEXT MESSAGES AND KEY PRESSES
// ==============================

// You can send 64-byte text messages to LFS as if the user had typed them in.
// Messages that appear on LFS screen (up to 128 bytes) are reported to the
// external program.  You can also send simulated keypresses to LFS.

// MESSAGES OUT (FROM LFS)
// ------------

struct IS_MSO // MSg Out - system messages and user messages
{
    byte    Size;        // 136
    byte    Type;        // ISP_MSO
    byte    ReqI;        // 0
    byte    Zero;

    byte    UCID;        // connection's unique id (0 = host)
    byte    PLID;        // player's unique id (if zero, use UCID)
    byte    UserType;    // set if typed by a user (see User Values below)
    byte    TextStart;    // first character of the actual text (after player name)

    char    Msg[128];
};

// User Values (for UserType byte)

enum
{
    MSO_SYSTEM,            // 0 - system message
    MSO_USER,            // 1 - normal visible user message
    MSO_PREFIX,            // 2 - hidden message starting with special prefix (see ISI)
    MSO_O,                // 3 - hidden message typed on local pc with /o command
    MSO_NUM
};

// NOTE : Typing "/o MESSAGE" into LFS will send an IS_MSO with UserType = MSO_O

struct IS_III // InsIm Info - /i message from user to host's InSim
{
    byte    Size;        // 72
    byte    Type;        // ISP_III
    byte    ReqI;        // 0
    byte    Zero;

    byte    UCID;        // connection's unique id (0 = host)
    byte    PLID;        // player's unique id (if zero, use UCID)
    byte    Sp2;
    byte    Sp3;

    char    Msg[64];
};

// MESSAGES IN (TO LFS)
// -----------

struct IS_MST // MSg Type - send to LFS to type message or command
{
    byte    Size;        // 68
    byte    Type;        // ISP_MST
    byte    ReqI;        // 0
    byte    Zero;

    char    Msg[64];    // last byte must be zero
};

struct IS_MSX // MSg eXtended - like MST but longer (not for commands)
{
    byte    Size;        // 100
    byte    Type;        // ISP_MSX
    byte    ReqI;        // 0
    byte    Zero;

    char    Msg[96];    // last byte must be zero
};

struct IS_MSL // MSg Local - message to appear on local computer only
{
    byte    Size;        // 132
    byte    Type;        // ISP_MSL
    byte    ReqI;        // 0
    byte    Sound;        // sound effect (see Message Sounds below)

    char    Msg[128];    // last byte must be zero
};

struct IS_MTC // Msg To Connection - hosts only - send to a connection or a player
{
    byte    Size;        // 72
    byte    Type;        // ISP_MTC
    byte    ReqI;        // 0
    byte    Zero;

    byte    UCID;        // connection's unique id (0 = host)
    byte    PLID;        // player's unique id (if zero, use UCID)
    byte    Sp2;
    byte    Sp3;

    char    Msg[64];    // last byte must be zero
};

struct IS_SCH // Single CHaracter - send to simulate single character
{
    byte    Size;        // 8
    byte    Type;        // ISP_SCH
    byte    ReqI;        // 0
    byte    Zero;

    byte    CharB;        // key to press
    byte    Flags;        // bit 0 : SHIFT / bit 1 : CTRL
    byte    Spare2;
    byte    Spare3;
};

// Message Sounds (for Sound byte)

enum
{
    SND_SILENT,
    SND_MESSAGE,
    SND_SYSMESSAGE,
    SND_INVALIDKEY,
    SND_ERROR,
    SND_NUM
};


// MULTIPLAYER NOTIFICATION
// ========================

// LFS will send this packet when a host is started or joined :

struct IS_ISM // InSim Multi
{
    byte    Size;        // 40
    byte    Type;        // ISP_ISM
    byte    ReqI;        // usually 0 / or if a reply : ReqI as received in the TINY_ISM
    byte    Zero;

    byte    Host;        // 0 = guest / 1 = host
    byte    Sp1;
    byte    Sp2;
    byte    Sp3;

    char    HName[32];    // the name of the host joined or started
};

// On ending or leaving a host, LFS will send this IS_TINY :

// ReqI : 0
// SubT : TINY_MPE        (MultiPlayerEnd)

// To request an IS_ISM packet at any time, send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_ISM        (request an IS_ISM)

// NOTE : If LFS is not in multiplayer mode, the host name in the ISM will be empty.


// VOTE NOTIFY AND CANCEL
// ======================

// LFS notifies the external program of any votes to restart or qualify

// The Vote Actions are defined as :

enum
{
    VOTE_NONE,            // 0 - no vote
    VOTE_END,            // 1 - end race
    VOTE_RESTART,        // 2 - restart
    VOTE_QUALIFY,        // 3 - qualify
    VOTE_NUM
};

struct IS_VTN // VoTe Notify
{
    byte    Size;        // 8
    byte    Type;        // ISP_VTN
    byte    ReqI;        // 0
    byte    Zero;

    byte    UCID;        // connection's unique id
    byte    Action;        // VOTE_X (Vote Action as defined above)
    byte    Spare2;
    byte    Spare3;
};

// When a vote is cancelled, LFS sends this IS_TINY

// ReqI : 0
// SubT : TINY_VTC        (VoTe Cancelled)

// When a vote is completed, LFS sends this IS_SMALL

// ReqI : 0
// SubT : SMALL_VTA      (VoTe Action)
// UVal : action         (VOTE_X - Vote Action as defined above)

// You can instruct LFS host to cancel a vote using an IS_TINY

// ReqI : 0
// SubT : TINY_VTC        (VoTe Cancel)


// RACE TRACKING
// =============

// In LFS there is a list of connections AND a list of players in the race
// Some packets are related to connections, some players, some both

// If you are making a multiplayer InSim program, you must maintain two lists
// You should use the unique identifier UCID to identify a connection

// Each player has a unique identifier PLID from the moment he joins the race, until he
// leaves.  It's not possible for PLID and UCID to be the same thing, for two reasons :

// 1) there may be more than one player per connection if AI drivers are used
// 2) a player can swap between connections, in the case of a driver swap (IS_TOC)

// When all players are cleared from race (e.g. /clear) LFS sends this IS_TINY

// ReqI : 0
// SubT : TINY_CLR        (CLear Race)

// When a race ends (return to game setup screen) LFS sends this IS_TINY

// ReqI : 0
// SubT : TINY_REN      (Race ENd)

// You can instruct LFS host to cancel a vote using an IS_TINY

// ReqI : 0
// SubT : TINY_VTC        (VoTe Cancel)


struct IS_RST // Race STart
{
    byte    Size;        // 28
    byte    Type;        // ISP_RST
    byte    ReqI;        // 0 unless this is a reply to an TINY_RST request
    byte    Zero;

    byte    RaceLaps;    // 0 if qualifying
    byte    QualMins;    // 0 if race
    byte    NumP;        // number of players in race
    byte    Spare;

    char    Track[6];    // short track name
    byte    Weather;
    byte    Wind;

    word    Flags;        // race flags (must pit, can reset, etc - see below)
    word    NumNodes;    // total number of nodes in the path
    word    Finish;        // node index - finish line
    word    Split1;        // node index - split 1
    word    Split2;        // node index - split 2
    word    Split3;        // node index - split 3
};

// To request an IS_RST packet at any time, send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_RST        (request an IS_RST)

struct IS_NCN // New ConN
{
    byte    Size;        // 56
    byte    Type;        // ISP_NCN
    byte    ReqI;        // 0 unless this is a reply to a TINY_NCN request
    byte    UCID;        // new connection's unique id (0 = host)

    char    UName[24];    // username
    char    PName[24];    // nickname

    byte    Admin;        // 1 if admin
    byte    Total;        // number of connections including host
    byte    Flags;        // bit 2 : remote
    byte    Sp3;
};

struct IS_CNL // ConN Leave
{
    byte    Size;        // 8
    byte    Type;        // ISP_CNL
    byte    ReqI;        // 0
    byte    UCID;        // unique id of the connection which left

    byte    Reason;        // leave reason (see below)
    byte    Total;        // number of connections including host
    byte    Sp2;
    byte    Sp3;
};

struct IS_CPR // Conn Player Rename
{
    byte    Size;        // 36
    byte    Type;        // ISP_CPR
    byte    ReqI;        // 0
    byte    UCID;        // unique id of the connection

    char    PName[24];    // new name
    char    Plate[8];    // number plate - NO ZERO AT END!
};

struct IS_NPL // New PLayer joining race (if PLID already exists, then leaving pits)
{
    byte    Size;        // 76
    byte    Type;        // ISP_NPL
    byte    ReqI;        // 0 unless this is a reply to an TINY_NPL request
    byte    PLID;        // player's newly assigned unique id

    byte    UCID;        // connection's unique id
    byte    PType;        // bit 0 : female / bit 1 : AI / bit 2 : remote
    word    Flags;        // player flags

    char    PName[24];    // nickname
    char    Plate[8];    // number plate - NO ZERO AT END!

    char    CName[4];    // car name
    char    SName[16];    // skin name - MAX_CAR_TEX_NAME
    byte    Tyres[4];    // compounds

    byte    H_Mass;        // added mass (kg)
    byte    H_TRes;        // intake restriction
    byte    Model;        // driver model
    byte    Pass;        // passengers byte

    int        Spare;

    byte    Sp0;
    byte    NumP;        // number in race (same when leaving pits, 1 more if new)
    byte    Sp2;
    byte    Sp3;
};

// NOTE : PType bit 0 (female) is not reported on dedicated host as humans are not loaded
// You can use the driver model byte instead if required (and to force the use of helmets)

struct IS_PLP // PLayer Pits (go to settings - stays in player list)
{
    byte    Size;        // 4
    byte    Type;        // ISP_PLP
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id
};

struct IS_PLL // PLayer Leave race (spectate - removed from player list)
{
    byte    Size;        // 4
    byte    Type;        // ISP_PLL
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id
};

struct IS_CRS // Car ReSet
{
    byte    Size;        // 4
    byte    Type;        // ISP_CRS
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id
};

struct IS_LAP // LAP time
{
    byte    Size;        // 20
    byte    Type;        // ISP_LAP
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    unsigned    LTime;    // lap time (ms)
    unsigned    ETime;    // total time (ms)

    word    LapsDone;    // laps completed
    word    Flags;        // player flags

    byte    Sp0;
    byte    Penalty;    // current penalty value (see below)
    byte    NumStops;    // number of pit stops
    byte    Sp3;
};

struct IS_SPX // SPlit X time
{
    byte    Size;        // 16
    byte    Type;        // ISP_SPX
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    unsigned    STime;    // split time (ms)
    unsigned    ETime;    // total time (ms)

    byte    Split;        // split number 1, 2, 3
    byte    Penalty;    // current penalty value (see below)
    byte    NumStops;    // number of pit stops
    byte    Sp3;
};

struct IS_PIT // PIT stop (stop at pit garage)
{
    byte    Size;        // 24
    byte    Type;        // ISP_PIT
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    word    LapsDone;    // laps completed
    word    Flags;        // player flags

    byte    Sp0;
    byte    Penalty;    // current penalty value (see below)
    byte    NumStops;    // number of pit stops
    byte    Sp3;

    byte    Tyres[4];    // tyres changed

    unsigned    Work;    // pit work
    unsigned    Spare;
};

struct IS_PSF // Pit Stop Finished
{
    byte    Size;        // 12
    byte    Type;        // ISP_PSF
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    unsigned    STime;    // stop time (ms)
    unsigned    Spare;
};

struct IS_PLA // Pit LAne
{
    byte    Size;        // 8
    byte    Type;        // ISP_PLA
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    byte    Fact;        // pit lane fact (see below)
    byte    Sp1;
    byte    Sp2;
    byte    Sp3;
};

// IS_CCH : Camera CHange

// To track cameras you need to consider 3 points

// 1) The default camera : VIEW_DRIVER
// 2) Player flags : CUSTOM_VIEW means VIEW_CUSTOM at start or pit exit
// 3) IS_CCH : sent when an existing driver changes camera

struct IS_CCH // Camera CHange
{
    byte    Size;        // 8
    byte    Type;        // ISP_CCH
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    byte    Camera;        // view identifier (see below)
    byte    Sp1;
    byte    Sp2;
    byte    Sp3;
};

struct IS_PEN // PENalty (given or cleared)
{
    byte    Size;        // 8
    byte    Type;        // ISP_PEN
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    byte    OldPen;        // old penalty value (see below)
    byte    NewPen;        // new penalty value (see below)
    byte    Reason;        // penalty reason (see below)
    byte    Sp3;
};

struct IS_TOC // Take Over Car
{
    byte    Size;        // 8
    byte    Type;        // ISP_TOC
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    byte    OldUCID;    // old connection's unique id
    byte    NewUCID;    // new connection's unique id
    byte    Sp2;
    byte    Sp3;
};

struct IS_FLG // FLaG (yellow or blue flag changed)
{
    byte    Size;        // 8
    byte    Type;        // ISP_FLG
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    byte    OffOn;        // 0 = off / 1 = on
    byte    Flag;        // 1 = given blue / 2 = causing yellow
    byte    CarBehind;    // unique id of obstructed player
    byte    Sp3;
};

struct IS_PFL // Player FLags (help flags changed)
{
    byte    Size;        // 8
    byte    Type;        // ISP_PFL
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id

    word    Flags;        // player flags (see below)
    word    Spare;
};

struct IS_FIN // FINished race notification (not a final result - use IS_RES)
{
    byte    Size;        // 20
    byte    Type;        // ISP_FIN
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id (0 = player left before result was sent)

    unsigned    TTime;    // race time (ms)
    unsigned    BTime;    // best lap (ms)

    byte    SpA;
    byte    NumStops;    // number of pit stops
    byte    Confirm;    // confirmation flags : disqualified etc - see below
    byte    SpB;

    word    LapsDone;    // laps completed
    word    Flags;        // player flags : help settings etc - see below
};

struct IS_RES // RESult (qualify or confirmed finish)
{
    byte    Size;        // 84
    byte    Type;        // ISP_RES
    byte    ReqI;        // 0 unless this is a reply to a TINY_RES request
    byte    PLID;        // player's unique id (0 = player left before result was sent)

    char    UName[24];    // username
    char    PName[24];    // nickname
    char    Plate[8];    // number plate - NO ZERO AT END!
    char    CName[4];    // skin prefix

    unsigned    TTime;    // race time (ms)
    unsigned    BTime;    // best lap (ms)

    byte    SpA;
    byte    NumStops;    // number of pit stops
    byte    Confirm;    // confirmation flags : disqualified etc - see below
    byte    SpB;

    word    LapsDone;    // laps completed
    word    Flags;        // player flags : help settings etc - see below

    byte    ResultNum;    // finish or qualify pos (0 = win / 255 = not added to table)
    byte    NumRes;        // total number of results (qualify doesn't always add a new one)
    word    PSeconds;    // penalty time in seconds (already included in race time)
};

// IS_REO : REOrder - this packet can be sent in either direction

// LFS sends one at the start of every race or qualifying session, listing the start order

// You can send one to LFS before a race start, to specify the starting order.
// It may be a good idea to avoid conflict by using /start=fixed (LFS setting).
// Alternatively, you can leave the LFS setting, but make sure you send your IS_REO
// AFTER you receive the IS_VTA.  LFS does its default grid reordering at the same time
// as it sends the IS_VTA (VoTe Action) and you can override this by sending an IS_REO.

struct IS_REO // REOrder (when race restarts after qualifying)
{
    byte    Size;        // 36
    byte    Type;        // ISP_REO
    byte    ReqI;        // 0 unless this is a reply to an TINY_REO request
    byte    NumP;        // number of players in race

    byte    PLID[32];    // all PLIDs in new order
};

// To request an IS_REO packet at any time, send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_REO        (request an IS_REO)

// Pit Lane Facts

enum
{
    PITLANE_EXIT,        // 0 - left pit lane
    PITLANE_ENTER,        // 1 - entered pit lane
    PITLANE_NO_PURPOSE,    // 2 - entered for no purpose
    PITLANE_DT,            // 3 - entered for drive-through
    PITLANE_SG,            // 4 - entered for stop-go
    PITLANE_NUM
};

// Pit Work Flags

enum
{
    PSE_NOTHING,        // bit 0 (1)
    PSE_STOP,            // bit 1 (2)
    PSE_FR_DAM,            // bit 2 (4)
    PSE_FR_WHL,            // etc...
    PSE_LE_FR_DAM,
    PSE_LE_FR_WHL,
    PSE_RI_FR_DAM,
    PSE_RI_FR_WHL,
    PSE_RE_DAM,
    PSE_RE_WHL,
    PSE_LE_RE_DAM,
    PSE_LE_RE_WHL,
    PSE_RI_RE_DAM,
    PSE_RI_RE_WHL,
    PSE_BODY_MINOR,
    PSE_BODY_MAJOR,
    PSE_SETUP,
    PSE_REFUEL,
    PSE_NUM
};

// View identifiers

enum
{
    VIEW_FOLLOW,    // 0 - arcade
    VIEW_HELI,        // 1 - helicopter
    VIEW_CAM,        // 2 - tv camera
    VIEW_DRIVER,    // 3 - cockpit
    VIEW_CUSTOM,    // 4 - custom
    VIEW_MAX
};

const int VIEW_ANOTHER = 255; // viewing another car

// Leave reasons

enum
{
    LEAVR_DISCO,        // 0 - disconnect
    LEAVR_TIMEOUT,        // 1 - timed out
    LEAVR_LOSTCONN,        // 2 - lost connection
    LEAVR_KICKED,        // 3 - kicked
    LEAVR_BANNED,        // 4 - banned
    LEAVR_SECURITY,        // 5 - OOS or cheat protection
    LEAVR_NUM
};

// Penalty values (VALID means the penalty can now be cleared)

enum
{
    PENALTY_NONE,        // 0       
    PENALTY_DT,            // 1
    PENALTY_DT_VALID,    // 2
    PENALTY_SG,            // 3
    PENALTY_SG_VALID,    // 4
    PENALTY_30,            // 5
    PENALTY_45,            // 6
    PENALTY_NUM
};

// Penalty reasons

enum
{
    PENR_UNKNOWN,        // 0 - unknown or cleared penalty
    PENR_ADMIN,            // 1 - penalty given by admin
    PENR_WRONG_WAY,        // 2 - wrong way driving
    PENR_FALSE_START,    // 3 - starting before green light
    PENR_SPEEDING,        // 4 - speeding in pit lane
    PENR_STOP_SHORT,    // 5 - stop-go pit stop too short
    PENR_STOP_LATE,        // 6 - compulsory stop is too late
    PENR_NUM
};

// Player flags

#define PIF_SWAPSIDE        1
#define PIF_RESERVED_2        2
#define PIF_RESERVED_4        4
#define PIF_AUTOGEARS        8
#define PIF_SHIFTER            16
#define PIF_RESERVED_32        32
#define PIF_HELP_B            64
#define PIF_AXIS_CLUTCH        128
#define PIF_INPITS            256
#define PIF_AUTOCLUTCH        512
#define PIF_MOUSE            1024
#define PIF_KB_NO_HELP        2048
#define PIF_KB_STABILISED    4096
#define PIF_CUSTOM_VIEW        8192

// Tyre compounds (4 byte order : rear L, rear R, front L, front R)

enum
{
    TYRE_R1,            // 0
    TYRE_R2,            // 1
    TYRE_R3,            // 2
    TYRE_R4,            // 3
    TYRE_ROAD_SUPER,    // 4
    TYRE_ROAD_NORMAL,    // 5
    TYRE_HYBRID,        // 6
    TYRE_KNOBBLY,        // 7
    TYRE_NUM
};

const int NOT_CHANGED = 255;

// Confirmation flags

#define CONF_MENTIONED        1
#define CONF_CONFIRMED        2
#define CONF_PENALTY_DT        4
#define CONF_PENALTY_SG        8
#define CONF_PENALTY_30        16
#define CONF_PENALTY_45        32
#define CONF_DID_NOT_PIT    64

#define CONF_DISQ    (CONF_PENALTY_DT | CONF_PENALTY_SG | CONF_DID_NOT_PIT)
#define CONF_TIME    (CONF_PENALTY_30 | CONF_PENALTY_45)

// Race flags

// HOSTF_CAN_VOTE        1
// HOSTF_CAN_SELECT        2
// HOSTF_MID_RACE        32
// HOSTF_MUST_PIT        64
// HOSTF_CAN_RESET        128
// HOSTF_FCV            256
// HOSTF_CRUISE            512

// Passengers byte

// bit 0 female
// bit 1 front
// bit 2 female
// bit 3 rear left
// bit 4 female
// bit 5 rear middle
// bit 6 female
// bit 7 rear right


// TRACKING PACKET REQUESTS
// ========================

// To request players, connections, results or a single NLP or MCI, send an IS_TINY

// In each case, ReqI must be non-zero, and will be returned in the reply packet

// SubT : TINT_NCN - request all connections
// SubT : TINY_NPL - request all players
// SubT : TINY_RES - request all results
// SubT : TINY_NLP - request a single IS_NLP
// SubT : TINY_MCI - request a set of IS_MCI


// AUTOCROSS
// =========

// When all objects are cleared from a layout, LFS sends this IS_TINY :

// ReqI : 0
// SubT : TINY_AXC        (AutoX Cleared)

// You can request information about the current layout with this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_AXI        (AutoX Info)

// The information will be sent back in this packet (also sent when a layout is loaded) :

struct IS_AXI // AutoX Info
{
    byte    Size;        // 40
    byte    Type;        // ISP_AXI
    byte    ReqI;        // 0 unless this is a reply to an TINY_AXI request
    byte    Zero;

    byte    AXStart;    // autocross start position
    byte    NumCP;        // number of checkpoints
    word    NumO;        // number of objects

    char    LName[32];    // the name of the layout last loaded (if loaded locally)
};

// On false start or wrong route / restricted area, an IS_PEN packet is sent :

// False start : OldPen = 0 / NewPen = PENALTY_30 / Reason = PENR_FALSE_START
// Wrong route : OldPen = 0 / NewPen = PENALTY_45 / Reason = PENR_WRONG_WAY

// If an autocross object is hit (2 second time penalty) this packet is sent :

struct IS_AXO // AutoX Object
{
    byte    Size;        // 4
    byte    Type;        // ISP_AXO
    byte    ReqI;        // 0
    byte    PLID;        // player's unique id
};


// CAR TRACKING - car position info sent at constant intervals
// ============

// IS_NLP - compact, all cars in 1 variable sized packet
// IS_MCI - detailed, max 8 cars per variable sized packet

// To receive IS_NLP or IS_MCI packets at a specified interval :

// 1) Set the Interval field in the IS_ISI (InSimInit) packet (50, 60, 70... 8000 ms)
// 2) Set one of the flags ISF_NLP or ISF_MCI in the IS_ISI packet

// If ISF_NLP flag is set, one IS_NLP packet is sent...

struct NodeLap // Car info in 6 bytes - there is an array of these in the NLP (below)
{
    word    Node;        // current path node
    word    Lap;        // current lap
    byte    PLID;        // player's unique id
    byte    Position;    // current race position : 0 = unknown, 1 = leader, etc...
};

struct IS_NLP // Node and Lap Packet - variable size
{
    byte    Size;        // 4 + NumP * 6 (PLUS 2 if needed to make it a multiple of 4)
    byte    Type;        // ISP_NLP
    byte    ReqI;        // 0 unless this is a reply to an TINY_NLP request
    byte    NumP;        // number of players in race

    NodeLap    Info[32];    // node and lap of each player, 1 to 32 of these (NumP)
};

// If ISF_MCI flag is set, a set of IS_MCI packets is sent...

struct CompCar // Car info in 28 bytes - there is an array of these in the MCI (below)
{
    word    Node;        // current path node
    word    Lap;        // current lap
    byte    PLID;        // player's unique id
    byte    Position;    // current race position : 0 = unknown, 1 = leader, etc...
    byte    Info;        // flags and other info - see below
    byte    Sp3;
    int        X;            // X map (65536 = 1 metre)
    int        Y;            // Y map (65536 = 1 metre)
    int        Z;            // Z alt (65536 = 1 metre)
    word    Speed;        // speed (32768 = 100 m/s)
    word    Direction;    // direction of car's motion : 0 = world y direction, 32768 = 180 deg
    word    Heading;    // direction of forward axis : 0 = world y direction, 32768 = 180 deg
    short    AngVel;        // signed, rate of change of heading : (16384 = 360 deg/s)
};

// NOTE 1) Info byte - the bits in this byte have the following meanings :

#define CCI_BLUE        1        // this car is in the way of a driver who is a lap ahead
#define CCI_YELLOW        2        // this car is slow or stopped and in a dangerous place

#define CCI_LAG            32        // this car is lagging (missing or delayed position packets)

#define CCI_FIRST        64        // this is the first compcar in this set of MCI packets
#define CCI_LAST        128        // this is the last compcar in this set of MCI packets

// NOTE 2) Heading : 0 = world y axis direction, 32768 = 180 degrees, anticlockwise from above
// NOTE 3) AngVel  : 0 = no change in heading,    8192 = 180 degrees per second anticlockwise

struct IS_MCI // Multi Car Info - if more than 8 in race then more than one of these is sent
{
    byte    Size;        // 4 + NumP * 28
    byte    Type;        // ISP_MCI
    byte    ReqI;        // 0 unless this is a reply to an TINY_MCI request
    byte    NumC;        // number of valid CompCar structs in this packet

    CompCar    Info[8];    // car info for each player, 1 to 8 of these (NumC)
};

// You can change the rate of NLP or MCI after initialisation by sending this IS_SMALL :

// ReqI : 0
// SubT : SMALL_NLI        (Node Lap Interval)
// UVal : interval      (0 means stop, otherwise time interval : 50, 60, 70... 8000 ms)


// CAR POSITION PACKETS (Initialising OutSim from InSim - See "OutSim" below)
// ====================

// To request Car Positions from the currently viewed car, send this IS_SMALL :

// ReqI : 0
// SubT : SMALL_SSP        (Start Sending Positions)
// UVal : interval        (time between updates - zero means stop sending)

// If OutSim has not been setup in cfg.txt, the SSP packet makes LFS send UDP packets
// if in game, using the OutSim system as documented near the end of this text file.

// You do not need to set any OutSim values in LFS cfg.txt - OutSim is fully
// initialised by the SSP packet.

// The OutSim packets will be sent to the UDP port specified in the InSimInit packet.

// NOTE : OutSim packets are not InSim packets and don't have a 4-byte header.


// DASHBOARD PACKETS (Initialising OutGauge from InSim - See "OutGauge" below)
// =================

// To request Dashboard Packets from the currently viewed car, send this IS_SMALL :

// ReqI : 0
// SubT : SMALL_SSG        (Start Sending Gauges)
// UVal : interval        (time between updates - zero means stop sending)

// If OutGauge has not been setup in cfg.txt, the SSG packet makes LFS send UDP packets
// if in game, using the OutGauge system as documented near the end of this text file.

// You do not need to set any OutGauge values in LFS cfg.txt - OutGauge is fully
// initialised by the SSG packet.

// The OutGauge packets will be sent to the UDP port specified in the InSimInit packet.

// NOTE : OutGauge packets are not InSim packets and don't have a 4-byte header.


// CAMERA CONTROL
// ==============

// IN GAME camera control
// ----------------------

// You can set the viewed car and selected camera directly with a special packet
// These are the states normally set in game by using the TAB and V keys

struct IS_SCC // Set Car Camera - Simplified camera packet (not SHIFT+U mode)
{
    byte    Size;        // 8
    byte    Type;        // ISP_SCC
    byte    ReqI;        // 0
    byte    Zero;

    byte    ViewPLID;    // UniqueID of player to view
    byte    InGameCam;    // InGameCam (as reported in StatePack)
    byte    Sp2;
    byte    Sp3;
};

// NOTE : Set InGameCam or ViewPLID to 255 to leave that option unchanged.

// DIRECT camera control
// ---------------------

// A Camera Position Packet can be used for LFS to report a camera position and state.
// An InSim program can also send one to set LFS camera position in game or SHIFT+U mode.

// Type : "Vec" : 3 ints (X, Y, Z) - 65536 means 1 metre

struct IS_CPP // Cam Pos Pack - Full camera packet (in car OR SHIFT+U mode)
{
    byte    Size;        // 32
    byte    Type;        // ISP_CPP
    byte    ReqI;        // instruction : 0 / or reply : ReqI as received in the TINY_SCP
    byte    Zero;

    Vec        Pos;        // Position vector

    word    H;            // heading - 0 points along Y axis
    word    P;            // pitch   - 0 means looking at horizon
    word    R;            // roll    - 0 means no roll

    byte    ViewPLID;    // Unique ID of viewed player (0 = none)
    byte    InGameCam;    // InGameCam (as reported in StatePack)

    float    FOV;        // 4-byte float : FOV in degrees

    word    Time;        // Time to get there (0 means instant + reset)
    word    Flags;        // ISS state flags (see below)
};

// The ISS state flags that can be set are :

// ISS_SHIFTU            - in SHIFT+U mode
// ISS_SHIFTU_HIGH        - HIGH view
// ISS_SHIFTU_FOLLOW    - following car
// ISS_VIEW_OVERRIDE    - override user view

// On receiving this packet, LFS will set up the camera to match the values in the packet,
// including switching into or out of SHIFT+U mode depending on the ISS_SHIFTU flag.

// If ISS_SHIFTU is not set, then ViewPLID and InGameCam will be used.

// If ISS_VIEW_OVERRIDE is set, the in-car view Heading Pitch and Roll will be taken
// from the values in this packet.  Otherwise normal in game control will be used.

// Position vector (Vec Pos) - in SHIFT+U mode, Pos can be either relative or absolute.

// If ISS_SHIFTU_FOLLOW is set, it's a following camera, so the position is relative to
// the selected car.  Otherwise, the position is absolute, as used in normal SHIFT+U mode.

// NOTE : Set InGameCam or ViewPLID to 255 to leave that option unchanged.

// SMOOTH CAMERA POSITIONING
// --------------------------

// The "Time" value in the packet is used for camera smoothing.  A zero Time means instant
// positioning.  Any other value (milliseconds) will cause the camera to move smoothly to
// the requested position in that time.  This is most useful in SHIFT+U camera modes or
// for smooth changes of internal view when using the ISS_VIEW_OVERRIDE flag.

// NOTE : You can use frequently updated camera positions with a longer Time value than
// the update frequency.  For example, sending a camera position every 100 ms, with a
// Time value of 1000 ms.  LFS will make a smooth motion from the rough inputs.

// If the requested camera mode is different from the one LFS is already in, it cannot
// move smoothly to the new position, so in this case the "Time" value is ignored.

// GETTING A CAMERA PACKET
// -----------------------

// To GET a CamPosPack from LFS, send this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_SCP        (Send Cam Pos)

// LFS will reply with a CamPosPack as described above.  You can store this packet
// and later send back exactly the same packet to LFS and it will try to replicate
// that camera position.


// TIME CONTROL
// ============

// You can Stop or Start Time in LFS and while it is stopped you can make LFS move
// in time steps in multiples of 100th of a second.  Warning : unlike pausing, this
// is a "trick" to LFS and the program is unaware of time passing, so you must not
// leave it stopped because LFS is unusable in that state.  You must never use this
// packet in multiplayer mode.

// Request the current time at any point with this IS_TINY :

// ReqI : non-zero        (returned in the reply)
// SubT : TINY_GTH        (Get Time in Hundredths)

// The time will be sent back in this IS_SMALL :

// ReqI : non-zero        (as received in the request packet)
// SubT : SMALL_RTP        (Race Time Packet)
// UVal    : Time            (hundredths of a second since start of race or replay)

// Stop and Start with this IS_SMALL :

// ReqI : 0
// SubT : SMALL_TMS        (TiMe Stop)
// UVal    : stop            (1 - stop / 0 - carry on)

// When STOPPED, make time step updates with this IS_SMALL :

// ReqI : 0
// SubT : SMALL_STP        (STeP)
// UVal : number        (number of hundredths of a second to update)


// BUTTONS
// =======

// You can make up to 240 buttons appear on the host or guests (ID = 0 to 239).
// You should set the ISF_LOCAL flag (in IS_ISI) if your program is not a host control
// system, to make sure your buttons do not conflict with any buttons sent by the host.

// LFS can display normal buttons in these four screens :

// - main entry screen
// - game setup screen
// - in game
// - SHIFT+U mode

// The recommended area for most buttons is defined by :

#define IS_X_MIN 0
#define IS_X_MAX 110

#define IS_Y_MIN 30
#define IS_Y_MAX 170

// If you draw buttons in this area, the area will be kept clear to
// avoid overlapping LFS buttons with your InSim program's buttons.
// Buttons outside that area will not have a space kept clear.
// You can also make buttons visible in all screens - see below.

// To delete one button or clear all buttons, send this packet :

struct IS_BFN // Button FunctioN - delete buttons / receive button requests
{
    byte    Size;        // 8
    byte    Type;        // ISP_BFN
    byte    ReqI;        // 0
    byte    SubT;        // subtype, from BFN_ enumeration (see below)

    byte    UCID;        // connection to send to or from (0 = local / 255 = all)
    byte    ClickID;    // ID of button to delete (if SubT is BFN_DEL_BTN)
    byte    Inst;        // used internally by InSim
    byte    Sp3;
};

enum // the fourth byte of IS_BFN packets is one of these
{
    BFN_DEL_BTN,        //  0 - instruction     : delete one button (must set ClickID)
    BFN_CLEAR,            //  1 - instruction        : clear all buttons made by this insim instance
    BFN_USER_CLEAR,        //  2 - info            : user cleared this insim instance's buttons
    BFN_REQUEST,        //  3 - user request    : SHIFT+B or SHIFT+I - request for buttons
};

// NOTE : BFN_REQUEST allows the user to bring up buttons with SHIFT+B or SHIFT+I

// SHIFT+I clears all host buttons if any - or sends a BFN_REQUEST to host instances
// SHIFT+B is the same but for local buttons and local instances

// To send a button to LFS, send this variable sized packet

struct IS_BTN // BuTtoN - button header - followed by 0 to 240 characters
{
    byte    Size;        // 12 + TEXT_SIZE (a multiple of 4)
    byte    Type;        // ISP_BTN
    byte    ReqI;        // non-zero (returned in IS_BTC and IS_BTT packets)
    byte    UCID;        // connection to display the button (0 = local / 255 = all)

    byte    ClickID;    // button ID (0 to 239)
    byte    Inst;        // some extra flags - see below
    byte    BStyle;        // button style flags - see below
    byte    TypeIn;        // max chars to type in - see below

    byte    L;            // left   : 0 - 200
    byte    T;            // top    : 0 - 200
    byte    W;            // width  : 0 - 200
    byte    H;            // height : 0 - 200

//    char    Text[TEXT_SIZE]; // 0 to 240 characters of text
};

// ClickID byte : this value is returned in IS_BTC and IS_BTT packets.

// Host buttons and local buttons are stored separately, so there is no chance of a conflict between
// a host control system and a local system (although the buttons could overlap on screen).

// Programmers of local InSim programs may wish to consider using a configurable button range and
// possibly screen position, in case their users will use more than one local InSim program at once.

// TypeIn byte : if set, the user can click this button to type in text.

// Lowest 7 bits are the maximum number of characters to type in (0 to 95)
// Highest bit (128) can be set to initialise dialog with the button's text

// On clicking the button, a text entry dialog will be opened, allowing the specified number of
// characters to be typed in.  The caption on the text entry dialog is optionally customisable using
// Text in the IS_BTN packet.  If the first character of IS_BTN's Text field is zero, LFS will read
// the caption up to the second zero.  The visible button text then follows that second zero.

// Text : 0-65-66-0 would display button text "AB" and no caption

// Text : 0-65-66-67-0-68-69-70-71-0-0-0 would display button text "DEFG" and caption "ABC"

// Inst byte : mainly used internally by InSim but also provides some extra user flags

#define INST_ALWAYS_ON    128        // if this bit is set the button is visible in all screens

// NOTE : You should not use INST_ALWAYS_ON for most buttons.  This is a special flag for buttons
// that really must be on in all screens (including the garage and options screens).  You will
// probably need to confine these buttons to the top or bottom edge of the screen, to avoid
// overwriting LFS buttons.  Most buttons should be defined without this flag, and positioned
// in the recommended area so LFS can keep a space clear in the main screens.

// BStyle byte : style flags for the button

#define ISB_C1            1        // you can choose a standard
#define ISB_C2            2        // interface colour using
#define ISB_C4            4        // these 3 lowest bits - see below
#define ISB_CLICK        8        // click this button to send IS_BTC
#define ISB_LIGHT        16        // light button
#define ISB_DARK        32        // dark button
#define ISB_LEFT        64        // align text to left
#define ISB_RIGHT        128        // align text to right

// colour 0 : light grey        (not user editable)
// colour 1 : title colour        (default:yellow)
// colour 2 : unselected text    (default:black)
// colour 3 : selected text        (default:white)
// colour 4 : ok                (default:green)
// colour 5 : cancel            (default:red)
// colour 6 : text string        (default:pale blue)
// colour 7 : unavailable        (default:grey)

// NOTE : If width or height are zero, this would normally be an invalid button.  But in that case if
// there is an existing button with the same ClickID, all the packet contents are ignored except the
// Text field.  This can be useful for updating the text in a button without knowing its position.
// For example, you might reply to an IS_BTT using an IS_BTN with zero W and H to update the text.

// Replies : If the user clicks on a clickable button, this packet will be sent :

struct IS_BTC // BuTton Click - sent back when user clicks a button
{
    byte    Size;        // 8
    byte    Type;        // ISP_BTC
    byte    ReqI;        // ReqI as received in the IS_BTN
    byte    UCID;        // connection that clicked the button (zero if local)

    byte    ClickID;    // button identifier originally sent in IS_BTN
    byte    Inst;        // used internally by InSim
    byte    CFlags;        // button click flags - see below
    byte    Sp3;
};

// CFlags byte : click flags

#define ISB_LMB            1        // left click
#define ISB_RMB            2        // right click
#define ISB_CTRL        4        // ctrl + click
#define ISB_SHIFT        8        // shift + click

// If the TypeIn byte is set in IS_BTN the user can type text into the button
// In that case no IS_BTC is sent - an IS_BTT is sent when the user presses ENTER

struct IS_BTT // BuTton Type - sent back when user types into a text entry button
{
    byte    Size;        // 104
    byte    Type;        // ISP_BTT
    byte    ReqI;        // ReqI as received in the IS_BTN
    byte    UCID;        // connection that typed into the button (zero if local)

    byte    ClickID;    // button identifier originally sent in IS_BTN
    byte    Inst;        // used internally by InSim
    byte    TypeIn;        // from original button specification
    byte    Sp3;

    char    Text[96];    // typed text, zero to TypeIn specified in IS_BTN
};


// OutSim - MOTION SIMULATOR SUPPORT
// ======

// The user's car in multiplayer or the viewed car in single player or
// single player replay can output information to a motion system while
// viewed from an internal view.

// This can be controlled by 5 lines in the cfg.txt file :

// OutSim Mode 0        :0-off 1-driving 2-driving+replay
// OutSim Delay 1       :minimum delay between packets (100ths of a sec)
// OutSim IP 0.0.0.0    :IP address to send the UDP packet
// OutSim Port 0        :IP port
// OutSim ID 0          :if not zero, adds an identifier to the packet

// Each update sends the following UDP packet :

struct OutSimPack
{
    unsigned    Time;    // time in milliseconds (to check order)

    Vector    AngVel;        // 3 floats, angular velocity vector
    float    Heading;    // anticlockwise from above (Z)
    float    Pitch;        // anticlockwise from right (X)
    float    Roll;        // anticlockwise from front (Y)
    Vector    Accel;        // 3 floats X, Y, Z
    Vector    Vel;        // 3 floats X, Y, Z
    Vec        Pos;        // 3 ints   X, Y, Z (1m = 65536)

    int        ID;            // optional - only if OutSim ID is specified
};

// NOTE 1) X and Y axes are on the ground, Z is up.

// NOTE 2) Motion simulators can be dangerous.  The Live for Speed developers do
// not support any motion systems in particular and cannot accept responsibility
// for injuries or deaths connected with the use of such machinery.


// OutGauge - EXTERNAL DASHBOARD SUPPORT
// ========

// The user's car in multiplayer or the viewed car in single player or
// single player replay can output information to a dashboard system
// while viewed from an internal view.

// This can be controlled by 5 lines in the cfg.txt file :

// OutGauge Mode 0        :0-off 1-driving 2-driving+replay
// OutGauge Delay 1       :minimum delay between packets (100ths of a sec)
// OutGauge IP 0.0.0.0    :IP address to send the UDP packet
// OutGauge Port 0        :IP port
// OutGauge ID 0          :if not zero, adds an identifier to the packet

// Each update sends the following UDP packet :

struct OutGaugePack
{
    unsigned    Time;        // time in milliseconds (to check order)

    char    Car[4];            // Car name
    word    Flags;            // OG_FLAGS (see below)
    byte    Gear;            // Reverse:0, Neutral:1, First:2...
    byte    SpareB;
    float    Speed;            // M/S
    float    RPM;            // RPM
    float    Turbo;            // BAR
    float    EngTemp;        // C
    float    Fuel;            // 0 to 1
    float    OilPress;        // BAR
    float    Spare1;
    float    Spare2;
    float    Spare3;
    float    Throttle;        // 0 to 1
    float    Brake;            // 0 to 1
    float    Clutch;            // 0 to 1
    char    Display1[16];    // Usually Fuel
    char    Display2[16];    // Usually Settings

    int        ID;                // optional - only if OutGauge ID is specified
};

#define OG_SHIFTLIGHT    1
#define OG_FULLBEAM        2
#define OG_HANDBRAKE    4
#define OG_PITSPEED        8
#define OG_TC            16
#define OG_HEADLIGHTS    32
#define OG_SIGNAL_L        64
#define OG_SIGNAL_R        128
#define OG_REDLINE        256
#define OG_OILWARN        512
#define OG_1            1024
#define OG_2            2048
#define OG_3            4096
#define OG_4            8192
#define OG_KM            16384
#define OG_BAR            32768

//////
#endif