
         Texture Garden texture generation language specification
         ========================================================

    This file documents version 1.00 of the texture generation language
          This is distributed with Texture Garden version 1.00.

1.00 Introduction
1.10 The format of this file
2.00 Writing textures
2.10 Syntactic considerations
3.00 Command summary (commands grouped by class)
4.00 Command details (commands grouped by class)

1.00 Introduction
~~~~~~~~~~~~~~~~~
The Language:

When editing texture generation programs, some syntactical rules need to be
borne in mind.  The language is a compromise between three design criteria:

1: That it should be readable by a human
2: That it should be editable by the computer.
3: That it should go like the clappers.

Compactness was not considered to be particularly important. 
Characteristically commands are verbose.  It is recommended that typing in
commands using longhand is to be avoided and that cut and paste facilities
are employed wherever possible.

When loaded, commands are translated into an internal format and the original
textfile is discarded.  Loaded files may contain command names in any case,
truncated names, commands optionally abbreviated with the "." character,
confused and confusing punctuation and mismatched brackets.  When the file is
saved, it is cleaned up, reformatted and expanded into a standard format. 
Unless you know what you are doing, keeping copies of the original files is
recommended, as What The Computer Thinks You Are Talking About may initially
differ from What You Are Trying To Say.

Error checking is currently implemented mainly at the parsing stage.  If the
program you feed the computer contains errors, a message will tell you
which line they are found on.  These messages should be helpful in the
process of tracking down mistakes.  Runtime error messages are also possible,
but should occur rarely in practise.

If your version of this program is unregistered, then you will probably
experience difficulties in changing existing textures or getting your own
textures to be displayed.  Please refer to the "Register" document for
details of why this occurs.

Resources:

There are currently several main resources available for use in generating
textures.  The texture generation program "sees" a virtual machine with a
variety of storage media and one primary output channel.

There are three one dimensional buffers of &400 16-bit values which may be
manipulated.   One two dimensional buffer is provided, with dimensions
controlled by the size of the sprite to be generated.  A buffer for storing
colourmaps exists and there is space reserved for the manipulation of &400
variables.  These contain unspecified values on entry to the routine.

Texture generation programs are entered when a texture is required.  Their
execution begins at their first line.

1.10 The format of this file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the command summary which follows, each command is named and then it is
followed by a string in brackets indicating what kind of parameters it takes.
If there are no brackets then the command takes no parameters.  In the second
part of the document, descriptions of the operation of each of the commands
are also given.

Comments are considered to be anything after a "|" character.  Comments in
If...Then...Else lines are treated using the same conventions as in Obey
files, i.e. "If 1 = 2 THEN |ECHO Equal! ELSE ECHO Not_Equal!" would print
"Not_Equal!" in an Obey file, despite the earlier "|".

2.00 Writing textures
~~~~~~~~~~~~~~~~~~~~~
Conventions:

All textures should begin with a definition of their primary palette enclosed
by the commands "StartColourDefinition" and "EndColourDefinition".

Textures terminate when they reach the "End" command.  It is conventional to
place subroutine definitions after the "End" so they are separate from the
main program.  The mutator may rely on this in the future.

2.00 Syntactic considerations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Essentially, the syntax of the language is simple.  

Everything falls into one of four categories.

These four categories are: Comments, Commands, Functions and Parameters.

Comments are simple: they are considered to be anything after a "|"
character.

Commands come in three types: Conditional, Ordinary and Branch commands.

Conditionals have the form: "If <Condition> Then <Command> Else <Command>". 
The "Until <Condition>" command also comes into this category.

Ordinary commands normally appear at the start of each line.  They may have
zero or more parameters.  If they have parameters then these are enclosed in
brackets.

Branch related commands come in several types.  "Define <DefinitionMarker>"
sets a named mark at a point in the file, "Call <DefinitionMarker>" calls the
relevant "Define" and continues until a "Return" is encountered. 
"Goto <DefinitionMarker>" simply continues execution from the relevant
"Define".

Functions may be given instead of parameters.  They should never appear at
the start of a line.  Functions are defined over the domain (&0000-&FFFF). 
They generally range over (&0000-&FFFF).  That they have the same range as
their domains means that it is convenient to feed the results of functions
to other functions as parameters.

Parameters may cover the range from &0000 to &FFFF.  They may be given as
signed or unsigned, decimal or hexadecimal (with a preceding "&") integers. 
Where a parameter is required, this may be given as a constant numerical
value or as a function.  Variables may be used and are implemented as simple
functions.

Textures are not especially sensitive to punctuation mistakes, spaces, or
other idiosyncrasies.  If brackets are mismatched, the program guesses where
they should be and inserts them.  This is useful when editing textures in a
text editor.

3.00 Command summary (commands grouped by class)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Index
~~~~~
01 Functions
02 Types
03 Constants
04 Variables
05 Section of Functions of X and Y
06 Miscellaneous
07 Conditional
08 Mutation
09 Animation
10 Graphical output
11 Fourier Transform related
12 Variable Setting
13 Dithering
14 Processing
15 Linear segments
16 Shifting
17 Rotation
18 Loops
19 Buffer manipulation
20 Waves and Distortions
21 Colour related
22 Mirroring, Flipping and Shearing
23 Blobbing
24 Branching
25 Light sources and bump maps

Main List
~~~~~~~~~

01 Functions
~~~~~~~~~~~~
Combine(Type,A,B)
Add(A,B)
Subtract(A,B)
Max(A,B)
Min(A,B)
Multiply(A,B)
ScaledMultiply(A,B)
ScaledSignedMultiply(A,B)
SignedMultiply(A,B)
PartlyScaledSignedMultiply(A,B)
PartlyScaledMultiply(A,B)
Divide(Numerator,Denominator)
Eor(A,B)
And(A,B)
Or(A,B)
Absolute(A)
LogicalShiftLeft(A,Exponent)
LogicalShiftRight(A,Exponent)
ArithmeticShiftLeft(A,Exponent)
ArithmeticShiftRight(A,Exponent)
Variable(Variable_Number)
Random(And_value,Eor_value)
Sin(Theta)
Cos(Theta)
SignedSin(Theta)
SignedCos(Theta)
SquareRoot(Value)

02 Types
~~~~~~~~
SimpleAddition
UnboundedAddition
CeilingAddition
HalvingAddition
SimpleSubtraction
UnboundedSubtraction
FloorSubtraction
HalvingSubtraction
Maximise
Minimise
Overwrite
PositiveOverwrite
Preserve
Multiplication
ScaledMultiplication
Zeroise

03 Constants
~~~~~~~~~~~~
True
False
Zero
Ninety
OneHundredAndEighty
TwoHundredandSeventy
FloydSteinberg
RGB
HSV
CIE
Gourad
Phong
Specular
SpecularPhong

04 Variables
~~~~~~~~~~~~
X
Y
Z
Size
LogSize
LogBitsPerPixel
AnimationFrameNumber
AnimationType(Frequency)
Registered

05 Section of Functions of X and Y
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Noise(Intensity,MaximumFrequency)
PinkNoise(Intensity,MaximumFrequency)
QuickNoise(Intensity,MaximumFrequency)
BandpassNoise(Intensity,MinimumFrequency,MaximumFrequency)
BandpassQuickNoise(Intensity,MinimumFrequency,MaximumFrequency)
FractalNoise(MaximumIntensity,FractalDimension)
ShiftedSymmetricNoise(Intensity,MaximumFrequency,X,Y)
ShiftedSymmetricPinkNoise(Intensity,MaximumFrequency,X,Y)
ShiftedNoise(Intensity,MaximumFrequency,X,Y)
ShiftedPinkNoise(Intensity,MaximumFrequency,X,Y)
ShiftedSymmetricQuickNoise(Intensity,MaximumFrequency,X,Y)
ShiftedQuickNoise(Intensity,MaximumFrequency,X,Y)
ShiftedSymmetricFractalNoise(MaximumIntensity,FractalDimension,X,Y)
ShiftedFractalNoise(Intensity,MaximumFrequency,X,Y)

TwoDimensionalPoint(X,Y)
OneDimensionalPoint(X)
OneDimensionalPointOne(X)
OneDimensionalPointTwo(X)
QuickTwoDimensionalPoint(X,Y)
QuickOneDimensionalPoint(X)
QuickOneDimensionalPointOne(X)
QuickOneDimensionalPointTwo(X)

06 Miscellaneous
~~~~~~~~~~~~~~~~
Percentage(Percentage)
AddToPercentage(DeltaPercentage)
Beep
Bell
End
Checksum(Value)
Error(Value)
ErrorText <string>
ReportText <string>
UnknownCommand

07 Conditional
~~~~~~~~~~~~~~
If <Condition> Then <Command> Else <Command>...

IsLessThan(A,B)
IsGreaterThan(A,B)
IsLessThanOrEqualTo(A,B)
IsGreaterThanOrEqualTo(A,B)
SignedIsLessThan(A,B)
SignedIsGreaterThan(A,B)
SignedIsLessThanOrEqualTo(A,B)
SignedIsGreaterThanOrEqualTo(A,B)
IsEqualTo(A,B)
IsNotEqualTo(A,B)

08 Mutation
~~~~~~~~~~~
StopMutating
StartMutating

09 Animation
~~~~~~~~~~~~
StartAnimating
StopAnimating

10 Graphical output
~~~~~~~~~~~~~~~~~~~
MakeSprite
AddToSprite
MakeVirtualSprite(Type_R,Type_G,Type_B)
MakeSpriteFromVirtualSprite
TruncateSpriteVertically(Bottom,Top)
TruncateSpriteHorizontally(Left,Right)
ResizeSprite(XFactor,YFactor)

11 Fourier Transform related
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CreateTwoDimensionalFilter(Filter_Description)
TwoDimensionalTransform
SmoothTwoDimensionalTransform
CreateOneDimensionalFilter(Filter_Description)
OneDimensionalTransform
SmoothOneDimensionalTransform

12 Variable Setting
~~~~~~~~~~~~~~~~~~~
SetVariable(Variable_Number,Value)
SetAnimationFrameNumber(Value)

Seed(Value)
RestoreArtefactsFlags
Phase(Value)
NoiseToBeFiltered(Value)
CreateCosineSymmetry
CreateSineSymmetry
CreateCosineArtefacts(Value)
CreateSineArtefacts(Value)
AbandonCosinePhase
AbandonSinePhase

13 Dithering
~~~~~~~~~~~~
Dithering(Value)
DitheringOne(Value)
DitheringTwo(Value)
ScaledDithering(Value)

14 Processing
~~~~~~~~~~~~~
OneDimensionalProcess(X1,X2,Function,Type)
TwoDimensionalProcess(X1,X2,Y1,Y2,Function,Type)
OneDimensionalFilter(Left,Centre,Right,Type)
TwoDimensionalFilter(Top_Left,Top_Centre,Top_Right,Middle_Left,Middle_Centre,
  Middle_Right,Bottom_Left,Bottom_Centre,Bottom_Right,Type)
TwoDimensionalContrast(Value)
OneDimensionalContrast(Value)
OneDimensionalFlood(Threshold,Multiplier,Value,Type)
TwoDimensionalFlood(Threshold,Multiplier,Value,Type)
OneDimensionalEqualization
TwoDimensionalEqualization
TwoDimensionalInversion
OneDimensionalInversion
GenerateOneDimensionalDust(Threshold,NewValue,Type)
GenerateTwoDimensionalDust(Threshold,NewValue,Type)
TwoDimensionalClear
OneDimensionalClear
DefineSolidBlock(Block_Description)
Sculpture(Path_of_X,Path_of_Y,Path_of_Z)
Resize(XFactor,YFactor)
ResizeBumpMap(XFactor,YFactor)

15 Linear segments
~~~~~~~~~~~~~~~~~~
LinearField(Y1,Y2)
LinearSegment(X1,X2,H1,H2,Type)
LinearFieldSegment(H1,H2,X1,X2,Type)
Rectangle(I,X1,X2,Y1,Y2,Type)

16 Shifting
~~~~~~~~~~~
OneDimensionalShift(Delta_X,Type)
TwoDimensionalShift(Delta_X,Delta_Y,Type)

17 Rotation
~~~~~~~~~~~
QuickRotate(Theta,Type)
Rotate(Theta,Type)
SlowRotate(Theta,Type)
RotateAbout(Theta,X,Y,Type)
SlowRotateAbout(Theta,X,Y,Type)

18 Loops
~~~~~~~~
Repeat
Until(Condition)
For(Number_of_times_to_loop)
Next

19 Buffer manipulation
~~~~~~~~~~~~~~~~~~~~~~
OneDimensionalStoreBufferOne
OneDimensionalStoreBufferTwo
OneDimensionalSwapBufferOne
OneDimensionalSwapBufferTwo
OneDimensionalMaskBufferOne(Type)
TwoDimensionalStore
TwoDimensionalSwap
TwoDimensionalMask(Type)

20 Waves and Distortions
~~~~~~~~~~~~~~~~~~~~~~~~
VerticalDistortion(Type)
HorizontalDistortion(Type)
HorizontalWaveWarp(Type)
VerticalWaveWarp(Type)
HorizontalWaves(Type)
VerticalWaves(Type)

21 Colour related
~~~~~~~~~~~~~~~~~
StartColourDefinition
EndColourDefinition
CreateColours(ColourModel)
CreateColoursUsingRGBData
CreateColoursUsingHSVData
CreateColoursUsingCIEData

22 Mirroring, Flipping and Shearing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HorizontalMirror(Type)
VerticalMirror(Type)
LeadingDiagonalMirror(Type)
TrailingDiagonalMirror(Type)
HorizontalShear(Size,Type)
VerticalShear(Size,Type)

23 Blobbing
~~~~~~~~~~~
Ripples(Intensity,Radius,X,Y,Type)
Radials(Intensity,Radius,X,Y,Type,TypeTwo)

24 Branching
~~~~~~~~~~~~
Define <DefinitionMarker>
Goto <DefinitionMarker>
Call <DefinitionMarker>
Return

25 Light sources and bump maps
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DefineLightSource(LightModel,Theta,Phi)
ShineLightOnVirtualSprite


4.00 Command details (commands grouped by class)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                       01 Section of Functions
                       =======================

Combine(Type,A,B)
~~~~~~~~~~~~~~~~~
This function combines the values of A and B according to the rule described
by the "Type" given.  This type may be expressed as one of the following:

SimpleAddition, UnboundedAddition, CeilingAddition, HalvingAddition,
SimpleSubtraction, UnboundedSubtraction, FloorSubtraction,
HalvingSubtraction, Maximise, Minimise, Overwrite, PositiveOverwrite,
Preserve, Multiplication or ScaledMultiplication.

These are described in the section on types below.  Alternatively, A number
or expression may be given.  Please refer to the types section which contains
technical details on this.

Add(A,B)
~~~~~~~~
Equivalent and preferred to the Combine function using combination type
UnboundedAddition.
Returns (A + B) And &FFFF.

Subtract(A,B)
~~~~~~~~~~~~~
Equivalent and preferred to the Combine function using combination type 
UnboundedSubtraction.
Returns (A - B) And &FFFF.

Max(A,B)
~~~~~~~~
Equivalent and preferred to the Combine function using combination type
Maximise.
Returns the greater of A and B (A and B are considered unsigned).

Min(A,B)
~~~~~~~~
Equivalent and preferred to the Combine function using combination type
Minimise.
Returns the greater of A and B (A and B are considered unsigned).

Multiply(A,B)
~~~~~~~~~~~~~
Equivalent and preferred to the Combine function using combination type
Multiplication.
Returns A * B And &FFFF.

ScaledMultiply(A,B)
~~~~~~~~~~~~~~~~~~~
Equivalent and preferred to the Combine function using combination type
ScaledMultiplication.
Returns ((A * B) DIV &10000) And &FFFF.

ScaledSignedMultiply(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of (A * B) << 16, treating A and B as signed
integers.

SignedMultiply(A,B)
~~~~~~~~~~~~~~~~~~~
Function returning the value of A * B, treating A and B as signed integers.

PartlyScaledSignedMultiply(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of (A * B) << 8, treating A and B as signed
integers.

PartlyScaledMultiply(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of (A * B) << 8.

Divide(Numerator,Denominator)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of Integer(Numerator / Denominator)

Eor(A,B)
~~~~~~~~
Function returning the value of A Exclusive_Or B.

And(A,B)
~~~~~~~~
Function returning the value of A And B (bitwise AND).

Or(A,B)
~~~~~~~
Function returning the value of A Or B (bitwise OR).

Absolute(A)
~~~~~~~~~~~
IF A < &8000 THEN returns A ELSE returns A Exclusive_Or &FFFF.

LogicalShiftLeft(A,Exponent)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of A * 2^Exponent (A << Exponent).

LogicalShiftRight(A,Exponent)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of Integer(A / 2^Exponent) (A >> Exponent).

ArithmeticShiftLeft(A,Exponent)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of A * 2^Exponent (A << Exponent).

ArithmeticShiftRight(A,Exponent)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of A / 2^Exponent treating A as a signed
integer.

Variable(Variable_Number)
~~~~~~~~~~~~~~~~~~~~~~~~~
Returns the value of the <Variable_Number>th system variable.

Random(And_value,Eor_value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function returning the value of a 16-bit system random number generator ANDed
with <And_value> and then EORed with <Eor_value>.

Sin(Theta)
~~~~~~~~~~
Returns ((Sin of <Theta>) + 0.5) * &8000.

Cos(Theta)
~~~~~~~~~~
Returns ((Sin of <Theta>) + 0.5) * &8000.

SignedSin(Theta)
~~~~~~~~~~~~~~~~
Returns (Sin of <Theta>) * &8000.

SignedCos(Theta)
~~~~~~~~~~~~~~~~
Returns (Sin of <Theta>) * &8000.

SquareRoot(Value)
~~~~~~~~~~~~~
Returns the square root of Value.

                      02 Section of Types
                      ===================

Types govern how two parameters are combined with one another.  Precicely
which two parameters it refers to depends on the function using it.  Often, a
process will perform some calculation on the value of a function at a point
and then recombine this with the original value at that point before using
its result.

In the following description of the common Types, A and B are used to
describe the two values to be combined.

SimpleAddition
~~~~~~~~~~~~~~
IF A + B < &10000 THEN returns (A + B) ELSE returns &20000 - (A + B).

This produces an effect like a ball bouncing off a ceiling (ahem).

UnboundedAddition
~~~~~~~~~~~~~~~~~
Returns (A + B) And &FFFF.

CeilingAddition
~~~~~~~~~~~~~~~
IF A + B < &10000 THEN returns (A + B) ELSE returns &FFFF.

HalvingAddition
~~~~~~~~~~~~~~~
Returns (A + B) DIV 2 (A and B are considered unsigned).

SimpleSubtraction
~~~~~~~~~~~~~~~~~
IF A - B > 0 THEN returns (A - B) ELSE returns (B - A).

This produces an effect like a ball bouncing off a floor.

UnboundedSubtraction
~~~~~~~~~~~~~~~~~~~~
Returns (A - B) And &FFFF.

FloorSubtraction
~~~~~~~~~~~~~~~~
IF A - B > 0 THEN returns (A - B) ELSE returns 0.

HalvingSubtraction
~~~~~~~~~~~~~~~~~~
Returns (A - B) DIV 2 (A and B are considered unsigned).

Maximise
~~~~~~~~
Returns the greater of A and B (A and B are considered unsigned).

Minimise
~~~~~~~~
Returns the lesser of A and B (A and B are considered unsigned).

Overwrite
~~~~~~~~~
Returns B.

PositiveOverwrite
~~~~~~~~~~~~~~~~~
Returns (B EOR &8000).

Preserve
~~~~~~~~
Returns A.

Multiplication
~~~~~~~~~~~~~~
Returns A * B And &FFFF.

ScaledMultiplication
~~~~~~~~~~~~~~~~~~~~
Returns ((A * B) DIV &10000) And &FFFF.

Zeroise
~~~~~~~
Returns 0.
                         03 Section of Constants
                         =======================

True
~~~~
Returns &FFFF.

False
~~~~~
Returns 0.

Zero
~~~~
Returns 0.

Ninety
~~~~~~
Returns &4000.

OneHundredAndEighty
~~~~~~~~~~~~~~~~~~~
Returns &8000.

TwoHundredandSeventy
~~~~~~~~~~~~~~~~~~~~
Returns &C000.  These commands are useful in connection with "Rotate".  They
are not affected by the mutation engine.

FloydSteinberg
~~~~~~~~~~~~~~
Returns &FEBE (from "FloydstEinBErg"). Used with the "Dithering" command.

RGB
~~~
Returns 0.  Usually used as a description of a colour model.

HSV
~~~
Returns 1.  Usually used as a description of a colour model.

CIE
~~~
Returns 2.  Usually used as a description of a colour model.

Gourad
~~~~~~
Returns 0.  Usually used as a lightsource type.

Phong
~~~~~
Returns 1.  Usually used as a lightsource type.

Specular
~~~~~~~~
Returns 2.  Usually used as a lightsource type.

SpecularPhong
~~~~~~~~~~~~~
Returns 3.  Usually used as a lightsource type.

                          04 Section of Variables
                          =======================

X
~
Y
~
Z
~
Return X, Y, and Z in appropriate situations.  In OneDimensional commands, Y
is always 0.  Z should not be used, except in "DefineSolidBlock" commands.

Size
~~~~
Returns the size at which the texture is being generated.  This should not
normally be referred to.

LogSize
~~~~~~~
Returns the size at which the texture is being generated.  This should not
normally be referred to.

LogBitsPerPixel
~~~~~~~~~~~~~~~
Returns the log in base 2 of the number of bits-per-pixel in the screen mode
in which the texture is being generated.  This may be usefully referred to
when choosing dithering patterns for the texture: e.g.

AnimationFrameNumber
~~~~~~~~~~~~~~~~~~~~
Returns the number of the animation frame currently being generated.
This is only of interest if the texture is to be animated.

AnimationType(Frequency)
~~~~~~~~~~~~~~~~~~~~~~~~
Returns the value of the corresponding value to Frequency in the buffer
controlling the type of animation to be used.  This buffer can be thought of
as containing 1024 signed 4-bit values, controlling the way in which various
frequencires in the texture are animated.  This should only normally be
referred to if the texture is to be animated.  If the texture is not being
animated and the "Use animation type" option is not on then it returns 0.

Registered
~~~~~~~~~~
Returns 0 if the user has the Freeware demonstration version of
Texture Garden: some non-zero value otherwise.

                  05 Section of Functions of X and Y
                  ==================================

These functions are functions of X and Y as well as of their parameters.
They are mainly used for describing filters by using a command like
"CreateTwoDimensionalFilter".  Filters are usually used to filter random
noise prior to this result then being inverse-fourier-transform'd.  The
descriptions of the functions describe what they look like when viewed in the
frequency domain.  Descriptions in three dimensions use the convention of
describing the value of the function at a position (X,Y) as its "height" at
that point.

Noise(Intensity,MaximumFrequency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a circle about the origin.  In
three dimensions it looks like a cylindrical tin can of height H = Intensity.

PinkNoise(Intensity,MaximumFrequency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a circle about the origin.  It
fades towards the edges and may be visualised in three dimensions as a cone
or "witches hat" of height H = Intensity.

QuickNoise(Intensity,MaximumFrequency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a square about the origin.  In
three dimensions it looks like  a square office block of height
H = Intensity.

BandpassNoise(Intensity,MinimumFrequency,MaximumFrequency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a circle about the origin with its
centre hollowed out.  In three dimensions it looks like a doughnut of height
H = Intensity with sharp corners.

BandpassQuickNoise(Intensity,MinimumFrequency,MaximumFrequency)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a square about the origin with its
centre hollowed out.  In three dimensions it looks like a square office block
with a square central courtyard.

FractalNoise(MaximumIntensity,FractalDimension)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This function looks like a mountain whose sides follow the function
H = FractalDimension/(RxR) where R is the distance from the origin.  The
mountain is truncated at H = MaximumIntensity.

ShiftedNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a circle centred at (X,Y).  In
three dimensions it looks like a cylindrical tin can of height H = Intensity.

ShiftedPinkNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a circle centred at (X,Y).  It
fades towards the edges and may be visualised in three dimensions as a cone
or "witches hat" of height H = Intensity.

ShiftedQuickNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like a square centred at (X,Y).  In
three dimensions it looks like  a square office block of height
H = Intensity.

ShiftedFractalNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This function looks like a mountain whose sides follow the function
H = FractalDimension/(RxR) where R is the distance from the point (X,Y).  The
mountain is truncated at H = MaximumIntensity.

ShiftedSymmetricNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like four circles centred at (X,Y),
(-X,Y), (X,-Y) and (-X,-Y).  In three dimensions it looks like four
cylindrical tin cans of height H = Intensity.

ShiftedSymmetricPinkNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like four circles centred at (X,Y),
(-X,Y), (X,-Y) and (-X,-Y).  They fade towards their edges and may be
visualised in three dimensions as four cones or "witches hats" of height
H = Intensity.

ShiftedSymmetricQuickNoise(Intensity,MaximumFrequency,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The plan view of this function looks like four squares centred at (X,Y),
(-X,Y), (X,-Y) and (-X,-Y).  In three dimensions they look like four square
office blocks of height H = Intensity.

ShiftedSymmetricFractalNoise(MaximumIntensity,FractalDimension,X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This function looks like four mountains whose sides follow the function
H = FractalDimension/(RxR) where R is the distance from the point (X,Y).  The
mountains are symmetrical about the lines X = 0 and Y = 0.  The mountains are
truncated at H = MaximumIntensity.

TwoDimensionalPoint(X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~
Returns the value or "height" at the point (X,Y).  This command and the three
that follow it employ an anti-aliising technique to smooth sharp edges.

OneDimensionalPoint(X)
~~~~~~~~~~~~~~~~~~~~~~ Returns the value or "height" at the point (X) in the
main one-dimensional buffer.

OneDimensionalPointOne(X)
~~~~~~~~~~~~~~~~~~~~~~~~~
Returns the value or "height" at the point (X) in the first one-dimensional
buffer.

OneDimensionalPointTwo(X)
~~~~~~~~~~~~~~~~~~~~~~~~~
Returns the value or "height" at the point (X) in the second one-dimensional
buffer.

QuickTwoDimensionalPoint(X,Y)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
QuickOneDimensionalPoint(X)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
QuickOneDimensionalPointOne(X)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
QuickOneDimensionalPointTwo(X)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These four commands are identical to the four above them, except for the fact
that they do not employ any anti-aliasing techniques.

                          06 Miscellaneous commands
                          =========================

Percentage(Percentage)
~~~~~~~~~~~~~~~~~~~~~~
Displays the percentage of the texture completed using the hourglass.
The "Percentage" parameter's domain may be considered as being either from
&0 to &63 (99) or from &80 to &63FF (100 * 256 - 1).  Using Percentage(&FFFF)
turns off the percentage display.

AddToPercentage(DeltaPercentage)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adds the value of DeltaPercentage to the current hourglass percentage.

Beep
~~~~
Bell
~~~~
These produce a short beep using an equivalent to VDU 7.

UnknownCommand
~~~~~~~~~~~~~~
This is not a command that should ever appear in a file, bit is inserted
whenever a command is not recognised.  If a texture does not form, and saving
the texture as a textfile contains this command, then probably some mistake
has been make in the typing of new commands.

End
~~~
This command should always be included at the end of the texture file and
before any subroutines are declared.  It should always be present, by
convention.

Checksum(Value)
~~~~~~~~~~~~~~~
This command is included as a marketing device for the program.  It enables
distribution of a version of the program that can read and display textures,
and allow their saving as bitmaps, while not allowing unregistered users to
edit the programs that generate these textures.

In unregistered versions of the program, textures which do not contain the
correct value in their checksum or contain no checksum at all are rejected by
the program and not displayed.  This limits the extent to which unregistered
users may manipulate their textures.

In registered versions, an additional module is supplied which will enable
the program (and all future upgrades of it) to read textures independently of
the checksum.

A site license or Super-user version will also display whether the checksum
is correct, and will write texture files with correct checksums, enabling
people other than the author to distribute textures readable by the freeware
distributed version of the program.

Error(Value)
~~~~~~~~~~~~
This is provided for debugging purposes.  When it is executed, texture
generation is terminated and control is returned to the user.  The "Value"
is reported to the user.

Report(Value)
~~~~~~~~~~~~
This is provided for debugging purposes.  When it is executed, the value of 
"Value" is sent via WIMP messages to a program such as my own !Zephyr, which
keeps a scrolling window of text for the purposes of debugging WIMP
applications.  Message number &804C0 is used.

ErrorText <string>
~~~~~~~~~~~~~~~~~~
When executed, texture generation is terminated and control is returned to
the user with the <string> reported as an error message.

ReportText <string>
~~~~~~~~~~~~~~~~~~~
When executed, <string> is sent via WIMP message to a WIMP debugging program
such as my own !Zephyr.  Message number &804C0 is used with a block
containing the raw text to be sent.

UnknownCommand
~~~~~~~~~~~~~~
This is for internal use only and should not be used.

                       07 Conditional commands
                       =======================

If <Condition> Then <Command> Else <Command>...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This command is unusual in that it does not require brackets for its
parameters.  The syntax is identical to the way if statements are used in
Obey files. The commands may optionally contain further If statements. 
Comments are treated as they would be in Obey files, i.e. "If 1 = 2 THEN
|ECHO Equal! ELSE ECHO Not_Equal!" would print "Not_Equal!" in an Obey file,
despite the earlier "|".

Digression beginning...

"If ... Then ... If ... Then ... Else" constructs currently treat the Else as
belonging to BOTH "If"s.  One can't help thinking that "If ... Then ... If
... Then ... Else ... Else" should make sense - i.e. the "Else" should belong
to the nearest "If".  Unless the "Ifs" are nested in this manner one of them
cannot have an "Else" without the other one getting it too.  However, BASIC
does not agree (and that's BBC BASIC, the official Englishman's dialect).  No
doubt the Germans would have implemented it as they are used to recursively
peeling verbs from their sentences and correlating them with earlier nouns. 
Still, the sentence "The boy, the girl, the man, kissed, hit, ran" is reputed
to be good English, though no-one seems quite to be able to get their head
'round it.  I suppose it is possible to invert the first condition so that
the "If" comes after the "Else" instead of after the Then (unless the command
required there is another "If" statement).

Obey files don't seem to like their "If"s nested either (programmers must
find it easier to just look for the next "Else" than to count the
intermediate "If"s), and so neither does Texture Garden (which tries to
follow the Obey file syntax, so its files can be displayed in Obey file
syntax-colouring modes in text editors).

...digression end.

As <Condition>s you cannot use "<", "=", ">=" "!=" etc.  A list of conditions
that are acceptable follows:

IsLessThan(A,B)
~~~~~~~~~~~~~~~
IsGreaterThan(A,B)
~~~~~~~~~~~~~~~~~~
IsLessThanOrEqualTo(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~
IsGreaterThanOrEqualTo(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
SignedIsLessThan(A,B)
~~~~~~~~~~~~~~~~~~~~~
SignedIsGreaterThan(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~
SignedIsLessThanOrEqualTo(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SignedIsGreaterThanOrEqualTo(A,B)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IsEqualTo(A,B)
~~~~~~~~~~~~~~
IsNotEqualTo(A,B)
~~~~~~~~~~~~~~~~~
These functions are fairly self explanatory, and I hope a single example will
suffice:

IsLessThan(A,B) returns TRUE (&FFFF or -1) if A is less than B, otherwise it
returns FALSE (0).

                        08 Mutation Commands
                        ====================

StopMutating
~~~~~~~~~~~~
This command effectively stops the system from mutating until the next
StartMutating command.  This has the effect of stopping any intervening
commands from being affected by any mutations or sexual recombination that
may occur.  This may be of use when stopping mutations affecting parts of the
texture whose structural integrity is important.

StartMutating
~~~~~~~~~~~~~
Reverses the effect of the last "StopMutating" command.

                      09 Animation Commands
                      =====================

StopAnimating
~~~~~~~~~~~~~
This command effectively stops the system variable "AnimationFrameNumber"
from affecting the texture until the next StartAnimating command.  This has
the effect of stopping any intervening commands from being affected by any
animation that is occuring.  This may be of use when stopping palettes which
are declared using Fourier transforms from being "animated" causing the
palette to change then this is considered undesirable.

StartAnimating
~~~~~~~~~~~~~~
Reverses the effect of the last "StopAnimating" command.

See also:
SetAnimationFrameNumber, AnimationFrameNumber and AnimationType(Frequency).

                   10 Graphical output commands
                   ============================

MakeSprite
~~~~~~~~~~
Creates a sprite in the current mode using the current colourmap.

AddToSprite
~~~~~~~~~~~
Adds to an existing sprite using the current colourmap.  The existing sprite
is written to only at the points where the value at (X,Y) is non-zero.

MakeVirtualSprite(Type_R,Type_G,Type_B)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This makes a 24-bit colour virtual sprite.

This is useful when creating images by using multiple layers of texture.

"Type_R", "Type_G" and "Type_B" are the combination-types to be used when
adding to an existing sprite for red, green and blue components respectively.

The virtual sprite should not be assumed to be blank when it is created
and so the first occurrence of this command should normally use
"Overwrite,Overwrite,Overwrite" as its parameters.

MakeSpriteFromVirtualSprite
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This command makes a RISC OS sprite from the 24-bit virtual sprite created
by a previous "MakeVirtualSprite" command.

FloydSteinberg dithering may be applied, but will only produce noticable
effects if the texture is rendered in 16, 256 or 32K modes.  In 16M modes,
FloydSteinberg dithering is not required.

The "MakeSpriteFromVirtualSprite" command usually leaves the virtual sprite
unaffected, but if FloydSteinberg dithering is being used, it is altered to
the dithered version of the sprite in the selected mode.

One point to note is that dithering should always be set either to "Zero"
or to "FloydSteinberg" before this command is executed.  As the dithering
command is affected by the mutator this should not be as a raw number, but as
one of the strings mentioned above.

This is for compatibility with other possible future dithering routines.

TruncateSpriteVertically(Bottom,Top)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Truncates the top and bottom edges from the sprite. * #

TruncateSpriteHorizontally(Left,Right)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Truncates the left- and right-hand edges from the sprite. * #

ResizeSprite(XFactor,YFactor)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Performs "TruncateSpriteHorizontally(0,XFactor)" and
"TruncateSpriteVertically(0,YFactor)".  This is the method used by
Texture Garden's front-end to resize textures.

* Note that with these commands, the sprite may not subsequently be added
  to.  These operations may stop the resulting sprite from tessellating.

# These commands should only be used when resizing the texture using the
  front-end is not necessary, as they will stop textures from being resized.

                    11 Fourier Transform related commands
                    =====================================

CreateTwoDimensionalFilter(Filter_Description)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This function is a function of X and Y as well as of its parameter
"Filter_Description".  It generates a field of values in the main two
dimensional working buffer.  These form a "Filter" which is usually used to
filter random noise with the result then being inverse-fourier-transform'd. 
The functions commonly used are described in a different section.  Filters
may be defined in other ways, if so desired, but this is the main recommended
method.

TwoDimensionalTransform
~~~~~~~~~~~~~~~~~~~~~~~
This and the command that follow it perform a series of operations on the
main two dimensional working buffer.  First, the contents of the buffer are
used as a filter to filter a spectrum of random white noise.

What noise is used and how the filtering is performed is affected by the
following commands: Seed(Value), Phase(Value), NoiseToBeFiltered(Value),
CreateCosineSymmetry, CreateSineSymmetry, CreateCosineArtefacts(Value),
CreateSineArtefacts(Value), AbandonCosinePhase, and AbandonSinePhase.

Exactly how these commands affect the filtering of the noise is partially
described elsewhere.

Next the resulting spectrum is exposed to an two-dimensional inverse fast
fourier transform.  This is an elaborate function that is capable of
converting a signal from the frequency domain into the space/time domain.  I
refer you to signal processing textbooks for further details.  Finally the
resultant vectors are converted to a series of amplitudes by squaring, adding
and then square-rooting their components.

SmoothTwoDimensionalTransform
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is identical to the above command, except the resulting values are
centred about &8000, eliminating the "spiky artefacts" that occur near H = 0
when the plain "TwoDimensionalTransform" is used.

CreateOneDimensionalFilter(Filter_Description)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See above description of this function in two dimensions.  The main one
dimensional buffer is used.  The filter is calculated only over the range
where Y = 0.

OneDimensionalTransform
~~~~~~~~~~~~~~~~~~~~~~~
See above description of this function in two dimensions.The main one
dimensional buffer is used.

SmoothOneDimensionalTransform
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See above description of this function in two dimensions.
The main one dimensional buffer is used.

                       12 Variable Setting commands
                       ============================

SetVariable(Variable_Number,Value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This sets variable number (Variable_Number MOD &400) to be equal to <Value>.

SetAnimationFrameNumber(Value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This sets the system variable "AnimationFrameNumber" to be equal to <Value>.
This not normally be referred to.  If the texture is to be animated manually
using batch files, then it may be used in conjunction with the "Use Animation
type" option.

Seed(Value)
~~~~~~~~~~~
Sets the seed to be used in the random number generators.

RestoreArtefactsFlags
~~~~~~~~~~~~~~~~~~~~~
Resets the "AbandonCosinePhase", "AbandonSinePhase", "CreateCosineSymmetry"
and "CreateSineSymmetry" flags to off.

Sets the values of "AbandonCosinePhase", "AbandonSinePhase",
"CreateCosineArtefacts" and "CreateSineArtefacts" to zero.

Phase(Value)
~~~~~~~~~~~~
Sets the phase to be used in the filtering of the random white noise to
<Value>.  This phase affects all frequencys equally.  Changing it smoothly
produces similar effects to animating the texture using the "Positive.Boring"
animation pattern.

NoiseToBeFiltered(Value)
~~~~~~~~~~~~~~~~~~~~~~~~
Sets the amplitude of the random white noise used in the filtering to
<Value>.

CreateCosineSymmetry
~~~~~~~~~~~~~~~~~~~~
When filtering white noise, eliminate all sin components.  This produces a
pattern guaranteed to at its maximum at its centre, with a rotational
symmetry of two.

CreateSineSymmetry
~~~~~~~~~~~~~~~~~~
When filtering white noise, eliminate all cosine components.  This produces a
pattern guaranteed to be zero at its centre, with a rotational symmetry of
two.

CreateCosineArtefacts(Value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When filtering white noise, this eliminates all cosine components with an
amplitude less than a certain value.  Its effect is like "CreateSineSymmetry"
but not as extreme.

CreateSineArtefacts(Value)
~~~~~~~~~~~~~~~~~~~~~~~~~~
When filtering white noise, this eliminates all sine components with an
amplitude less than a certain value.  Its effect is like
"CreateCosineSymmetry" but not as extreme.

AbandonCosinePhase
~~~~~~~~~~~~~~~~~~
When filtering white noise, this eliminates the effect of the noise on the
cosine components of the result.  Instead of white noise, "bright white
light" may be thought of as being used.

AbandonSinePhase
~~~~~~~~~~~~~~~~
See "AbandonCosinePhase" substituting "Sine" for "Cosine".

                      13 Dithering commands
                      =====================

The next three commands affect the way dithering is used in the generation of
palettes and sprites.

Dithering0 affects the red component of palettes defined using RGB data, the
"hue" component of palettes defined using HSV data and general
(within-palette) dithering when making Sprites.

Dithering1  affects the green component of palettes defined using RGB data
and the "saturation" component of palettes defined using HSV data.

Dithering2  affects the blue component of palettes defined using RGB data and
the "value" component of palettes defined using HSV data.

Floyd-Steinberg dithering is available if virtual sprites are being used
through the "Dithering(FloydSteinberg)" command.  Note that
"ScaledDithering(FloydSteinberg)" will not usually work.

Dithering(Value)
~~~~~~~~~~~~~~~~
Sets Dithering0, Dithering1 and Dithering2 to be equal to <Value>.

DitheringOne(Value)
~~~~~~~~~~~~~~~~~~~
Sets Dithering1 to be equal to <Value>.

DitheringTwo(Value)
~~~~~~~~~~~~~~~~~~~
Sets Dithering2 to be equal to <Value>.

ScaledDithering(Value)
~~~~~~~~~~~~~~~~~~~~~~
Sets Dithering0 to be equal to a value which depends on the colour depth of
the mode being used.  The precise Value given to Dithering0 varies as
follows:

Depth Result
 16M  0
 32K  Value * 3 / 8
 256  Value / 2
  16  Value
   4  Value * 2
   2  Value * 4
 If the result is greater than &FFFF, then it is set to this ceiling.

                    14 Processing commands
                    ======================

OneDimensionalProcess(X1,X2,Function,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The section of the main one dimensional buffer defined by (X1,X2) is
processed according to "Function" and combined with its original self using
combination-type "Type".  "Function" may usefully contain commands such as
"OneDimensionalPoint(X)".


TwoDimensionalProcess(X1,Y1,X2,Y2,Function,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The rectangle in the main two dimensional buffer defined by opposing corners
at (X1,Y1) and (X2,Y2) is processed according to "Function" and combined with
its original self using combination-type "Type".  "Function" may usefully
contain commands such as "TwoDimensionalPoint(X,Y)".

OneDimensionalFilter(Left,Centre,Right,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each point in the one dimensional buffer is processed by adding the values of
its two neighbours and itself (multiplied by one of three multipliers) and
dividing by &100 before combining it with its original self using
combination-type "Type".  The following diagram describes the position of the
relevant multipliers.

                -------------
                | L | C | R |
                -------------

TwoDimensionalFilter(Top_Left,Top_Centre,Top_Right,
                     Middle_Left,Middle_Centre,Middle_Right,
                     Bottom_Left,Bottom_Centre,Bottom_Right,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each point in the two dimensional buffer is processed by adding the values of
its eight neighbours and itself (multiplied by a series of multipliers) and
dividing by &100 before combining it with its original self using
combination-type "Type".  The following diagram describes the position of the
relevant multipliers.

                  ----------------
                  | TL | TC | TR |
                  ----------------
                  | ML | MC | MR |
                  ----------------
                  | BL | BC | BR |
                  ----------------

OneDimensionalContrast(Value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Multiplies the entire contents of the main one dimensional buffer by <Value>,
divides by &100 and then truncates any high bit "spillage".

TwoDimensionalContrast(Value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Multiplies the entire contents of the main two dimensional buffer by <Value>,
divides by &100 and then truncates any high bit "spillage".

OneDimensionalFlood(Threshold,Multiplier,Value,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the contents of the main one dimensional buffer at any point is less than
<Threshold>, this command multiplies it by <Multiplier>, divides by &100 and
then combines it with <Value> using combination-type "Type".

TwoDimensionalFlood(Threshold,Multiplier,Value,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the contents of the main one dimensional buffer at any point is less than
<Threshold>, this command multiplies it by <Multiplier>, divides by &100 and
then combines it with <Value> using combination-type "Type".

OneDimensionalEqualization
~~~~~~~~~~~~~~~~~~~~~~~~~~
This expands the range of the contents of the main one dimensional buffer
until it covers the range &0000-&FFFF by using linear scaling.

TwoDimensionalEqualization
~~~~~~~~~~~~~~~~~~~~~~~~~~
This expands the range of the contents of the main two dimensional buffer
until it covers the range &0000-&FFFF by using linear scaling.

One of the problems with this command (and the one above) emerges when
textures using it are animated.  Because the height of the highest mountain
and the floor of the deepest valley (so to speak) determine the scaling
factor to be used, this will be a different factor for different animation
frames.  An especially high mountain will produce a "freak" low gain value. 
This will have the effect of making the rest of the texture appear lower than
it would normally be.  Depending on the colouring scheme used, this can
result in an unsightly flashing effect in the resultant animation.  There is
no simple fix for this, but truncating high mountains, and using a fixed gain
contrast command are both possible.

GenerateOneDimensionalDust(Threshold,Function,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Processes the contents of the main one dimensional buffer by comparing it to
a bank of white noise and combining those values exceeded by some threshold
(<Threshold>) by the function (of X) "Function" using combination-type
"Type".

GenerateTwoDimensionalDust(Threshold,Function,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to above using the main two dimensional buffer.

TwoDimensionalInversion
~~~~~~~~~~~~~~~~~~~~~~~
Inverts (EORs with &FFFF) the main two dimensional buffer.

OneDimensionalInversion
~~~~~~~~~~~~~~~~~~~~~~~
Inverts (EORs with &FFFF) the main one dimensional buffer.

TwoDimensionalClear
~~~~~~~~~~~~~~~~~~~
Clears the main two dimensional buffer with zeros.

OneDimensionalClear
~~~~~~~~~~~~~~~~~~~
Clears the main one dimensional buffer with zeros.

DefineSolidBlock(Block_Description)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This command defines a solid block of texture in three dimensions.  Its
single parameter, "Block_Description" is a function of X,Y, and Z.  This
function usually refers to the various buffers using the
"TwoDimensionalPoint" commands.

Sculpture(Path_of_X,Path_of_Y,Path_of_Z)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This command sculpts a solid shape from the solid block of texture described
in the last "DefineSolidBlock" command.  The parameters, "Path_of_X",
"Path_of_Y", "Path_of_Z", define a mapping between X and Y and the three
dimensional space.  They are all functions of X and Y.  The resulting shape
is stored in the main two dimensional buffer.

Resize(XFactor,YFactor)
~~~~~~~~~~~~~~~~~~~~~~~
Resizes the texture by XFactor and YFactor.
Actually performs something similar to:
"TwoDimensionalShift(&8000,&8000,Overwrite)"
"TwoDimensionalProcess(0,0,XFactor,YFactor,TwoDimensionalPoint(
   Combine(Multiplication,&40000 DIV XFactor,LogicalShiftRight(X,&6)),
   Combine(Multiplication,&40000 DIV YFactor,LogicalShiftRight(Y,&6))),
   Overwrite)".
"TwoDimensionalShift(&8000,&8000,Overwrite)"

ResizeBumpMap(XFactor,YFactor)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This command is used in a similar context to the "Resize(XFactor,YFactor)"
command.  It is intended for use in resizing bump maps.  The front end
assumes that if the two dimensional map has been changed since the last
virtual sprite was made, then this command has been inserted at the
appropriate point.

If called with XFactor and YFactor both equal to &FFFF this command does
no processing.  Otherwise it performs the action of
"Resize(XFactor,YFactor)".

                     15 Linear segment commands
                     ==========================

LinearField(H1,H2)
~~~~~~~~~~~~~~~~~~
Creates a linear field over the entire domain of the main one dimensional
buffer.  It ranges from H1 ay X = 0 to H2 at X = &FFFF. *

LinearSegment(X1,X2,H1,H2,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creates a linear field over the domain (X = X1 to X = X2) in
the main one dimensional buffer.  It ranges from Y = H1 at X = X1 to Y = H2
at X = X2. *

LinearFieldSegment(H1,H2,X1,X2,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creates a linear field over the domain (X = &FFFF - X2 to X = &FFFF - X1) in
the main one dimensional buffer.  It ranges from Y = H2 at X = &FFFF - X2 to
Y = H1 at X = &FFFF - X1.  The behaviour of the command when X1 is greater
than X2 is always produces a repeatable result, but it is beyond the scope
of this document to describe its exact effect.  In particular, it should not
be assumed that when X1 is greater than X2 this command affects this domain.

This ridiculous specification of the syntax of this command is a legacy from
Texture Garden's developmental days.  It has been retained to enable old
textures to be generated correctly.  The command
"LinearSegment(X1,X2,H1,H2,Type)" should now be used preferentially. *

* Note that by virtue of its nature, the previous three commands may destroy
  the ability of textures using it to tessellate.

Rectangle(I,X1,Y1,X2,Y2,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Simply creates a rectangle in the main two dimensional buffer.  Of "height"
<I> and opposing corners at (X1,Y1) and (X2,Y2), the rectangle is combined
with the existing pattern using combination-type "Type".

                        16 Shifting commands
                        ====================

OneDimensionalShift(Delta_X,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The main one dimensional buffer is shifted by <Delta_X> and combined with its
original self using combination-type "Type".

TwoDimensionalShift(Delta_X,Delta_Y,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The main two dimensional buffer is shifted by (<Delta_X>,<Delta_Y>) and
combined with its original self using combination-type "Type".

                         17 Rotation commands
                         ====================

QuickRotate(Theta,Type)
~~~~~~~~~~~~~~~~~~
The main two dimensional buffer is rotated by <Theta> rounded to the nearest
multiple of 90 degrees and combined with its original self using
combination-type "Type".  Usually <Theta> is one of "Zero", "Ninety",
"OneHundredAndEighty" and "TwoHundredAndSeventy".

Rotate(Theta,Type)
~~~~~~~~~~~~~~~~~~
The main two dimensional buffer is rotated by <Theta> rounded to the nearest
multiple of 1/3 of a degree and combined with its original self using
combination-type "Type". *

SlowRotate(Theta,Type)
~~~~~~~~~~~~~~~~~~~~~~
Same as Rotate but with sub-pixel anti-aliasing. *

RotateAbout(Theta,X,Y,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to Rotate, but the rotation is about an arbitrary point.  This is not
equivalent to a Shift, Rotate and Shift because of the location of the
introduced discontinuities. * #

SlowRotateAbout(Theta,X,Y,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Same as RotateAbout but with sub-pixel anti-aliasing. *

* Note that by virtue of the nature of its action, this command may destroy
  the ability of the texture to tessellate unless <Theta> is one of "Zero",
  "Ninety", "OneHundredAndEighty" and "TwoHundredAndSeventy" (in which case
  "QuickRotate" should be used).  The discontinuities are introduced at what
  would normally turn into the edges of the sprite.  However, further
  processing may alter their location.  The command is also a bit quick and
  dirty in that no anti-aliasing techniques are used to smooth the rotation. 
  If multiple rotations are used then this might become a problem, though it
  may also produce some interesting effects as the number of iterations
  reaches 100.

# Note that there is no QuickRotateAbout as this can be accomplished with a
  QuickRotate and a TwoDimensionalShift.

                      18 Loops
                      ========
Repeat
~~~~~~
Sets up a "Repeat"-type loop.

Until(Condition)
~~~~~~~~~~~~~~~~
Loops to the matching "Repeat" until <Condition> is non-zero.

For(Number_of_times_to_loop)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets up a "For"-type loop to be executed <Number_of_times_to_loop> times.

Next
~~~~
Loops to the matching "For" for the specified number of times.

                  19 Buffer manipulation commands
                  ===============================

OneDimensionalStoreBufferOne
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stores the contents of the main one dimensional buffer in the first one
dimensional buffer, overwriting its contents.

OneDimensionalStoreBufferTwo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Stores the contents of the main one dimensional buffer in the second one
dimensional buffer, overwriting its contents.

OneDimensionalSwapBufferOne
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Swaps the contents of the main one dimensional buffer with the contents of
the first one dimensional buffer.

OneDimensionalSwapBufferTwo
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Swaps the contents of the main one dimensional buffer with the contents of
the second one dimensional buffer.

OneDimensionalMaskBufferOne(Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Combines the contents of the main one dimensional buffer with the contents of
the first one dimensional buffer using combination-type "Type".

TwoDimensionalStore
~~~~~~~~~~~~~~~~~~~
Stores the contents of the main two dimensional buffer in the first two
dimensional buffer, overwriting its contents. *

TwoDimensionalSwap
~~~~~~~~~~~~~~~~~~
Swaps the contents of the main two dimensional buffer with the contents of
the first two dimensional buffer. *

TwoDimensionalMask(Type)
~~~~~~~~~~~~~~~~~~~~~~~~
Combines the contents of the main two dimensional buffer with the contents of
the first two dimensional buffer using combination-type "Type". *

* Note that the memory used in manipulating the first two dimensional buffer
  is not allocated by default, and this will cause the process of texture
  generation to use more memory than normal.  This is only important in
  if textures are to be generated in low-memory environments.
  
                     20 Wavey and Distorting commands
                     ================================

VerticalDistortion(Type)
~~~~~~~~~~~~~~~~~~~~~~~~
Applies a series of vertical displacements to the contents of the main two
dimensional buffer according to the contents of the main one dimensional
buffer.  The maximum displacement is twice the dimensions of the main two
dimensional buffer.  Combination-type "Type" is used.

HorizontalDistortion(Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~
See "VerticalDistortion" which is similar.

HorizontalWaveWarp(Type)
~~~~~~~~~~~~~~~~~~~~~~~~
Applies a "shaped smear" of waves to the contents of the main two dimensional
buffer whose horizontal displacements vary according to the contents of the
main one dimensional buffer.  The exact form of the smear is controlled by
the first one dimensional buffer.  The maximum amplitude of the waves is
twice the dimensions of the main two dimensional buffer.  Combination-type
"Type" is used.

VerticalWaveWarp(Type)
~~~~~~~~~~~~~~~~~~~~~
See "HorizontalWaveWarp" which is similar.

HorizontalWaves(Type)
~~~~~~~~~~~~~~~~~~~~~
Applies a "smear" of waves to the contents of the main two dimensional
buffer.  The exact form of the smear is controlled by the main one
dimensional buffer.  The maximum amplitude of the waves is twice the
dimensions of the main two dimensional buffer.  Combination-type "Type" is
used.

VerticalWaves(Type)
~~~~~~~~~~~~~~~~~~~
See "HorizontalWaves" which is similar.

GenerateOneDimensionalDust(Threshold,Function,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Processes the contents of the main one dimensional buffer by comparing it to
a bank of white noise and combining those values exceeded by some threshold
(<Threshold>) by the function (of X) "Function" using combination-type
"Type".

GenerateTwoDimensionalDust(Threshold,Function,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similar to above using the main two dimensional buffer.

TwoDimensionalInversion
~~~~~~~~~~~~~~~~~~~~~~~
Inverts (EORs with &FFFF) the main two dimensional buffer.

OneDimensionalInversion
~~~~~~~~~~~~~~~~~~~~~~~
Inverts (EORs with &FFFF) the main one dimensional buffer.

                  21 Colour related commands
                  ==========================

StartColourDefinition
~~~~~~~~~~~~~~~~~~~~~
This should occur at the start of every palette definition.  It is a marker
used by the front end to manipulate texture texts.

EndColourDefinition
~~~~~~~~~~~~~~~~~~~
This should occur at the end of every palette definition.  It is a marker
used by the front end to manipulate texture texts.

SetColour(ColourModel,Component1,Component2,Component3)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Selects the current colour to the one specified by "Component1",
"Component2" and "Component3" as set out in the "CreateColours(ColourModel)"
command (see below).

CreateColours(ColourModel)
~~~~~~~~~~~~~~~~~~~~~~~~~~
This command sets up a field of 24 bit RGB values describing the palette
which will be used in any "MakeSprite", "AddToSprite" or "MakeVirtualSprite"
commands.  The "ColourModel" may be one of "RGB", "HSV" or "CIE".  This
command represents the preferred method of performing these actions.

The three one-dimensional buffers are used to supply the colour's components.

With the "RGB" ColourModel, buffer two contains the red component, buffer
one contains the green component, and the main buffer containing the blue
component.

With the "HSV" ColourModel, buffer two contains the red component, buffer
one contains the green component, and the main buffer containing the blue
component.

With the "HSV" ColourModel, buffer two contains the "hue" component, buffer
one contains the "saturation" component, and the main buffer contains the
"value" component.

With the "HSV" ColourModel, buffer two contains the "X" component, buffer one
contains the "Y" component, and the main buffer contains the "Z" component.

CreateColoursUsingRGBData
~~~~~~~~~~~~~~~~~~~~~~~~~
Performs "CreateColours(RGB)".  

CreateColoursUsingHSVData
~~~~~~~~~~~~~~~~~~~~~~~~~
Performs "CreateColours(HSV)".

CreateColoursUsingCIEData
~~~~~~~~~~~~~~~~~~~~~~~~~
Performs "CreateColours(CIE)".

             22 Mirroring, Flipping and Shearing commands
             ============================================
        
Caution should be exercised when using the leading-diagonal and
trailing-diagonal versions of the mirror and flip commands as they may
prevent the resulting texture from tessellating correctly.  The shear
commands may also appear to produce different effects at different
resolutions unless the absolute size of their parameter is kept quite small.

The following commands all combine the main two dimensional buffer with its
mirror image in the specified axis before combining it with its original self
using combination-type "Type".

HorizontalMirror(Type)
~~~~~~~~~~~~~~~~~~~~~~
VerticalMirror(Type)
~~~~~~~~~~~~~~~~~~~~
LeadingDiagonalMirror(Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
TrailingDiagonalMirror(Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following "Flip" commands are similar to the "Mirror" commands.  However,
the result is no longer guaranteed to be symmetrical.  They take fractionally
longer to perform.

HorizontalFlip(Type)
~~~~~~~~~~~~~~~~~~~~
VerticalFlip(Type)
~~~~~~~~~~~~~~~~~~
LeadingDiagonalFlip(Type)
~~~~~~~~~~~~~~~~~~~~~~~~~
TrailingDiagonalFlip(Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Shears combine a sheared image of the main two dimensional buffer with its
original self using combination-type "Type".  A shear of Size 1 produces a 45
degree shear; higher numbers may be thought of as representing  the effect of
repeated shears.

HorizontalShear(Size,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~
VerticalShear(Size,Type)
~~~~~~~~~~~~~~~~~~~~~~~~
                  23 Blobbing commands
                  ====================

Ripples(Intensity,Radius,X,Y,Type)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This produces a circular effect in the main two dimensional buffer.  The
effect is centred at (X,Y) and is of radius <Radius> and height <Intensity>. 
The effect is composed of concentric ripples modulated by the contents of the
main one dimensional buffer.

Radials(Intensity,Radius,X,Y,Type,TypeTwo)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This produces a near-circular effect in the main two dimensional buffer.  The
effect is centred at (X,Y) and is of radius <Radius> and height <Intensity>. 
The effect is composed of distorted ripples combined with radial lines
modulated by the contents of the one dimensional buffers.  The main one
dimensional buffer affects the distortion, the first buffer affects the
ripples and the second affects the radial lines and their distribution.
"Type" affects the way the radial lines are combined with the background and
"TypeTwo" affects the way the ripples are combined with the resultant.

                     24 Branching
                     ============

Define <DefinitionMarker>
~~~~~~~~~~~~~~~~~~~~~~~~~
Places a marker in the program and gives it a name.  This name may contain
any characters, but top-bit-set (> &7F), low values (< &20), ")", "|" and
"," should not be used for compatibility with future versions of the
program.

Goto <DefinitionMarker>
~~~~~~~~~~~~~~~~~~~~~~~
Jumps directly to the named marker.

Call <DefinitionMarker>
~~~~~~~~~~~~~~~~~~~~~~~
Calls a routine at the named marker, setting up a return address.
Calls and Jumps may not currently be used as functions or as parameters to
functions.  They may be used as commands in conditional statements.

Return
~~~~~~
Returns from the most recent call.

                   25 Light sources and bump maps
                   ==============================

DefineLightSource(LightModel,Theta,Phi)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets up a light source.  This comes from angle Theta in the horizontal plane
(&0 = East, &4000 = North, etc.) and elevation Phi (&0 = on the horizon,
&FFFF = at the zenith).

The colour is defined as the current colour (i.e. the one last defined with
a "SetColour" command).

If the lighting model requires it, the current dithering will be used to
define the specular constant.

The lighting model may currently be one of "Gourad", "Phong", "Specular" or
"SpecularPhong".

If you use more than one light source, it is easy to saturate the resulting
texture, which will appear to have uniform blobs of colour, usually white.

This may also happen when shining bright light souces from near the horizon.
Because many bump maps will have tall narrow peaks, shining a light from the
side will produce significantly more illumination than shining one from
near the zenith.

To stop this from happening, either reduce the intensity of the lights being
used, shine them more from overhead, or reduce the bumpiness of the map
being used.

Currently, only the first eight lightsources are recognised.

ShineLightOnVirtualSprite
~~~~~~~~~~~~~~~~~~~~~~~~~
This performs the computation using the main two dimensional buffer as the
data for the bumpmap, and the previously defined light sources to specify
the lighting.

The virtual sprite contains the data which is to be illuminated, and is used
to store the result.

NOTES:

  1. In order to cooperate with future front ends to this feature, the
     "DefineLightSource" commands, the "SetColour" commands and the
     "ShineLightOnVirtualSprite" command should all be grouped together in
     one section, with a "ResizeBumpMap" at the beginning if appropriate.

  2. The "ResizeBumpMap" should always be used if the bumpmap is altered
     since the last MakeVirtualSprite command.  It should be placed after
     the bumpmap has been created, and directly before any SetColour
     commands.  If this is not done, the texture may not resize properly.
