Nov 10 2005
by op9080

Q: What is it?
A: A GTA San Andreas loader & script injector with source code.

Features:
========

1) Supports GTA SA v1.0 US & EU executables.  Automatically detects the
   version and uses the correct addresses.

2) Either starts a new instance of the game or connects to an
   existing instance if there's one running.

3) Can run the game in either fullscreen or window mode.  You can
   switch between fullscreen and window mode while running by
   pressing the Alt-Enter hotkey.
   Limitation: Window mode is only possible if your game resolution
   is strictly smaller than your desktop resolution (so that it
   can fit the entire window with its frame in).  Otherwise it
   will run in fullscreen.

4) Injects a custom script into the script engine.  The custom
   script can be paused/continued by pressing Alt-S.  The default
   script it comes with lets you explore Liberty City.  Press
   Alt-L to go to Liberty City.  Press Alt-G to return to the
   mainland.  You can take a vehicle if you want.  If you don't,
   a Banshee will be spawned for you.  You'll also get a jetpack,
   and unlimited height on the jetpack so you can explore all
   of Saint Mark's.
   Warning: very little of LC is solid in SA, so you'll quickly fall
   off on ground.  If you do, press Alt-G for rescue.  If you're in your
   own car, you'll get an insane stunt of around 10000 feet as a bonus :-)

5) Will disable some of the splash screens on startup (thanks to kyeman).

6) Press Alt-F10 to reduce gravity by a factor of 50.  Press Alt-F10
   again to return to normal (thanks to Stretchnutter).

7) Press Alt-F9 to remove the game's 270 KPH speed limit on the
   Hydra.  Press Alt-F9 again to reinstate the limit.

8) Press Alt-F8 to set unlimited height on aircraft.  Press Alt-F8
   again to reinstate the limit.

Command line options:
====================
-window : run in window mode
-fullscreen : run fullscreen (the default)
-script : inject the script (the default)
-noscript : don't inject the script
-splash : enable splash screens
-nosplash : disable splash screens (the default)


For developers who want to use the source code:
==============================================
- Doesn't use a DLL.  Instead it loads itself into the GTA SA process.
- Was built using MSVC 7.1.  I've tried to remove all incompatibilities
  with MSVC 6.0, so hopefully it will compile with 6.0 as well.
  You must link with the /FIXED:NO linker option.  It's also recommended
  that you set a high base address with /BASE (My project file uses /BASE:0x48320000).
- You can add your own hotkeys in customKeyHook().
- You can add special script processing code in customScriptHook()
  define the symbol DO_CUSTOM_SCRIPT_HOOK to enable this.
- There's a skeleton hook for IDirect3DDevice9::Present() if you
  want to do some custom drawing.  Add the code in customPresent()
  and define the symbol DO_CUSTOM_PRESENT.
- It has a set of iostream-style classes to support script building.
  They support insertion of opcodes, GTA parameter types 1 - 9,
  jump labels and If-Then-Else blocks.  You can look at the sample
  scripts in custom.cpp to get the idea.  Below is full documentation.
- If you don't want to use the supplied classes, you can use your
  favorite script builder/compiler and stuff raw script bytes
  with Script::add().
- For a GXT hook, define DO_GXT_HOOK and use customStrings().
- For full thread control, define DO_FULL_THREAD_CONTROL and
  use customThreadFilter().  This lets you decide which threads of
  main.scm get executed and which don't.
- Don't use malloc(), use Win32 API such as
  HeapAlloc(GetProcessHeap(), ...) instead.
- If you statically link to DLLs that are not normally loaded
  by gta_sa.exe, you need to explicitly LoadLibrary() them after
  being transferred to the gta_sa process.

Changelog:
=========
Nov 15 2005
- added unlimited height on aircraft.
Nov 13 2005
- added unlimited height jetpack to Liberty City explorer.
- added speed limit remover for the Hydra.
Nov 10 2005
- updates timers @32 @33 in injected script
- GXT hook
- full thread control
- does not unhook if have custom jobs
Nov 09 2005
- fixed some MSVC 6.0 compilation issues
Nov 08 2005
- original version

Building Scripts:
================
To insert an opcode
  script << opcode(number)
or use one of the named statically defined opcodes in Opcodes.h (thanks
to spookie).  You can also add your own named opcodes to Opcodes.h.

To insert an integer or float parameter
  script << number
it automatically chooses the correct type and size for the parameter.

To insert a local variable reference
  script << L(var_number)
var_number should be in the range 0-33 for non-mission scripts and 0-1023
for mission scripts.  Local vars 32-33 are timers.  You can also declare
and name your local vars, see the example in the code.

To insert a global variable reference
  script << G(var_number)
var_number should be in the range 2 - 10949.

To insert an array reference
  script << A(v1, v2)
where v1 and v2 are either an L() or a G().  v1 is the array base and v2 is the index.

To insert a fixed length 8-character string (GTA parameter type 9)
  script << "string"

Note: GTA SA parameter types 10-19 are not supported in this version.

For opcodes that have a variable-length parameter list and need
the parameter list terminated with a '\0', use:
  script << endparams;

jump labels:
You can define labels for use with jump/jump_if_false/gosub like this

Label l1, l2;
script << jump << l1;		// forward label reference
... some script code ...
script >> l2;				// sets position of label l2
... more script code ...
script >> l1;				// sets position of label l1
... more script code ...
script << jump << l2;		// backward label reference

If-Then-Else blocks:
script << If << conditional_expression << Then;
script       << body_of_then;
script << ElseIf << conditional_expresssion << Then;	// optional
script       << body_of_elseif;
script << Else;		// optional
script       << body_of_else;
script << EndIf;

You can have as many ElseIf blocks as you want.
A conditional expression is one of
- conditional_opcode_statement
- conditional_opcode_statement << And << conditional_opcode_statement << And ... And << conditional_opcode_statement
- conditional_opcode_statement << Or << conditional_opcode_statement << Or ... Or << conditional_opcode_statement
You can have up to 9 conditions in a compound conditional expression.
You can't mix Ands and Ors in the same conditional expression.

Q: what are BareElse/BareElseIf/BareThen?
A: These are special forms that omit the auto-generated code and
   allow you more control.

Suppose you have code like this...
... some script code ...
script     << jump some_label;
script << Else;
... rest of script code ...

Normally, the Else generates a jump instruction to jump past the rest
of the else blocks to the end of the if statement.  However, in this
example, the auto-generated jump is unreachable since it's preceded
by a jump (might also be preceded by a return).  So you can use
the BareElse keyword instead to suppress the auto-generated jump.

... some script code ...
script     << jump some_label;
script << BareElse;
... rest of script code ...

BareElseIf is similar but replaces ElseIf.

BareThen is less useful - a Then generates an automatic
jump_if_false past the then block.  Suppose you have something like

script << If << condition << Then
script       << body_of_then
script << EndIf
script << jump someOtherPlace;

If the condition is false then 2 jumps will take place -
from the Then to past the EndIf, and from there to someOtherPlace.
You can short-circuit this double jump by using

script << If << condition << BareThen
script       << jump_if_false someOtherPlace;
script       << body_of_then
script << EndIf
script << jump someOtherPlace;

Note that it's never necessary to use the Bare form, so you needn't
worry about it if you don't want to.  It can just save a little
unreachable code space and some unnecessary double jumps.
