@DATABASE "Default"
@AUTHOR "Paul Manias"
@(c) "Copyright 1996-1997 DreamWorld Productions."
@$VER: 0.7 Beta (6 July 1997)
@NODE "Main" "Master.GPI"

Name:         MASTER.GPI AUTODOC
Version:      0.7 Beta.
Date:         6 July 1997
Author:       Paul Manias
Copyright:    DreamWorld Productions, 1996-1997.  All rights reserved.
Notes:        This  document is still being written and will contain errors
              in  a  number  of  places.   The information within cannot be
	      treated as official until this autodoc reaches version 1.0.

 @{b}GENERAL INFORMATION@{ub}
 @{"Data Objects  " LINK "Objects.guide/DataObjects"}
 @{"Data Checking " LINK "DataChecking"}
 @{"Emulation     " LINK "Emulation"}
 @{"Error Codes   " LINK "ErrorCodes"}
 @{"Lists         " LINK "Lists"}
 @{"Structures    " LINK "Structures"}
 @{"Tags          " LINK "Tags"}

 @{b}FUNCTIONS@{ub}
 @{"Blitter       " LINK "Blitter.guide/Functions"}
 @{"Debug         " LINK "Debug.guide/Functions"}
 @{"JoyPorts      " LINK "JoyPorts.guide/Functions"}
 @{"Kernal        " LINK "Kernal.guide/Functions"}
 @{"Master        " LINK "Master"}
 @{"Objects       " LINK "Objects.guide/Functions"}
 @{"Pictures      " LINK "Pictures.guide/Functions"}
 @{"Screens       " LINK "Screens.guide/Functions"}
 @{"Sound         " LINK "Sound.guide/Functions"}

 @{b}STRUCTURES@{ub}
 @{"Bitmap        " LINK "Blitter.guide/Bitmap"}
 @{"Bob/MBob      " LINK "Blitter.guide/BobMBob"}
 @{"File          " LINK "Files.guide/File"}
 @{"GameScreen    " LINK "Screens.guide/GameScreen"}
 @{"GMSTask       " LINK "Kernal.guide/GMSTask"}
 @{"GPI           " LINK "Kernal.guide/GPI"}
 @{"Picture       " LINK "Pictures.guide/Picture"}
 @{"Sound         " LINK "Sound.guide/Sound"}

@EndNode
---------------------------------------------------------------------------
@NODE "Master" "Master Functions"

 @{b}MASTER INTERFACE@{ub}
 @{"CopyStructure()" LINK "Copystructure()"}
 @{"FastRandom()"    LINK "FastRandom()"}
 @{"GetStructure()"  LINK "GetStructure()"}
 @{"InitTags()"      LINK "InitTags()"}
 @{"ReadKey()"       LINK "ReadKey()"}
 @{"SlowRandom()"    LINK "SlowRandom()"}
 @{"SmartUnpack()"   LINK "SmartUnpack()"}
 @{"WaitLMB()"       LINK "WaitLMB()"}
 @{"WaitTime()"      LINK "WaitTime()"}
 @{"WriteDec()"      LINK "WriteDec()"}
 @{"WriteHex()"      LINK "WriteHex()"}

@EndNode
---------------------------------------------------------------------------
@NODE  "GMSTask" "Structure: GMSTask"

Name:    GMSTask
Version: 1
ID Code: GT
Type:    Complex, Private

@{b}@{u}DESCRIPTION@{uu}@{ub}
This structure is off limits to normal programs, and is only for use by the
GPI  functions.   The most a normal GMS program will do with this structure
is  pass it around functions that ask for it.  If you want to get some data
from  a GMSTask structure, make sure you use the appropriate function to do
so.

@EndNode
---------------------------------------------------------------------------
@NODE "Structures" "Structure Layout"

                             @{b}STRUCTURE LAYOUT@{ub}


GMS  structures  have  been  designed  with just one commonality:  They all
start  with  a  ID and Version header, followed by a private "stats" field.
Following this are whatever fields are relevant for that structure type.

Example:

     STRUCTURE  GameScreen,0
	WORD	GS_ID
	WORD	GS_Version
	APTR	GS_Stats
	...

The  ID  consists  of  a  two  character  structure  ID.   An  example  for
GameScreens  is:   ID_GAMESCREEN  = "GS"

The  Version  field  can  be  used for jump tables to deal with the various
structure  types  and  handling  the future expansion of the structure.  It
starts at 0 and goes upwards.

The  Stats  field  follows  immediately  after  the  Version  field, and is
reserved  for  various  uses.   For  example if a structure is written to a
file,  then  the  stats  field could contain the chunk size, as in IFF.  To
prevent  confusion  the  Stats  field  must  always  be set to 0 when being
initialised for the first time.

Structure  Identification  can  be  used for more than tracking versions of
passed  structures.  One such is example is the LIST ID header, which tells
a  function  that  it  needs  to  perform  the same action to more than one
structure.  You can read more about this in @{"Lists" LINK "Lists"}.


                       @{b}STRUCTURE AUTO-INITIALISATION@{ub}


A  standard  GMS  policy  for initialisation functions is to initialise all
empty  fields  to  either  the  user  defaults, or values determined by any
related  fields.   For  example, omitting the ScrWidth and ScrHeight values
from  a  screen  would  cause the screen to open at the user's ScrWidth and
ScrHeight defaults.  On the other hand if you were to omit the PicWidth and
PicHeight settings, then these would inherit the values present in ScrWidth
and  ScrHeight.  Sometimes if there is a file present, the values will come
from that file's header structure.  For example, IFF pictures will fill out
a picture structure if it has empty fields.

The  only  fields  that  are  not  auto-initialised are the ones containing
flags, such as the attrib and option fields.


                           @{b}FUTURE COMPATIBILITY@{ub}


In GMS it is illegal to define a structure in your code and compile it into
the  final  binary.   The only way you can legally obtain a structure is to
call  its  related  Get*() function (eg GetPicture()) or to use a tag list,
which  will  return  an initialised structure to you.  This rule solves all
future compatibility concerns in relation to structure handling.

@EndNode
---------------------------------------------------------------------------
@Node "Lists" "GMS Lists"

                                   @{b}LISTS@{ub}


A  list  is intended for processing 2 or more structures inside a function.
This  is  the  fastest  way  that you can process a whole lot of structures
without  having  to  make  heaps of function calls.  Lets say you wanted to
load  in  10  sounds  from  your  hard-drive  using  InitSound().  Normally
InitSound()  takes  a  Sound  Structure, but it can also identify a list by
checking the header ID.

To  illustrate,  a  typical list for initialising/loading sounds looks like
this:

SoundList:
	dc.l	LIST                ;List identification header.
	dc.l	SND_Boom            ;Pointers to each sound to load and
	dc.l	SND_Crash           ; initialise.
	dc.l	SND_Bang
	dc.l	SND_Ping
	dc.l	SND_Zoom
	dc.l	SND_Zig
	dc.l	SND_Zag
	dc.l	SND_Wang
	dc.l	SND_Whump
	dc.l	SND_Bong
	dc.l	LISTEND             ;Indicate an end to the list.

When you want to load all your sounds in, just use this piece of code:

	move.l	GMSBase(pc),a6
	lea	SoundList(pc),a0    ;a0 = Pointer to the soundlist.
	CALL	InitSound
	tst.l	d0
	bne.s	.error

Or:	if (InitSound(&SoundList) == NULL)
	   return(ERR_FAILED);

Pretty  easy right?  Of course, there are lots of other functions that sup-
port lists.  For example:

	InitBob()
	InitSprite()
	InitSound()
	FreeSound()
	FreeBob()

Some   functions   are  specially  written  to  be  given  lists  only,  eg
DrawBobList().  This is mainly for speed reasons, as we don't want to waste
time checking if a structure is a list or not in time critical situations.

That's  basically the summary on lists.  You may be interested to know that
the  GMS  package  is  the only programmers aid that supports structures in
this  way.  You will learn more about lists and how ID fields will help you
in other areas of this doc.

@EndNode
---------------------------------------------------------------------------
@NODE "Tags" "Tags"

                                 @{b}GMS TAGS@{ub}


GMS  supports  tags in a way that is practically identical to the Amiga OS.
The  only major difference is that an internal change in design allows them
to operate a little faster.  Tags allow you to support all future structure
versions, and they are convenient for use in C.  Unfortunately they take up
more  memory  than a convential structure.  Because pre-compiled structures
are  generally  illegal in GMS, you have to use tags a lot.  Make sure that
you look at the demos so that you understand how to use them.

Here are just some of the functions that support tags:

	AddScreen()
	LoadPic()
	InitBob()

For  C  users  the  names  of  these  functions  have  a  "Tags" suffix, eg
AddScreenTags().   Assembler  programmers  can  use  the  already  existing
function  names.  Note that tags are treated the same way as lists, and can
only be identified by functions when they are passed a TAGS ID in the first
field.

On the lowest level, tags are represented like this:

	dc.l	TAGS_ID,<Structure>
	dc.l	<ti_Tag>,<ti_Data>
	dc.l	TAGEND

Example:

	dc.l	TAGS_GAMESCREEN,0
	dc.l	GSA_ScrWidth,320
	dc.l	GSA_ScrHeight,256
	dc.l	TAGEND

If  you omit the Structure and replace it with NULL as in this example, the
relevant  structure  will  be  allocated  for  you.   The  newly  allocated
structure   will  be  placed  in  the  NULL  entry  (useful  for  assembler
programmers),  and  will  also  be returned by the function.  If a tag call
results  in  a  return  of  NULL then an error has occured and the call has
failed.   To  find  out why the failure occured you would have to use a GMS
debugger like IceBreaker.

Here is an example of using tags in C:

      struct GameScreen *GameScreen;

      if (GameScreen = AddScreenTags(TAGS_GAMESCREEN,NULL,
           GSA_Planes,5,
           GSA_Palette,Palette,
           GSA_ScrMode,LORES,
           GSA_ScrWidth,320,
           GSA_ScrHeight,256,
           GSA_ScrType,ILBM,
           GSA_ScrAttrib,DBLBUFFER,
           TAGEND)) {

         /* Code Here */

      DeleteScreen(GameScreen);
      }

There  are  also  some  special  flags  that  you  can use for advanced Tag
handling.  These flags are identified in ti_Tag, and they are:

TAG_IGNORE - Skips to the next Tag entry.

TAG_MORE   - Terminates the current TagList and starts another one (pointed
	     to in the ti_Data field).

TAG_SKIP   - Skips this and the next ti_Data items.

That's  all you need to know, just remember to terminate all your tag calls
with TAGEND.

@EndNode
---------------------------------------------------------------------------
@NODE "ErrorCodes" "GMS Error Codes"

                                @{b}ERROR CODES@{ub}


GMS  has  a  universal set of error codes that are used by functions with a
return  type  of @{i}ErrorCode@{ui}.  This enables you to easily identify errors and
debug  these  problems  when they occur.  ErrorCodes are sent to IceBreaker
with  full  descriptions,  so  use  this program for easy identification of
errors.  Here is a description of current error codes and what they mean:

@{b}[0] ERR_OK@{ub}
No error occurred, function has executed successfully.

@{b}[1] ERR_NOMEM@{ub}
Not  enough memory was available when this function attempted to allocate a
memory block.

@{b}[2] ERR_NOPTR@{ub}
A required structure address pointer was not present.

@{b}[3] ERR_INUSE@{ub}
This structure has previous allocations that have not been freed.

@{b}[4] ERR_STRUCT@{ub}
You  have given this function a structure version that is not supported, or
you have passed it an unidentifiable memory address.

@{b}[5] ERR_FAILED@{ub}
An unspecified failure has occurred.

@{b}[6] ERR_FILE@{ub}
Unspecified file error, eg file not found, disk full etc.

@{b}[7] ERR_DATA@{ub}
This function encountered some data that has unrecoverable errors.

@{b}[8] ERR_SEARCH@{ub}
An  internal  search was performed and it failed.  This is a specific error
that  can  occur  when  the  function  is searching inside file headers for
something, eg the BODY section of an IFF file.

@{b}[9] ERR_SCRTYPE@{ub}
Screen Type not recognised or supported, eg currently True Colour modes are
not available.

@{b}[10] ERR_GPI@{ub}
This function tried to initialise a GPI and failed.

@{b}[11] ERR_RASTCOMMAND@{ub}
Invalid raster command detected.  Check your rasterlist for errors and make
sure it terminates with a RASTEND.

@{b}[12] ERR_RASTERLIST@{ub}
Complete  rasterlist  failure.  You have tried to do something which is not
possible under present conditions.

@{b}[13] ERR_NORASTER@{ub}
Rasterlist was missing from GameScreen->Rasterlist.

@{b}[14] ERR_DISKFULL@{ub}
Disk full error, time to get more space.

@{b}[15] ERR_FILEMISSING@{ub}
File not found.

@{b}[16] ERR_WRONGVER@{ub}
Wrong version or version not supported.

@{b}[17] ERR_MONITOR@{ub}
Monitor driver not found or not supported.

@{b}[18] ERR_UNPACK@{ub}
Problem with unpacking of data.

@{b}[19] ERR_ARGS@{ub}
You  tried to pass invalid arguments to this function, such as a NULL value
where you should have placed a pointer.

@EndNode
---------------------------------------------------------------------------
@NODE "DataChecking" "GMS Data Checking"
@{b}
                               DATA CHECKING

                                    AND

                           VALIDATION PROCEDURES
@{ub}

The  design of GMS in terms of ease of use has allowed for the inclusion of
simple  and  efficient  data  checking  mechanisms.  This results in a more
rigorous  and  protective  system for the programmer, allowing functions to
detect  if  they have been passed inappropriate data structures.  On top of
this,  functions include null handling, data checking, and validation.  Due
to  the  presence of IceBreaker you can quickly find out where your program
has  gone  wrong, as functions report errors directly to you in english and
not error codes or software failure numbers.

@{b}
                            GARBAGE PROTECTION
@{ub}

The  simplest  example  of  garbage  protection has already been mentioned,
which  is that of functions checking that they have been passed the correct
data  structures  before  they actually do anything with them.  This offers
the  programmer more security when developing, as passing the wrong data to
a  function  is not uncommon and can often result in disaster.  In the past
protection  from  such actions has been employed at the level of a language
compiler,  such  as  C's  type  checking feature.  However this has obvious
problems  as  there  is  never  any  assurance that what you are passing is
correct  -  there  is no way of knowing that the data has not been tampered
with, if the pointer is simply pointing to the wrong structure or if it was
not initialised correctly in the first place.

Therefore  the only sure-fire way of protecting a system and the programmer
from such accidents is at the function level, where the data is checked for
validity  before  hand  and not processed until it passes the various tests
employed.   This  does  not  mean  checking  each field for valid values, a
simple  ID  test is more than enough at this stage.  Surprisingly very few,
or  even  no  other  operating systems are capable of consistently offering
such a feature.

Other garbage protection features include software based memory protection.
This  is  significantly different to hardware based memory protection which
requires the addition of a memory management system with the CPU.  Although
memory protection on a software level will always be less stringent than at
hardware,  it  has an advantage of being able to deal with errors in a more
suitable  way,  rather than exceptions being generated that often result in
the  program  being shut down by the OS.  A good example of all this is the
InitTags() function.

InitTags() takes an empty structure and a list of data tags, then processes
the  data  tags  and  writes  out  the  values to the given structure.  The
procedure to do this is straight forward and takes no more than a few lines
of  assembler  to  implement.   However if the tag list has bad data values
there  is  nothing  to  stop  data  being written outside of the structures
memory  boundary.   To  stop  this  InitTags()  finds  out  the size of the
destination structure and compares it to the destination given in each tag.
If  a  problem  is  discovered  the  function  stops  operations, passes an
informative  message  on to IceBreaker, then returns to the program with an
error  code.   The program can then exit in its own way, and the programmer
can  immediately  find  out what went wrong without the bother of exception
codes or attempting to understand what the assembler registers might mean.

@{b}
                             DATA INTERFERENCE
@{ub}

There are two types of data interference:  accidental interference which is
the  result  of  a  programming error, and deliberate interference which is
caused  by  a  routine  finding  a  data  value that is already in error or
is  inappropriate,  so  it  is  resultantly  changed.   Many initialisation
functions  in  GMS  provide  the latter so that a program does not crash or
unexpectedly  exit  for  small  mistakes.   Also  it allows each field in a
structure  to  be  checked  for  inappropriate  values  and  report them to
IceBreaker, whereas previously they may have gone unnoticed.

As  an  example,  lets  say  a  programmer was loading a picture that was 4
planes  in  depth.  Although this was specified in the picture structure he
forgot  to  set the screen type to ILBM.  Because it was already set in his
preference  settings  for  GMSPrefs  it  works  anyway, so the problem goes
unnoticed.  Later, a user with a setting of CHUNKY8 tries the program.  Now
normally  this could crash the system or cause the program to never work at
all,  because  a  CHUNKY8 screen cannot have a plane setting of 4.  However
LoadPic()  will  pick  up  on this and immediately change the setting to 8.
The problem is now solved, and the program works fine.

This  kind  of  checking  and  comparisons  are  often used and it allows a
certain  amount of extra future-proofing to the generally functionality.  A
small  programming  flaw made now, which might not show up until future GMS
versions, can now be dealt with quickly and without incident.


@EndNode
-----------------------------------------------------------------------------
@NODE "CopyStructure()" "Master/CopyStructure"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      CopyStructure()
Short:     Copies details from one structure to another.
Assembler: CopyStructure(Structure [a0], Destination [a1])
C/C++:     void CopyStructure(APTR Source, APTR Destination);

@{b}@{u}DESCRIPTION@{uu}@{ub}
Copies  one  structure across to another.  The structures can be similar or
completely  different  (eg  as ludicrous as it sounds, even a GameScreen ->
Sound copy is possible).

This  function only copies fields that DESCRIBE the structures in question,
it  DOES  NOT  copy  fields  that contain option flags, fields that contain
pointers  to  the  main  area  of  data  (eg  screen  bitplanes), or fields
designated as private.

Only  NULL  fields  in  the  destination structure may be set by the source
structure.

@{b}@{u}INPUT@{uu}@{ub}
Source      - Points to any structure type that is officially recognised by
	      GMS (ie it must be referenced in the master document).
Destination - Same requirements as for the Source.


@{b}@{u}SEE ALSO@{uu}@{ub}
@{"GetStructure" LINK "GetStructure()"}

@EndNode
---------------------------------------------------------------------------
@NODE "FastRandom()" "Master/FastRandom"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:	   FastRandom()
Short:     Generate a random number between 0 and <Range>.
Assembler: Random = FastRandom(Range [d1])
C/C++:     UWORD FastRandom(UWORD Range);

@{b}@{u}DESCRIPTION@{uu}@{ub}
Creates  a  random  number  as  quickly  as possible.  The routine uses one
divide to determine the range and will automatically change the random seed
value  each  time  you call it.  This routine has now been fully tested and
generates 100% patternless numbers.

Remember  that  all  generated numbers fall BELOW the Range.  Add 1 to your
range if you want this number included.

@{b}@{u}INPUTS@{uu}@{ub}
Range - A range between 1 and 32767.  An invalid range of 0 will result in
        a division by zero error.

@{b}@{u}RESULT@{uu}@{ub}
Random - A number greater or equal to 0, and @{i}less than@{ui} Range.

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"SlowRandom" LINK "SlowRandom()"}, @{"demos/randomplot" SYSTEM "GMS:demos/RandomPlot"}

@EndNode
-----------------------------------------------------------------------------
@NODE "GetStructure()" "Master/GetStructure"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      GetStructure()
Short:     Gets the latest version of a specified structure.
Assembler: Structure = GetStructure(ID [d0])
C/C++:     APTR GetStructure(ULONG ID);

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function will get the latest version of any structure in GMS, so long
as  it  has  an  ID  and  a related Get*() function (GameScreens, Pictures,
Sounds and others fit this requirement).

You can also pass it TAGS_* identifiers, eg TAGS_GAMESCREEN, as they can be
uniquely identified.

@{b}@{u}INPUT@{uu}@{ub}
ID - One of the ID's as specified in the games/games.i file

@{b}@{u}RESULT@{uu}@{ub}
Structure  -  The  latest  version  of  the  specified structure or NULL if
failure (caused by lack of memory or unrecognised ID).

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"InitTags" LINK "InitTags()"}

@EndNode
-----------------------------------------------------------------------------
@NODE "InitTags()" "Master/InitTags"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      InitTags()
Short:     Initialise a structure according to a tag list.
Assembler: ErrorCode = InitTags(Structure [a0], TagList [a1])
C/C++:     ULONG InitTags(APTR Structure, APTR TagList);

@{b}@{u}DESCRIPTION@{uu}@{ub}
This  function  is  intended  for  GPI's but may be used by GMS programs if
required.

It will process a standard tag list and store specified values in the given
structure,  which should be empty although this is not a pre-requisite.  It
is important that the tags themselves have been correctly defined using the
TBYTE, TWORD and TLONG flags.  Check the games/games.i file for examples.

This  function  has  some software based memory protection and will prevent
values from being written outside of the structure's memory area.  Detected
errors will be sent to the GMS debugger.

@{b}@{u}INPUTS@{uu}@{ub}
Structure - Pointer to allocated structure memory.
TagList   - Pointer to a standard GMS tag list (see tags).

@{b}@{u}RESULT@{uu}@{ub}
ErrorCode - ERR_OK if successful.

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"GetStructure" LINK "GetStructure()"}

@EndNode
---------------------------------------------------------------------------
@NODE "ReadKey()" "Master/ReadKey"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      ReadKey()
Short:     Reads the keyboard and returns any new keypresses.
Assembler: KeyValue = ReadKey(Keys [a1])
C/C++:     UBYTE ReadKey(struct Keys *);

@{b}@{u}DESCRIPTION@{uu}@{ub}
Checks  to  see if there was a keypress since the last time you called this
routine.   If  there  were  no  keypresses then KeyValue will return a NULL
value.

Most key values are returned as ANSI, which is of the range 1-127.  Special
keys  (eg Cursor Keys, function Keys etc) are held in the range of 128-255.
You can see what these special keys are in games.i.

Qualifiers have automatic effects on the ANSI value (eg shift+c will return
"C").   Alt  keys,  Ctrl  keys,  and  Amiga keys have no effect on the ANSI
value.

The  KeyStruct is also updated for future reference.  A KeyStruct will hold
up  to  four  keys since your previous check.  If you are calling ReadKey()
every  vertical  blank,  you  are  already  supporting  typing speeds of an
astronomical  600  words  per  minute,  so  it  is  only necessary to check
KP_Key1.   If  you are only grabbing keys every 1/2 second, then all fields
should be checked.

@{b}@{u}NOTE@{uu}@{ub}
The  GMS  input handler needs to be active for this function to work.  This
is  done by calling ShowScreen() or AddInputHandler() in the initialisation
section of your program.

@{b}@{u}INPUT@{uu}@{ub}
Keys - Pointer to a valid Keys structure.

@{b}@{u}RESULT@{uu}@{ub}
KeyValue - Contains  the  latest keypress value, ie is identical to KP_Key1.
Keys     - Updated  to  hold new key data.  You may receive as much
	   as 4 keys in the provided fields.  Key fields containing
	   zero indicate that no key was pressed.

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"AddInputHandler" LINK "AddInputHandler()"}, @{"games/misc.i" LINK "INCLUDES:games/misc.i"}

@EndNode
---------------------------------------------------------------------------
@NODE "SlowRandom()" "Master/SlowRandom"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      SlowRandom()
Short:     Generate a random number between 0 and <Range>.
Assembler: Random = SlowRandom(Range [d1])
C/C++:     ULONG SlowRandom(UWORD Range);

@{b}@{u}DESCRIPTION@{uu}@{ub}
Generates  a  very good random number in a relatively short amount of time.
This routine takes approximately two times longer than FastRandom(), but is
guaranteed of giving excellent random number sequences.

Remember  that  all  generated numbers fall BELOW the Range.  Add 1 to your
range if you want this number included.

@{b}@{u}INPUTS@{uu}@{ub}
Range - A range between 1 and 32767.

@{b}@{u}RESULT@{uu}@{ub}
Random - A number greater or equal to 0, and @{i}less than@{ui} Range.

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"FastRandom" LINK "FastRandom()"}, @{"demos/randomplot" SYSTEM "GMS:demos/RandomPlot"}

@EndNode
---------------------------------------------------------------------------
@NODE "SmartUnpack()" "Master/SmartUnpack"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      SmartUnpack()
Short:     Unpack data from one memory location to another.
Assembler: MemLocation = SmartUnpack(Source [a0], Destination [a1],
            Password [d0], MemType [d1])
C/C++:     APTR SmartUnpack(APTR Source, APTR Destination, ULONG Password,
            ULONG MemType)

@{b}@{u}DESCRIPTION@{uu}@{ub}
Attempts  to  unpack  a data area if it can assess the packing method used.
The  data  should  begin  with  an  ID longword followed by the size of the
original  data  before it was packed.  The data itself must follow directly
after this.  Any packer that does not do this will not be supported by this
function.

If  you  pass  NULL as the destination address, SmartUnpack() will allocate
the  memory  for  you,  but you must give a recognised memory type.  If you
give the Destination, the MemType is ignored.

This  function  currently  supports  XPK  (external) and the RNC (internal)
packer  types.   The  RNC packer can unpack directly over itself (ie Source
and Destination can be the same).  Do not try this with the XPK packer - it
won't work!

@{b}@{u}NOTE@{uu}@{ub}
Remember  to free any memory returned in MemLocation with FreeMemBlock() if
you wanted the allocation.

@{b}@{u}INPUTS@{uu}@{ub}
Source      - Pointer  to  start  of  packed  data  (must  be an ID header).
Destination - Destination for unpacked data or NULL for allocation.
Password    - FileKey or NULL if none is used.
MemType     - Memory type (only supply if Destination is NULL).

@{b}@{u}RESULT@{uu}@{ub}
MemLocation - Pointer to the unpacked data.

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"SmartLoad" LINK "SmartLoad()"}

@EndNode
---------------------------------------------------------------------------
@NODE "WaitLMB()" "Master/WaitLMB"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      WaitLMB()
Short:     Wait for the user to hit the left mouse button.
Assembler: WaitLMB()
C/C++:     void WaitLMB(void);

@{b}@{u}DESCRIPTION@{uu}@{ub}
Waits  for  the  user  to hit the left mouse button.  It will not return to
your program until this event occurs.  Multi-tasking time will be increased
while waiting and an implanted AutoSwitch() call supports screen switching.

@{b}@{u}SEE ALSO@{uu}@{ub}
@{"ReadMouse" LINK "ReadMouse()"}

@EndNode
---------------------------------------------------------------------------
@NODE "WaitTime()" "Master/WaitTime"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:      WaitTime()
Short:     Wait for a specified amount of micro-seconds.
Assembler: WaitTime(MicroSeconds [d0])
C/C++:     void WaitTime(UWORD MicroSeconds)

@{b}@{u}DESCRIPTION@{uu}@{ub}
Waits  for  a  specified amount of micro-seconds.  During this time it will
reduce the task priority and make regular calls to AutoSwitch() for you.

@{b}@{u}INPUT@{uu}@{ub}
MicroSeconds - Amount of micro-seconds to wait for.

@EndNode
---------------------------------------------------------------------------
@NODE "WriteDec()" "Master/WriteDec"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:	   WriteDec()
Short:     Outputs a Number as decimal formatted text.
Assembler: Address = WriteDec(Number [d0], AmtDigits [d1], Destination [a0])
C/C++:     APTR WriteDec(LONG Number, ULONG AmtDigits, char *Destination)

@{b}@{u}DESCRIPTION@{uu}@{ub}
Takes  a  Number  and  outputs it to Destination as decimal formatted text.
AmtDigits  defines the maximum amount of digits that you want to be written
out.  If the number does not completely fill the given amount of digits, it
will  be  trailed with leading zero's.  If the AmtDigits parameter is NULL,
the  number  will  be  output  with  left  alignment,  (no leading zero's).
Negative numbers get a '-' character put in front.

@{b}@{u}INPUTS@{uu}@{ub}
Number	    - A number to convert to text.
AmtDigits   - The amount of digits to write out, or NULL if you
	      want left alignment with no trailing 0's.
Destination - Memory location of where you want the numeric text to
	      be written out.

@{b}@{u}RESULT@{uu}@{ub}
Address - The address where this function stopped writing out any
	  characters.

@EndNode
-----------------------------------------------------------------------------
@NODE "()" "Master/"

@{b}@{u}FUNCTION@{uu}@{ub}
Name:
Short:
Assembler:
C/C++:

@{b}@{u}DESCRIPTION@{uu}@{ub}

@{b}@{u}INPUT@{uu}@{ub}

@{b}@{u}RESULT@{uu}@{ub}

@{b}@{u}SEE ALSO@{uu}@{ub}

@EndNode
