<HTML>
<H1>SWI Documentation for the Amnesia module version 1.00</H1>

<H1>Amnesia SWIs</H1>

  <a href="#init">Amnesia_Init</a>
  <a href="#claimblock">Amnesia_ClaimBlock</a>
  <a href="#releaseblock">Amnesia_ReleaseBlock</a>
  <a href="#extendblock">Amnesia_ExtendBlock</a>
  <a href="#describeblock">Amnesia_DescribeBlock</a>
  <a href="#claimtable">Amnesia_ClaimTable</a>
  <a href="#releasetable">Amnesia_ReleaseTable</a>
  <a href="#wipetable">Amnesia_WipeTable</a>
  <a href="#tidy">Amnesia_Tidy</a>
  <a href="#makeobject">Amnesia_MakeObject</a>
  <a href="#makeobjectspace">Amnesia_MakeObjectSpace</a>
  <a href="#selecttable">Amnesia_SelectTable</a>
  <a href="#processtable">Amnesia_ProcessTable</a>
  <a href="#deleteobject">Amnesia_DeleteObject</a>
  <a href="#countobjects">Amnesia_CountObjects</a>
  <a href="#setwindow">Amnesia_SetWindow</a>
  <a href="#readwindow">Amnesia_ReadWindow</a>
  <a href="#setplotoffset">Amnesia_SetPlotOffset</a>
  <a href="#readplotoffset">Amnesia_ReadPlotOffset</a>
  <a href="#setgravity">Amnesia_SetGravity</a>
  <a href="#readgravity">Amnesia_ReadGravity</a>
  <a href="#collisioncheck">Amnesia_CollisionCheck</a>
  <a href="#loadfile">Amnesia_LoadFile</a>
  <a href="#loadhammered">Amnesia_LoadHammered</a>
  <a href="#savefile">Amnesia_SaveFile</a>
  <a href="#loadtable">Amnesia_LoadTable</a>
  <a href="#savetable">Amnesia_SaveTable</a>
  <a href="#gettableaddr">Amnesia_GetTableAddr</a>
  <a href="#blocks">Amnesia_Blocks</a>
  <a href="#remote">Amnesia_Remote</a>

Amnesia is a module which provides support for memory allocation and an
'object handler' primarily for use in video games.  The Amnesia module has
many facilities and you are unlikely to need all of them.  This document
contains full information regarding the SWIs so may look a bit daunting. 
Dont worry - its not half as complicated as it looks!


<a name="init">Amnesia_Init</a>
------------

Initialises the Amnesia module

On Entry

R0 = Area start
R1 = Area length
R2 = Area type

On Exit

R0 preserved
R1 preserved
R2 preserved

Interrupt status not altered.  Executes in SVC mode.
SWI is not re-entrant. 

Use

This SWI must be issued before using any other Amnesia facilities.  R0 should
be word aligned (multiple of 4).  The register meanings are as follows:

R0 = 0 : Claim from RMA.

R2 = 0 : Tidy mode - compact heap on each release of memory
R2 = 1 : Messy mode - compact heap when out of space
R2 = 2 : Static mode - compact heap only when instructed to do so

In tidy mode the module will shift the heap and gather all of the free space
together when blocks or tables are deallocated, so the heap is always tidy
and not fragmented.  In messy mode the heap will be shifted if there is not
enough space for a requested allocation.  Therefore the heap is usually in a
mess and fragmented.  This mode tends to give you occasional big tidy-ups
instead of regular small ones.  In static mode the heap is not shifted until
you specifically request it.  This is so that BASIC programs have a chance to
re-read all of the pointers that they use.

To release the Amnesia block, call this SWI with R1=0.

The module can only support one heap at a time, although this heap can be
split up into blocks as you please.

The SWI may return errors as the memory block is checked for validity.  All
of the following SWIs will return errors if called before a successful
Amnesia_Init.

=======================================

<a name="claimblock">Amnesia_ClaimBlock</a>
------------------

Claim a block of memory from the Amnesia heap.

On Entry

R0 = Address of pointer which will be used to reference the block.
R1 = Length required in bytes
R2 = Zero, or pointer to name string
R3 = Flags

On Exit

Pointer at R0 set to point to block, or [R0] = zero if allocation failed.
R1 = length allocated

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI must not be called from an interrupt routine.

Use

This SWI attempts to Claim a block of memory within the Amnesia heap if
available.  It may shift the heap in messy mode.  R1 is rounded up to be a
multiple of 4.  If the call is successful the block is then yours to do what
you like with.  Always use the pointer at [R0] to access the block, as it may
change when the heap is tidied.  You may supply R0 = 0, but Amnesia will no
longer be able to tidy the heap below the block.

The name pointed to by R2 may be up to 8 characters long and is for your use
only.  Amnesia will take a copy.

The flags in R3 are as follows:

Bit 0 : If this bit is set, the block is static - it will not be moved by
heap tidying.  Avoid static blocks if possible as they may cause Amnesia to
waste memory.  Ideally all of your static blocks should be claimed before
your moveable ones.

Bit 1 : If set, the block claimed will be quad-word aligned +4 like blocks
returned by OS_Module.  The address will end in 4 (so look like
&amp;xxxxxxx4).

Bit 2 : If this bit is set, the block is assumed to be accessed by an
interrupt routine (because its a sound sample, for example).  If so,
interrupts are disabled when the block is moved during a heap tidy to prevent
problems. 

Errors will be returned if there is no room.

=======================================

<a name="releaseblock">Amnesia_ReleaseBlock</a>
--------------------

Release a previously claimed block of memory.

On Entry

R0 = Address of pointer (as above) or zero

On Exit


The call zeroes pointer at [R0] if release is valid ie [R0] is a pointer to
an Amnesia block.

Interrupt status unchanged.
Executes in SVC mode.  SWI must not be called from an interrupt routine. 

Use

This SWI will release a block which has been previously claimed with
Amnesia_ClaimBlock.  If R0=0 then the whole Amnesia area is released.  In
tidy mode the heap will be shifted to release the free space for future
allocations.  The error Not a valid block may be returned.

=======================================

<a name="extendblock">Amnesia_ExtendBlock</a>
-------------------

Extends a block which has already been claimed

On Entry

R0 = Address of current pointer to block
R1 = New length required in bytes

On Exit

Pointer at [R0] may be changed if block is moved
R1 = new length allocated

Interrupt status unchanged.
Executes in SVC mode.  SWI must not be called from an interrupt routine. 

Use

This SWI tries to extend or shrink a previously claimed block.  The heap may
be shifted in tidy or messy modes.  May return the errors No room or Not an
allocated block.  The usual method is to claim another block, copy, and then
release the block to be extended.

=======================================

<a name="describeblock">Amnesia_DescribeBlock</a>
---------------------

Returns information about a block.
On Entry

R0 = pointer to block or block number

On Exit

R0 = block address
R1 = block size
R2 = start of data area
R3 = size of data area
R4 = pointer to name
R5 = pointer to block pointer (as passed in R0 to ClaimBlock)
R6 = block flags

Interrupt status unchanged.
Executes in SVC mode.  SWI is re-entrant. 

Use

This SWI returns information on a specified block.

=======================================

<a name="claimtable">Amnesia_ClaimTable</a>
------------------

Claims space for a table of objects and creates a header for that table

On Entry

R0 = Your handle for the table (0-31)
R1 = Flags
R2 = Zero or pointer to name
R3 = Number of objects
R4 = Size of a single object (bytes)

On Exit

R0-R3 Preserved

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI must not be called from an interrupt routine. 

Use

This SWI sets up a table for subsequent use.  A table is a list of objects
which usually represent sprites on the screen (aliens, missiles etc) but can
be used for other purposes.  All objects in the new table are marked as
inactive.  Returns an error if the allocation fails.

R1 contains information as follows:

bit | meaning if set 

0   - objects require collision checking facilities.

The processing of tables is detailed with the SWI Amnesia_ProcessTable.  If
the collision checking bit is set a collison checking table of a default
length will be claimed.  This will be extended during run-time if necessary.

The possible errors are No room, not initialised, bad table type, bad handle.

=======================================

<a name="releasetable">Amnesia_ReleaseTable</a>
--------------------

Releases a previously claimed table

On Entry

R0 = Your handle for the table (0-31)

On Exit

R0 preserved

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI must not be called from an interrupt routine. 

Use

Releases the space used by a table and its collision checking area if
present.  May return errors if the table is corrupted.

=======================================

Amnesia_ExtendTable
-------------------

*** This SWI is not implemented ***

=======================================

<a name="wipetable">Amnesia_WipeTable</a>
-----------------

On Entry

R0 = Your handle for the table (0-31)

On Exit

R0 corrupted, others preserved.

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI must not be called from an interrupt routine. 

Use

This SWI marks all objects in the specified table as inactive.

=======================================

<a name="tidy">Amnesia_Tidy</a>
------------

Tidies the heap and makes all of the free space available.

On Entry

No parameters

On exit

No results

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI must not be called from an interrupt routine. 

Use

This SWI will tidy the Amnesia heap and collect all of the free space
together.  In messy or tidy modes this will be performed automatically and
this SWI need not be used.  In static mode you can call this SWI in response
to the error No room in amnesia heap, and then update your pointers before
resuming.  This SWI may return errors such as overwritten/nonsensical blocks
in area.

=======================================

<a name="makeobject">Amnesia_MakeObject</a>
------------------

Creates an object in a table.

On Entry

R0 = Table handle
R1 = Object type/sprite (non-zero)
R2 = Object flags
R3 = x coord
R4 = y coord
R5 = x velocity
R6 = y velocity
R7 = Timer value
R8 = Object size

On Exit

R1 = address of object allocated, for you to fill in the rest if you need to.
R1 = Zero, and carry set if no object could be created.

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI is not re-entrant. 

Use

This SWI creates an object (an entry in the table) with the given parameters
if there is room.  No error will be returned if the object cannot be created
because there is no room in the table, but R1 will be zero on exit.  The SWI
tries to create an object as quickly as possible, but will scan the whole
table for a free space if necessary.  When a space is found the module stores
all passed registers using the form STMIA R10,{R1-R8} where R10 = the address
of the new object, returned to you in R1.

The coordinates in R3,R4 are FastSpr style, shifted left twelve places.  The
top left of the screen in (0,0) and the bottom right in, say, mode 13, is
(320&lt;&lt;12, 256&lt;&lt;12).  The values in R5,R6 are added directly to
these.

The <a href="flags">object flags</a> are stored in R2

              
The timer in R7 has the following structure:

&lt;byte 3>&lt;byte 2> | &lt;byte 1 &lt;byte 0>
  timer value       timer decrement

Upon each process pass (each time Amnesia_Process is used on the object) the
action SUB R7,R7,R7,LSL #16 is performed.  When this causes the timer to
cross zero the timer is said to have expired and the action specified by the
flags in R1 is taken.

The size should be specified in PIXELS in R8, in the following format:

&lt;byte 3>&lt;byte 2> | &lt;byte 1>&lt;byte 0>
     x size             y size

If the 'make up the object size' bit is set the module attempts to read the
object size from the FastSpr file.  If that fails the size is set to zero. 
Object size is used for collison checking only.  Note that R8 cannot be
passed from the BASIC SYS command and should be filled in using the returned
address in R1 if necessary.

If the FastSpr animation bit is set, the word after the object timer is used
to control the FastSpr animation.  Bits 31-24 are passed as the animation
frame.

This SWI may return the error Table does not exist.

=======================================

<a name="makeobjectspace">Amnesia_MakeObjectSpace</a>
-----------------------

Finds a space for you to make an object yourself

On Entry

R0 = Table handle

On Exit

R0 preserved
R1 = Address of available object, or zero if unable to allocate.

Interrupts disabled in critical stages otherwise unaltered.
Executes in SVC mode.  SWI is not re-entrant. 

Use

This SWI finds a free object space in the given table if possible.  You must
then fill in all of the parameters yourself if you wish to create an object. 
The object data is undefined on return so must be overwritten.  May return a
table does not exist error.

=======================================

<a name="selecttable">Amnesia_SelectTable</a>
-------------------

Selects a table for subsequent processing.

On Entry

R0 = Table handle [+ user attn bits]
R1 = Process type (0 -> normal, 1 -> scan (CMP), 2 -> scan (TST))

If R1=0
  R2 = Plot action (0 -> plot, 1 -> don't)

If R1=1 or 2
  R2 = offset in object
  R3 = CMP or TST value
  R4 = BIC value

On Exit

R0-R2 altered, ready to pass to Amnesia_ProcessTable
R0 = table number + internal flags + user attn flags
R1 = pointer to first object
R2 = internal flags
R3,R4 preserved


Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant. 

Use

This SWI selects the table to be processed next.  Subsequent calls to
Amnesia_ProcessTable will update objects, plot them if necessary, and may ask
the user to process objects.  If a normal process is selected this SWI will
also wipe the collision checking table if present.  If you wish to return
objects with user attention bits (bits 24-31) in their flags, set the
relevant bit or bits in R0.

If R1 = 0 the table is processed fully.

If R1 = 1 the table is scanned using a CMP instruction.  The value at offset
R2 in each object is BICed with R4 and compared with the value of R3, and the
object returned if identical.

If R1 = 2 the table is scanned using a TST instruction.  The value at offset
R2 in each object is BICed with R4 and TSTed with the value of R3, and the
object returned if any bit set in R3 is also set in the value at the selected
offset.  If R3 = 0 all objects are returned.


=======================================

<a name="processtable">Amnesia_ProcessTable</a>
--------------------

Processes one or more objects from a table.

On Entry

At the start of a process these registers should be those generated by
Amnesia_SelectTable.

R0 = Table Handle plus flag bits
R1 = Value from Amnesia_SelectTable or the previous Amnesia_ProcessTable
R2 = Reason code/flags
R3 = Scan value, if a scan is selected

On Exit

R0 = Table handle plus flag bits
R1 = Updated pointer to current object which needs attention, or zero if end
of table
R2 = Reason code/flags
R3 = Preserved


Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Amnesia_ProcessTable should be called repeatedly after a single
Amnesia_SelectTable to process the table.  The SWI will process the object as
necessary, and it will return control to you if the object needs attention.

If R2 = 0 the end of the table has been reached and processing has finished. 
You should not call this SWI again before selecting another table.

The module keeps no internal records of which table you are processing, so
you may process objects/tables in any order.  The three or four parameters
passed to Amnesia_ProcessTable fully define what is going on.

This SWI may return errors.  R0 will point to an error block as usual.

=======================================

<a name="deleteobject">Amnesia_DeleteObject</a>
--------------------

Deletes an object in a table

On Entry

R1 = Object address

On Exit

All registers preserved

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Simply STRs zero at address R1.  Use to make your code look tidier if you
like.

=======================================

<a name="countobjects">Amnesia_CountObjects</a>
--------------------

Counts the number of objects in a table

On Entry

R0 = table number

On Exit

R0 = number of objects

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Returns the number of objects in the specified table.

=======================================

<a name="setwindow">Amnesia_SetWindow</a>
-----------------

Sets an Amnesia window.

On Entry

R0 = window to set
R1 = minimum x coordinate
R2 = minimum y coordinate
R3 = maximum x coordinate
R4 = maximum y coordinate

On Exit

R0-R4 preserved

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

This SWI sets one of the windows held by Amnesia.  The window set is governed
by R0.


R0 = 0 : Set the game window.  This window is provided purely for the user,
and will return for attention if an object is outside of this window.  It
could be used, for example, to bounce a ball on the edge of the screen.  The
plot offset is not added before this comparison.

R0 = 1 : Set the plot window.  If any part of an object is within this window
the module will attempt to plot it.  The plot offset is added before the
comparison.

R0 = 2 : Sets the kill window.  If a object wanders completely outside of
this window it will be deleted if the relavent flag is set.  The plot offset
is not added before comparison.

=======================================

<a name="readwindow">Amnesia_ReadWindow</a>
------------------

Sets the game window.

On Entry

R0 = window to read

On Exit

R0 altered
R1 = minimum x coordinate
R2 = minimum y coordinate
R3 = maximum x coordinate
R4 = maximum y coordinate

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Reads the settings of a window.

=======================================

<a name="setplotoffset">Amnesia_SetPlotOffset</a>
---------------------

Sets the plot offset.

On Entry

R0 = x offset
R1 = y offset

On Exit

R0, R1 = Previous values

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

The plot offset is added to an objects coordinates before passing them to
FastSpr, if the relavent bit is set.  The coordinates are in pixels&lt;&lt;12.

=======================================

<a name="readplotoffset">Amnesia_ReadPlotOffset</a>
----------------------

Reads the plot offset.

On Entry

No parameters

On exit

R0 = x offset
R1 = y offset

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Returns the plot offset, for use by your own plotting code, for example.

=======================================

<a name="setgravity">Amnesia_SetGravity</a>
------------------

Sets the plot offset.

On Entry

R0 = x gravity
R1 = y gravity

On Exit

R1 preserved

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Gravity is added to an objects velocity on each process pass if bit 3 is set
in the flags.  Any value, positive or negative, is permitted for R0 and R1.

=======================================

<a name="readgravity">Amnesia_ReadGravity</a>
-------------------

Reads the gravity setting

On Entry

No parameters

On exit

R0 = x gravity
R1 = y gravity

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Use

Returns the gravity setting.

=======================================


<a name="collisioncheck">Amnesia_CollisionCheck</a>
----------------------

Performs collision checking between two tables

On Entry

R0 = First table number (0-31)
R1 = Second table number (0-31)

On Exit

R0 = Address of colliding object in the first table, or 0 if no collision.
R1 = Address of colliding object in second table.
R2 = offset of object in first table.  Don't bother with these.
R3 = offset of object in second table

Interrupt status unaltered.
Executes in SVC mode.  SWI is re-entrant.

Additional info - file <a href="colcheck">ColCheck</a>.

Use

This SWI performs a fast collision check between two tables, or between a
table and itself.  The addresses of the objects are returned.  Collision
checking can then be continued by calling the SWI again, until R0 returns
zero.  An example coding is:


.collisioncheck
STMFD R13!,{R14}
MOV R0,#1
MOV R1,#2
.loop
SWI "Amnesia_CollisionCheck"
CMP R0,#0
BEQ done
STMFD R13!,{R0-R1}
MOV R4,#0
STR R4,[R0]; delete both colliding objects
STR R4,[R1];
LDMFD R13!,{R0-R1}
B loop
.done
LDMFD R13!,{PC}

For collision checking to work, the following must be true:

 Both tables must have been claimed with collision checking enabled
 The objects in question must have the collision checking bit set in their
flags

Collision checking between a table and itself is a special case.  Amnesia
deals with the anomalies for you, to ensure that are not told about an object
colliding with itself.  Half the number of checks are required.

The algorithm used is moderately fast.  Tables of bounding boxes are built up
as objects are processed.  Subsequently each check between two objects takes
six instructions to complete.  If two tables of 50 objects are checked
against each other this takes 2500 checks (5050) so thats 15000
instructions.  Obviously the amount collision checking should be minimised to
reduce the processor time required.  With this in mind, if any object does
not need a collision check, then do not set the collision check bit in the
objects flags.

This SWI will return errors if the tables do not exist, or were not claimed
with collision checking specified.

=======================================

<a name="loadfile">Amnesia_LoadFile</a>
----------------

Creates an Amnesia block and loads a file into it

On Entry

R0 = address of block pointer
R1 = filename
R2 = pathname

On Exit

[R0] = address of allocated block
R1-R2 unchanged, R0 corrupted

Interrupt status unaltered.
Executes in SVC mode.  SWI should not be called from an interrupt routine.

Use

This SWI loads a file into the Amnesia area, creating a block to do so.  R0
is the address of the pointer which you wish to use for the block.  The block
will be quad word aligned plus 4 bytes, like an OS_Module block.  The string
pointed to by R1 is added after that pointed to by R2 to produce the complete
filename.

==================================

<a name="loadhammered">Amnesia_LoadHammered</a>
--------------------

Creates an Amnesia block and loads a file into it

On Entry

R0 = address of block pointer
R1 = filename
R2 = pathname

On Exit

[R0] = address of allocated block
R1-R2 unchanged, R0 corrupted

Interrupt status unaltered.
Executes in SVC mode.  SWI should not be called from an interrupt routine.

Use

Identical to Amnesia_LoadFile but decompresses the file if it is a Hammered
file.

==================================

<a name="savefile">Amnesia_SaveFile</a>
----------------

Saves an Amnesia block

On Entry

R0 = address of block
R1 = filename
R2 = filetype

On Exit

R1-R2 unchanged, R0 corrupted

Interrupt status unaltered.
Executes in SVC mode.  SWI should not be called from an interrupt routine.

Use

This SWI saves an Amnesia block as a file.

=======================================

<a name="loadtable">Amnesia_LoadTable</a>
-----------------

Saves the objects in an Amnesia table

On Entry

R0 = table number
R1 = filename
R2 = pathname

On Exit

R1-R2 unchanged, R0 corrupted

Interrupt status unaltered.
Executes in SVC mode.  SWI should not be called from an interrupt routine.

Use

This SWI loads objects from a file into an Amnesia table.  The object length
and table name should match.  Objects already in the table are preserved.

=======================================

<a name="savetable">Amnesia_SaveTable</a>
-----------------

Saves the objects in an Amnesia table

On Entry

R0 = table number
R1 = filename

On Exit

R1-R2 unchanged, R0 corrupted

Interrupt status unaltered.
Executes in SVC mode.  SWI should not be called from an interrupt routine.

Use

This SWI saves the objects in an Amnesia table which have bit 17 set in their
flags.

=======================================

<a name="gettableaddr">Amnesia_GetTableAddr</a>
--------------------

Gets the address of a table.

On Entry

R0 = table number

On exit

R0 = table address

Interrupt status unaltered.
Executes in SVC mode.  SWI is re entrant.

Use

This SWI returns the address of a table should you wish to manipulate it
yourself.  A brief idea of the table structure can be gleaned fron the
Headers document in the Technical directory.

=======================================

<a name="blocks">Amnesia_Blocks</a>
--------------

Prints a diagnostic report.

On Entry

No parameters

On exit

No results.

Interrupt status unaltered.
Executes in SVC mode.  SWI should not be called from an interrupt routine.

Use

Prints a diagnostic report listing the current block allocations, showing if
the area is sound or not.  If an Amnesia has just returned an error the
report will tell you in which block the error occured.

This SWI is intended for use from the command line during software
development.  It can be invoked by the command *Amnesia Blocks (or *Amn.B.). 
Amnesia keeps a guard word at the start of each block, so this command will
you if you have written to memory past the end of a block and corrupted the
header of the next.

=======================================

<a name="remote">Amnesia_Remote</a>
--------------

Attaces a remote call address to Amnesia's process loop.

On Entry

R0 = address to call
R1 = value to pass in R12

On exit

preserved

Interrupt status unaltered.
Executes in SVC mode.  SWI is not re-entrant.

Use

This SWI is new to Amnesia 1.50.  The call adds a routine to the process loop
which will be called if bit 19 is set in an object's flags.  Please see the
sources for the exact position of the call during the process routine, and
the <a href="remote">special help file</a>.

=======================================

****************************************************
    This document is copyright A.Southgate 1994.
    It may be freely distibuted and copied but
    should not be modified, otherwise things will
    get very confusing.
****************************************************
</HTML>