InSim System for Live for Speed : (Patch G Version : 1)
=================================


InSim allows communication between an external program and LFS.exe.

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


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

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 integer
float		4-byte float
MSHT		4-byte minutes, seconds, hundredths, thousandths


InSim initialisation
====================

To initialise the InSim system, type into LFS :

/insim XXXXX	- XXXXX is the 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 UDP port.

Now you must send a special UDP packet to LFS.

struct InSimInit		// UDP packet to initialise the InSim system
{
	char	Id	[4];	// ISI + zero
	word	Port;		// Port for UDP replies from LFS (0...65535)
	byte	Flags;		// Bit flags for options - see below
	byte	NodeSecs;	// Number of seconds between NLP or MCI packets (0=none)
	char	Admin	[16];	// Admin password (required if set in LFS host options)
};

Now you can send packets to control LFS, and LFS will be sending packets to you.

Flags in InSimInit packet : set the relevant bits to turn on the option :

#define ISF_RACE_TRACKING	1	// bit 0 : turns on race tracking
#define ISF_GUARANTEE		2	// bit 1 : turns on guaranteed delivery
#define ISF_SPLIT_MESSAGE	4	// bit 2 : use MSS, not MSO for user messages
#define ISF_NO_WARNINGS		8	// bit 3 : turns off packet warnings
#define ISF_KEEP_ALIVE		16	// bit 4 : makes lfs send keep alive packets
#define ISF_NLP_MCI		32	// bit 5 : makes lfs send MCI instead of NLP

Note : If Port is zero, LFS will send replies back to the port of the incoming packet


InSimPack
=========

InSimPack is used for various InSim requests (see below)

struct InSimPack		// General purpose 8 byte UDP packet
{
	char	Id	[4];	// 3 character identifier followed by zero character
	int	Value;		// 32 bit value depending on the type of InSimPack
};


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.

This small version packet can be sent on request :

struct InSimVersion
{
	char	Id	[4];	// VER + 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, send an InSimPack like this :

Id	: "VER"  (VERsion)
Value	: 0


Closing Insim
=============

You can send a packet to ask InSim to return to its waiting / initialised / listening
state by sending an InSimPack with Id = "ISC" (InSimClose) and Value = 0.

It will then require another InSimInit packet to start operating again.

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


Maintaining the connection - Important
======================================

If InSim does not receive a packet for 2 minutes, it will close the connection and
return to its original waiting / initialised state.

To open it again you would need to send another InSimInit packet.

To avoid InSim closing in this way, you should send a packet every 20 - 30 seconds.
One example of a "keep alive" packet is an "ACK" InSimPack with value = 0.
This "blank acknowledgment packet" will have no other effect on LFS.

Note 1 : If you set the ISF_KEEP_ALIVE option in the InSimInit packet, then LFS will
send a blank acknowledgement packet whenever it has not sent anything for 20 seconds.
If you don't receive anything for 2 minutes it may be safe to assume that you have
lost the connection for some reason.  This option is also useful if your program
doesn't run at all while it is waiting for a packet to arrive.

Note 2 : If you want to request a small reply from LFS to check the connection at any
time, a good one to send is a "GTH" InSimPack - LFS returns a "RTP" InSimPack.  This
has no functional effect on LFS as it is simply a time reporting packet (see below).


State Reporting and Request
===========================

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

struct StatePack
{
	char	Id	[4];	// STA + zero
	float	ReplaySpeed;	// 4-byte float - 1.0 is normal speed

	word	Flags;		// State Flags (see below)
	byte	InGameCam;	// Which type of camera is selected (see below)
	byte	ViewPlayer;	// Player index of viewed car

	byte	NumPlayers;	// Num in race
	byte	NumConns;	// Num connections including host
	byte	NumFinished;	// Number finished or qualified
	byte	RaceInProgress;	// 0 - no / 1 - race / 2 - qualifying

	byte	QualMins;
	byte	RaceLaps;
	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
};

The bits stored in "State Flags" are :
--------------------------------------
#define ISS_GAME		1	// in game (or MPR)
#define ISS_REPLAY		2	// in SPR
#define ISS_PAUSED		4	// paused
#define ISS_SHIFTU		8	// in SHIFT+U mode
#define ISS_SHIFTU_HIGH		16	// HIGH view
#define ISS_SHIFTU_FOLLOW	32	// following car
#define ISS_SHIFTU_NO_OPT	64	// buttons are hidden
#define ISS_SHOW_2D		128	// showing 2d display
#define ISS_FRONT_END		256	// in front end 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

InGameCam shows the NOT SHIFT+U selected camera mode
----------------------------------------------------
0	Arcade View
1	Helicopter View
2	TV Camera View
3	Driver View
4	Custom View

To request a StatePack from LFS, send an InSimPack like this :
--------------------------------------------------------------
Id	: "SST"  (Send State)
Value	: 0

Setting states
--------------
These states can be controlled by a special packet :

ISS_SHIFTU_FOLLOW	// following car
ISS_SHIFTU_NO_OPT	// buttons are hidden
ISS_SHOW_2D		// showing 2d display
ISS_MPSPEEDUP		// multiplayer speedup option
ISS_SOUND_MUTE		// sound is mute

struct StateFlagsPack
{
	char	Id	[4];	// SFP + zero
	word	Flag;		// the state to set (ISS_xxx)
	byte	OffOn;		// 0 = off / 1 = on
	byte	Sp3;		// spare
};

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


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 screeen (up to 128 bytes) are reported to the
external program.  You can also send simulated keypresses to LFS.

struct MsgTypePack // 64 chars - send to LFS to simulate typing message or command
{
	char	Id	[4];	// MST + zero
	char	Msg	[64];	// text message or /command, must end with zero
};

struct MsgToConn // 64 chars - send to LFS and on to a chosen connection (0 = host)
{
	char	Id	[4];	// MTC + zero
	byte	Conn;		// connection
	byte	UniqueId;	// destination player UniqueId : if set, Conn is ignored
	byte	Sp2;
	byte	Sp3;
	char	Msg	[64];	// text message or /command, must end with zero
};

struct MsgOutPack // 128 chars - LFS reporting displayed messages
{
	char	Id	[4];	// MSO + zero
	char	Msg	[128];	// displayed message, with colours removed
};

struct MsgOutSplit // 64 chars - user messages if ISF_SPLIT_MESSAGE flag is ON
{
	char	Id	[4];	// MSS + zero
	char	UName	[24];	// user name
	char	PName	[24];	// player name
	char	Msg	[64];	// text message from user
};

struct SingleCharPack // send to LFS to simulate single character
{
	char	Id	[4];	// SCH + zero
	char	Char;		// key to press
	byte	Flags;		// bit 0 : SHIFT / bit 1 : CTRL
	byte	Spare2;
	byte	Spare3;
};

Note 1 : you must set the "Flags" bits if you want to simulate a key that
  needs CTRL or SHIFT held down.

Note 2 : a new command has been added to LFS : /mso
  Typing "/mso MESSAGE" into LFS will send a MSO packet to the external program.


Multiplayer Notification
========================

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

struct InSimMulti
{
	char	Id	[4];	// ISM
	byte	Host;		// 0 = guest / 1 = host
	byte	Sp1;
	byte	Sp2;
	byte	Sp3;
	char	Name	[32];	// the name of the host joined or started
};

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

Id	: "MPE"  (MultiPlayerEnd)
Value	: 0

To request a InSimMulti packet at any time, send a InSimPack with Id = "ISM".
- 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 :

VOTE_NONE	0
VOTE_END_RACE	1
VOTE_RESTART	2
VOTE_QUALIFY	3

struct InSimVote
{
	char	Id	[4];	// VTN + zero (VoTe Notify)
	byte	Conn;		// connection (0 is host)
	byte	Type;		// VOTE_X (Vote Action as defined above)
	byte	Spare2;
	byte	Spare3;
};

When a vote is cancelled, LFS sends this InSimPack to the control program

Id	: "VTC"  	(VoTe Cancel)
Value	: 0

When a vote is completed, LFS sends this InSimPack to the control program

Id	: "VTA"  	(VoTe Action)
Value	: action 	(VOTE_X - Vote Action as defined above)

The external program can instruct LFS host to cancel a vote using an InSimPack

Id	: "VTC"  	(VoTe Cancel)
Value	: 0


Setting Screen Mode
===================

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

struct InSimMode
{
	char	Id	[4];	// MOD + zero (MODe)
	int	Bits16;		// set to choose 16-bit mode
	int	RR;		// refresh rate - zero for default
	int	Width;		// 0 - go to window
	int	Height;		// 0 - 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.


Race Tracking
=============

Special Packets are provided for Race Tracking.
These will be sent if InSim was initialised with the ISF_RACE_TRACKING flag set.

Because it's using UDP protocol, it's possible some packets may be lost.  So a
simple "guaranteed delivery" system has been implemented :

You must send an aknowledgment reply to LFS after receiving these packets, or
 LFS will try to send them again.

An acknowledgment packet is an InSimPack like this :

Id	: "ACK"         (ACKnowledge)
Value	: VerifyId      (as given in the received packet)

RACE TRACKING PACKETS - you must send an acknowledgement reply to these packets
---------------------
struct IS_RST // Race STart
{
	char	RST	[4];

	byte	RaceLaps;	// 0 if qualifying
	byte	QualMins;	// 0 if race
	byte	NumInRace;
	byte	Spare;

	char	Track	[6];
	byte	Weather;
	byte	Wind;

	byte	Sp0;
	byte	Sp1;
	word	VerifyId;
};

struct IS_REN // Race ENd (return to entry screen)
{
	char	REN	[4];

	byte	Sp0;
	byte	Sp1;
	word	VerifyId;
};

struct IS_NCN // New ConN
{
	char	NCN	[4];

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

	byte	Admin;
	byte	Sp1;
	byte	Sp2;
	byte	Sp3;

	byte	ConnNum;	// new conn's number (0 = host, 1, 2...)
	byte	Total;		// number of connections on host, including host
	word	VerifyId;
};

struct IS_CNL // ConN Leave (end connection is moved down into this slot)
{
	char	CNL	[4];

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

	byte	ConnNum;
	byte	Total;
	word	VerifyId;
};

struct IS_NPL // New PLayer joining race (if number already exists, then leaving pits)
{
	char	NPL	[4];

	char	UName	[24];	// username
	char	PName	[24];	// nickname
	char	Plate	[8];	// number plate - NO ZERO AT END!
	char	CName	[32];	// car name

	word	Flags;		// player flags (see below)
	byte	Type;		// bit 0 - female / bit 1 - AI
	byte	UniqueId;	// player's assigned unique id

	byte	PlyNum;		// player's number (0 = pole, 1, 2...)
	byte	Total;		// number in race (same when leaving pits, 1 more if new)
	word	VerifyId;
};

struct IS_PLP // PLayer Pits (go to settings - stays in player list)
{
	char	PLP	[4];

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

	byte	UniqueId;	// player's assigned unique id
	byte	Sp1;
	byte	Sp2;
	byte	Sp3;

	byte	PlyNum;		// player's number (stays in list)
	byte	Total;		// new total (expect : same as before)
	word	VerifyId;
};

struct IS_PLL // PLayer Leave race (spectate - leaves player list, all are shunted down)
{
	char	PLL	[4];

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

	byte	UniqueId;	// player's assigned unique id
	byte	Sp1;
	byte	Sp2;
	byte	Sp3;

	byte	PlyNum;		// player's number (others shunt down)
	byte	Total;		// new total (expect : 1 less than before)
	word	VerifyId;
};

struct IS_CPR // Conn Player Rename
{
	char	CPR		[4];

	char	UName	[24];	// username
	char	OldName	[24];	// old name
	char	NewName	[24];	// new name
	char	Plate	[8];	// number plate - NO ZERO AT END!

	byte	UniqueId;	// unique id : 0 = connection has no player in race
	byte	Sp1;
	word	VerifyID;
};

struct IS_CLR // CLear Race - all players removed from race in one go
{
	char	CLR	[4];

	byte	Sp0;
	byte	Sp1;
	word	VerifyId;
};

struct IS_LAP // LAP time
{
	char	LAP	[4];

	char	UName	[24];	// username
	char	PName	[24];	// nickname
	char	CName	[32];	// car name

	MSHT	Time;		// lap time

	byte	PlyNum;		// player's number
	byte	UniqueId;	// player's assigned unique id
	word	VerifyId;
};

struct IS_SPX // SPlit X time
{
	char	SPX		[4];	// SP1 / SP2 / SP3 + zero

	MSHT	Time;			// split time

	byte	PlyNum;			// player's number
	byte	UniqueId;		// player's assigned unique id
	word	VerifyID;
};

struct IS_RES // RESult (qualify or finish)
{
	char	RES	[4];

	char	UName	[24];	// username
	char	PName	[24];	// nickname
	char	Plate	[8];	// number plate - NO ZERO AT END!
	char	CName	[32];	// car name

	word	Flags;		// player flags
	byte	Type;		// bit 0 - female / bit 1 - AI
	byte	UniqueId;	// unique id : 0 = player already left before result was sent

	MSHT	TotalTime;	// race time
	MSHT	BestLap;	// best lap

	byte	ResultNum;	// position in results table (qualify may be inserted not at end)
	byte	NumResults;	// total number of results (qualify doesn't always add a new one)
	word	VerifyId;
};

struct PosId // NOT A PACKET - small 2-byte structure - part of the REO (below)
{
	byte	OldPos;		// old position in list
	byte	UniqueId;	// player's assigned unique id
};

struct IS_REO // REOrder (when race restarts after qualifying)
{
	char	REO	[4];

	PosId	Info	[28];	// old positions and unique id

	byte	Sp0;		// spare
	byte	NumPlayers;	// number of players in race
	word	VerifyId;
};

Player flags definition
-----------------------
SWAPSIDE	1
GEARCHANGECUT	2
GEARCHANGEBLIP	4
AUTOGEARS	8
RESERVED_1	16
OLD MOUSE	32
HELP_BRAKE	64
HELP_THROTTLE	128
RESERVED_2	256
AUTOCLUTCH	512
MOUSE		1024
KB_NO_HELP	2048
KB_STABILISED	4096

NON-VERIFIED TRACKING PACKETS - do not send an acknowledgement reply to these packets
-----------------------------
If NodeSecs was set in the InSimInit packet, LFS will send IS_NLP or IS_MCI packets at
the specified interval, depending on the InSimInit initialisation flag ISF_NLP_MCI.

When ISF_NLP_MCI flag is NOT SET...

struct NodeLap // NOT A PACKET - small 4-byte structure - part of the NLP (below)
{
	word	Node;		// current path node
	byte	Lap;		// current lap
	byte	UniqueId;	// player's assigned unique id
};

struct IS_NLP // Node and Lap Packet
{
	char	NLP	[4];

	word	NumNodes;	// total number of nodes in the path
	word	FinishLine;	// the node number of the finish line

	byte	NumPlayers;	// number of players in race
	byte	Sp1;		// spare
	byte	Sp2;		// spare
	byte	Sp3;		// spare

	NodeLap	Info	[28];	// node and lap of each player
};

When ISF_NLP_MCI flag is SET...

struct CompCar // NOT A PACKET - Car info in a 24-byte structure - part of the MCI (below)
{
	word	Node;		// current path node
	byte	Lap;		// current lap
	byte	UniqueId;	// player's assigned unique id
	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 : (see note 1 below)
	word	Heading;	// direction of forward axis : (see note 1 below)
	short	AngVel;		// signed, rate of change of heading : (see note 2)
};

Note 1 : 0 = world y axis direction, 32768 = 180 degrees, anticlockwise from above
Note 2 : 0 = no change in heading, 8192 = 180 degrees per second anticlockwise

struct IS_MCI // MultiCarInfo - if more than 8 in race then more than one of these is sent
{
	char	MCI	[4];

	word	NumNodes;	// total number of nodes in the path
	word	FinishLine;	// the node number of the finish line

	byte	NumPlayers;	// number of players in race
	byte	FirstPly;	// first player in this packet (0 in 1st packet, 8 in 2nd...)
	byte	Sp2;		// spare
	byte	Sp3;		// spare

	CompCar	Info	[8];	// car info for each player, max 8 per packet
};

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

Id	: "NLI"         (Node Lap Interval)
Value	: Interval      (0 means stop, otherwise interval in milliseconds, minimum 100)

TRACKING PACKET REQUESTS
------------------------
- send to LFS to request player / connection / result packets
- these requests work even if race tracking is not switched on

To request a IS_RES, send a InSimPack with Id = "RES" and value = result number (0,1,2...)
To request a IS_NPL, send a InSimPack with Id = "NPL" and value = player number (0,1,2...)
To request a IS_NCN, send a InSimPack with Id = "NCN" and value = conn number (0,1,2...)
To request a IS_NLP, send a InSimPack with Id = "NLP" and value = 0
To request a IS_MCI, send a InSimPack with Id = "MCI" and value = 0


Car Position Packets : (Initialising OutSim from InSim)
======================

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

Id	: "SSP" - Start Sending Positions (sends UDP packets using OutSim system)
Value	: delay between updates (zero means stop sending)

The SSP packet makes LFS start sending UDP packets if in game, using the OutSim
system as documented at the end of the README.txt file.

You do NOT need to set any OutSim values in LFS cfg.txt as OutSim is automatically
initialised by the SSP packet.

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

Note : OutSim packets don't have a 4-byte header like InSim packets.
- You can identify an OutSim packet by its size (64 bytes) and first byte (zero).


Camera Control :
================

In-game mode 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 SetCarCamera		// Simplified camera packet (not SHIFT+U mode)
{
	char	Id	[4];	// SCC + zero
	byte	ViewPlayer;	// Player Index of car to view (0 = pole...)
	byte	InGameCam;	// InGameCam (as reported in StatePack)
	byte	UniqueId;	// Overrides ViewPlayer if set
	byte	Spare3;
};

Special case : set ViewPlayer or InGameCam to 255 to leave that option unchanged.
Note : if UniqueId is used, the ViewPlayer byte will be ignored

Direct camera control
---------------------
A Camera Position Packet can be used for LFS to report a camera position and state,
and for the external program to set LFS camera position in game or SHIFT+U mode.

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

struct CamPosPack		// Full camera packet (in game OR SHIFT+U mode)
{
	char	Id	[4];	// CPP + zero
	Vec	Pos;		// Position vector
	word	Heading;	// 0 points along Y axis
	word	Pitch;		// 0 means looking at horizon
	word	Roll;		// 0 means no roll
	byte	ViewPlayer;	// Player Index of car to view (0 = pole...)
	byte	InGameCam;	// InGameCam (as reported in StatePack)
	float	FOV;		// 4-byte float : FOV in radians
	word	Time;		// Time to get there (0 means instant + reset)
	word	Flags;		// State Flags
}

State flags controlling this packet
-----------------------------------
The relevant Flags that can be set are :

#define ISS_SHIFTU		8	// in SHIFT+U mode
#define ISS_SHIFTU_HIGH		16	// HIGH view
#define ISS_SHIFTU_FOLLOW	32	// following car
#define ISS_VIEW_OVERRIDE	8192	// 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 ViewPlayer 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)
-------------------------
This is ignored for in-game (not SHIFT+U) cameras.

For SHIFT+U cameras, Pos can be either relative or absolute.

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

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" than your
updates.  For example, sending a camera position every 100 ms, with a Time value of
1000 ms.  LFS will make a smooth motion from these "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 an InSimPack like this :

Id	: "SCP"  (Send Camera Pos)
Value	: 0

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.

Stop and Start with an InSimPack like this :

Id	: "TMS"  (Time Stop)
Value	: 1 - stop / 0 - carry on

When STOPPED, make time step updates with this InSimPack :

Id	: "STP"  (Time Step)
Value	: 1, 2, 3, 4 etc, number of hundredths of a second to update

Request the current time at any point with this InSimPack :

Id	: "GTH"  (Get Time in Hundredths)
Value	: 0

The time will be sent back in this InSimPack :

Id	: "RTP"  (Race Time Packet)
Value	: Time   (Hundredths of a second since start of race or replay)


New text commands added to LFS - useful for InSim :
===================================================

Note : most host / admin commands are now available in single player

New command line startup options :
----------------------------------
/insim=PORT      (PORT is between 1 and 65535)
/windowed=X      (X = no/yes - overrides the cfg.txt setting)

Commands - general :
--------------------
/spr and /mpr commands to run SPR or MPR from entry (front end) screen
/end command to exit from replay back to front end
/qualify and /restart for host / single player / admin
/sp - go into single player from entry screen

Commands for game setup screen :
--------------------------------
/ai [NAME] add ai driver (can specify NAME)
/ready and /cancel - set ready or cancel ready
/clear - clear all racers from list
/car X - select car (FRTBO46M) - if not already in race
/setup X - select setup name X - if not already in race

LFS - 8 April 2004