home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
misc
/
tornado
/
brief005
/
Brief
< prev
next >
Wrap
Text File
|
1995-07-13
|
86KB
|
1,812 lines
Tornado developers release 1 brief v0.05 alpha (12-07-1995)
This is a brief containing all of the formats and protocols as yet defined
throughly for Tornado. Mistakes may have been made, and the data contained
below is subject to change until release 1 comes out.
I strongly suggest you put this this through a printer and get it onto
hardcopy as soon as possible!
You will notice how every record is of length 2^x: This is so you can use
MOV Rx,<reg with no of records counted>,LSL #5 to get the logical offset in
bytes into the structure list.
At Tornado's private word is stored an OS_Module type block (dynamic area on
a RPC - possibly on lower OS machines too (vectoring OS_ChangeDynamicArea)):
+00: ptr to start of the Tornado system heap (currently here + 64 bytes)
+04: reloc ptr to subtask heap, itself a heap+ heap, within the system heap
+08: reloc ptr to the Tornado tasks currently active
+12: reloc ptr to the files currently in tfs:
+16: reloc ptr to the current tfs: directory
+20: fixed ptr to Tornado module task's user stack
+24: reloc ptr to 1K of scratch space
+28: reloc ptr to yeigen>=2 Tornado_SpriteOp style sprite space
+32: reloc ptr to yeigen<=1 Tornado_SpriteOp style sprite space
+36: reloc ptr to query windows open and their status
+40: reloc ptr to list of Tornado applications currently known about through
declarations by their !Boot files
(note if this is 0 then this option has been disabled)
+44 to +60: Reserved
+64: start of Tornado system heap
+xxx: end of Tornado system heap
****************************************************************************
Files currently in tfs: structure: (fixed 64 byte records)
+00: reloc ptr to data (0=empty record)
+04: reloc ptr to null terminated filename
+08: load address
+12: exec address
+16: length in bytes
+20: file attributes
+24: OS_Monotonic time when this file was last accessed by Tornado_Getaddr
+28: filetype of file (-64 if plain data)
Note that on RISC-OS to the current day the filetype is stored in the
load address, but it is also available here for future readiness.
+32: handle of file fileswitch gave us (=0 if file not open)
+36: sequential ptr of this file
+40: id handle of the owner of this file (duplicated in the stored block)
+44: reloc ptr to list of index's to subfiles
+48: file index that is hotlinked above this (=0 if none)
+52: file index that is hotlinked below this (=0 if none)
+56: reserved
+60: reserved
Notes on tfs:
* Use WimpExt_MemMove to do the memory copying, as it uses an Arm2 (erk!)
optimised memory copying routine. Sorries to Arm3 users!
* Allocated space for gbpb files is identical to the file length, due to
the quick access nature of RAM :-)
* FileSwitch buffer size is 1K.
* Direct unbuffered gbpb is supported.
* The file handle we pass to fileswitch is the record number of the file
entry ie; the first file gets a handle 0, the second =1. Simply shift the ptr
to the file's record down by six bits.
* FSEntry Args 8 uses the following code:
\On entry R2=file addr R3=number of zeros to write
MOV R0,R3,ASR #10 ; divide by 1024
ADD R2,R2,#start addr of file in memory after extending it by R3 bytes
ADR R1,zeros ; address of 32 bytes of zeros
LDMIA R1,{R3-R10}
.loop
{assemble this 1024/32=32 times. Works with a cache as 32*4=128bytes}
STMIA R2!,{R3-R10}
{end assembly loop}
SUBS R0,R0,#1
BNE loop
* The final note is that we won't adhere to everything specified in the
PRM's, although by right we should, but then again Acorn haven't, so why
should we? Specifically, sod the following:
No special fields (no one uses them anyway AFAIK)
Null length filenames
amassing all OS_Wrch output into a dynamic buffer _before_ printing it!
fancy *Cat. It will be simple, and give the same output as *Ex would.
libraries? Dunno, BBC style libraries are rather inefficient nowadays -
I'd prefer something like TornLib:.
Booting tfs: :-)
privilage bytes etc. Privs may be installed for future versions of
Tornado though.
What we will do is:
unlimited directory depth and filename length
use of spaces and topbit chars in filenames
unlimited number of files in a directory
unlimited number of files being opened
buffered i/o whenever possible, as it improves efficiency (eg;
fileswitch and our module not having to call super-fast copying routines
just to transfer one byte :-) )
block gbpb, as well as single byte
FSEntry_Func 15, as this is used by the Filer to display its windows
Startup banner: *definately!* :-)
****************************************************************************
Active Tornado task list structure: (fixed 128 byte records)
+00: reloc ptr to task name as passed to Tornado_Initialise (0=empty record)
+04: task handle
+08: task's R1 as passed from Tornado_Poll containing Wimp_Poll blk (fixed)
is on the subtask heap if this task is a subtask, otherwise in task's
memory slot
+12: 0, or interval between being preempted in milliseconds
if this is negative, then preemption is currently paused
+16: time given to wimp during preemption in centiseconds
+20: reloc ptr to last in the list of 17,18,19 preemption poll returns
+24: reloc ptr to last in the list of 1 preemption poll returns
+28: reloc ptr to last in the list of all other preemption poll returns
+32: fixed ptr to 256 bytes of preemption wkspace
+36: reloc ptr to list of 17,18,19 message numbers that should be immediately
acknowledged.
+40: reloc ptr to list of filetypes the app can load OR
if a subtask, then this is a reloc ptr to the 256 byte data block on the
subtask heap
+44: reloc ptr to list of filetypes the app can save OR
if a subtask, then this is a reloc ptr to a variable length block on the
subtask heap
+48: flags
bit 0: this task disabled garbaging on the system heap
bit 1: this task is a subtask
bit 2: this task has crashed, and polling has been disabled
+52: more flags
+56: option flags
+60: more option flags
+64: reloc ptr to list of query handles this task has open (=0 if none)
+68: reloc ptr to list of blocks this task has claimed off the system heap
if a subtask, then is a list of blocks claimed off the subtask heap
+72: reloc ptr to this task's config file
if a subtask, then this is reserved
+76: reloc ptr to list of files currently loaded in by the app
if a subtask, then this is reserved
+80: reloc ptr to list of subtasks currently running under this (sub)task
+84 to +124: reserved
Notes on Tornado task list:
Poll return list structure: (linked list)
+00: return code
+04: reloc ptr to next last in chain, or 0 if this is the last
+08: data as per Wimp_Poll until end of blk
Note: for the poll return 1, data is:
+08: window handle
+12,+16,+20,+24:bounding box to be updated/redrawn in that window
Filetype list structure: (fixed 8 byte records)
+00: filetype
+04: flags
bit 0:don't OLE to this file unless there is no choice
bit 1:disable automated loading for this filetype
Query window data structure: (fixed 16 byte records)
+00: window handle of query window currently open
+04: 0=this slot empty, 1=query window active, 2=waiting for data
collection
+08: result code if applicable.
+12: reloc ptr to window's indirection space
Currently loaded files list: (fixed 8 byte records)
+00: reloc ptr to file data
+04: reloc ptr to list of subfiles, if any (ie; =0 if none)
Currently running subtasks: (fixed 16 byte records)
+00: wimp handle of subtask
+04: Tornado id slot no of subtask
+08: reloc ptr to 256 byte block
+12: reloc ptr to variable length block used for holding returned blocks
****************************************************************************
Known Tornado applications list structure: (fixed 16 byte records)
+00: reloc ptr to task's path
+04: reloc ptr to list of filetypes the app can load
+08: slot number of task (=0 if not loaded right now)
+12: reserved
Notes on Tornado task list:
****************************************************************************
****************************************************************************
SWI's not definitively defined:
Tornado_IOOp - used to ensure apps don't receive serial data when they
shouldn't, and to buffer output so when routing is switched back here
the data isn't lost. And for general i/o, with Tornado handling the
interfacing.
Tornado_Status
Tornado_Initialise
Tornado_Poll
Tornado_Closedown
Tornado_SpriteOp - Tornado's superior spriteop calls
Tornado_ColourTrans - Tornado's superior colourtrans calls
Tornado_RenderFile - accesses library to render a file stored in system heap
Tornado_StandardEntryToFS - sets what's in tfs: on startup
Tornado_QCopyMem - enters into WimpExt_MoveMem currently
Tornado_CopyMem - enters into WimpExt_CopyMem currently
Tornado_RedrawWindow - allows a redraw of any parts of the window needing
updated, and anything specified by the Tornado script.
SWI's defined for sure:
Tornado_Initheap (SWI &)
On entry:
R0=flags
bit 0: This heap is a postslot heap
bit 1: This heap is a heap within an OS_Module block, and please
auto-extend
bit 2: This heap is a heap within a Heap+ block, and please auto-extend
bit 30: This heap being initialised is the proposed Tornado system heap
R1=ptr to proposed heap base
R2=ptr to heap base if bit 2 set
R3=length of proposed heap
On exit:
R1=ptr to heap base
All registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to initialise a Tornado Heap+ type heap. This heap format is based on
OS_Heap style heaps, and offers complete internal format compatibility. In
other words, you can use OS_Heap with this heap (be very careful though!),
but you won't be able to use any of the extended calls.
The area of memory you intend to initialise will be verified, and header
and other information written into it. Note minimum size is 128 bytes, and
the base must begin on a word-aligned address. The length must be a multiple
of 4 bytes.
The format of the information written into the area is not guaranteed to
remain similar during releases of Tornado, but presently is this:
+00:&70616548 = "Heap", like with OS_Heap |
+04:Offset to free list | Note this is the standard
+08:Offset to heap base | OS_Heap header
+12:Offset to heap end |
+16:&18 = the Heap+ identifier - also to OS_Heap indicates a block length
+20:offset within heap to the list of relocatable blocks
+0: length of list in bytes (beginning=0)
+4: offset within heap to an allocated block descriptor
+24:offset within heap to the list of non-relocatable blocks
+0: length of list in bytes (beginning=0)
+4: offset within heap to an allocated block descriptor
+28:flags
bit 0: this heap is auto-extending using Wimp_SlotSize
bit 1: this heap is auto-extending using OS_Module
bit 2: this heap is auto-extending using Tornado_Extblk
bit 30:this heap is auto-extending as the Tornado system heap
bit 31:disable garbage collection if bit 30 set
+32: base of heap+ heap containing this heap+ heap if bit 2 of +28 is set
Also, the format of each allocated blk:
-32:usually length of block +32 bytes (for OS_Heap - not used by Tornado)
-28:status word
-1 if it can't be dumped to disc (guaranteed -1 if non-reloc)
0 if it is dumpable to disc, but currently isn't
1 if it is currently on disc, in which case +00 onwards actually
contains the pathname to the stored block data.
-24:bit 30 clear means this block is non-reloc, set means reloc
bit 29 set means this block is one of a linked list
bits 0 to 28 is the id no (ie; the slot) of the task owning this block
-20: reloc ptr of linked block before this one (=total length of data if first)
-16: reloc ptr of linked block after this one (=0 if last)
-12: reserved
-08: reserved
-04:length of data (not including this header). Negative if the data is
on disc and not in memory, which means that this block is 32+256 bytes
long, ie; =288 bytes.
+00:start of data if data is in memory, or start of null terminated
pathname if the data is on disc.
Note that if bit 0 is set then the task's slot is automatically extended by
an appropriate amount and the heap set up at the previous environment end
address. From now on, any extensions to the heap needed will be done
automatically. Bit 1 will extend it using OS_Module; bit 2 will extend it
using Tornado_Extblk.
Note also that the heap+ structure itself is relocatable - this means all heap+
heaps can also be stored in a Heap+ or otherwise relocatable block.
Related calls:
All tornado heap calls;
Tornado_Getblk (SWI &)
On entry:
R0=flags
bit 0: this block is relocatable
bit 1: give it a unique filename (used only if R1=0). Can't be used if
bit 3 is set.
bit 2: don't do a garbage collection after this call
bit 3: the data contained within this block is ready-to-save (R1=0). In
other words, this block contains a saveable file. If this bit is
clear, the file in tfs: is marked as data (filetype=-64).
bit 4: If bit 0 is set,the data in this block is to be fragmented into
blocks of R6 length. This means special actions must be taken
when accessing the block's data. See below.
bit 5: If bit 4 set, automatically set R6 to the best value for speed.
bit 6: the data in this block also has subfiles. If this is set, then
R5 comes into play. Bit 3 must be set.
R1=heap+ ptr, 0 if system heap, -1 if subtask heap
R2=ptr to description of blk (used if R1=0 and bit 1 is clear)
R3=size of block wanted (bigger one may be granted)
R4=filetype of file if R1=0 and bit 3 is set
R5=reloc ptr to list of reloc ptr's to subfiles if bit 5 and bit 3 is set
R6=length of fragment if R1=0, bit 4 is set and bit 5 is clear.
On exit:
R1=updated heap+ ptr if R1<>0 on entry
R2=flags returned
bit 0: this block has had fragmentation forced
R3=handle of block; =0 and C set if allocation failed
R6=if bit 4 set on entry, =number of fragmented blocks allocated.
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full, if bit 2 is set. Otherwise undefined.
Use:
Used to claim a block from a Heap+ heap. If R1=0 then the block is claimed
from the Tornado system heap, in which case the block will also be given a
filename entry in your task's account.
If you ask for a relocatable block (by setting bit 0), which is _strongly_
recommended, then you will be given a handle which from hence you can use to
reference the block by. It will always be a negative number, and any data
contained within the block must be able to be relocated at arbitrary times.
You will not know if/when/how/why the block has been moved. To get the
_current_ address of the block, use Tornado_Getaddr. Read its entry for
further details of use.
If you ask for a non-relocatable block, the handle will be equal to the
start of the block. However, it is good programming practice to also call
Tornado_Getaddr for this handle, just to be sure you are getting the address
of the block (also makes sure if you change it later you won't have to change
too much of your code).
Unless you specifically ask otherwise, an automatic garbage collection
will be performed after this call, unless it has been disabled (only for
system heap).
The block will be given a filename entry in your account if you are
claiming from the system heap. This entry currently goes into the Claims
directory in your folder, unless you have set bit 3, in which case it will be
entered in the FileXXX directory. The unique filename given to a block if
requested is currently the hexadecimal equivalent of its handle.
If bit 4 on entry is set, then the data to be contained within this block
will be split up into blocks of R6 size. This is needed for virtual memory
reasons, as otherwise in order to edit a 24Mb file you'd need 24Mb of RAM to
store it in while it's being accessed. Splitting the 24Mb file into sections
of data, each contained within its own block, means accessing the block can
be done with much less RAM, typically 1Mb.
If bit 5 is set on entry, then R6 will be set to a multiple of the track
size of the media upon which the blocks are being kept, less a few dozen
bytes. This is because disc drives can load most efficiently when they load
full tracks of data. For example, a floppy E format has 1024 byte sectors, 5
sectors a track. And to load in 5120 bytes takes just as long as 1 byte.
However, loading in 5121 bytes needs access to another track, and takes as
long as loading in 10240 bytes. Determining how many multiples depends on
memory size, and Tornado preferences.
Note on this point that you should have bit 5 set for speed, but if you
have a routine that needs fixed portions of data (say a sprite plotter), then
set your own R6 value. For example, a sprite plotter plotting a 2560x2048
true colour sprite would use a 10240 byte fragment, as one line of such a
sprite contains just that much data.
Note that if you have specified auto-extending in Tornado_Initheap call,
then this call will only return an error if the entire heap couldn't be
extended, otherwise it's because the heap is full.
Note also that recursion is possible here: this heap being extended by
this call may cause the heap it's in to extend which may cause the heap it's
in to also extend. Failure of any one of these will return an error from this
command. Also, this command thus may take a while having to garbage and
extend multiple heaps.
Finally, note that the block may be fragmented even if you didn't ask for
it. This is because the user may wish to run in a tight-memory situation and
has requested that no blocks requested over x K should be allowed to remain
in memory. If you can't handle this, free the block and give an error to the
user using Tornado_GiveError with message no. 1, and if the user allows the
claim reclaim the failed block and continue with the operation. Make sure the
operation is fully cancelled if the user so chooses though.
Related calls:
All tornado heap calls;
Tornado_Freeblk (SWI &)
On entry:
R0=flags
bit 2: don't do a garbage collection after this call
R1=heap+ ptr, 0 if system heap, -1 if subtask heap
R3=handle of block
On exit:
R1=updated heap+ ptr if R1<>0 on entry
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to free a claimed block.
Unless you specifically ask otherwise, an automatic garbage collection
will be performed after this call, and if auto-extending is set, then the
heap will be automatically shrunk if possible. This, as above, may lead to
all heaps in the tree above to shrink as well. Thus, this command may take a
while having to garbage and shrink multiple heaps.
Related calls:
All tornado heap calls;
Tornado_Extblk (SWI &)
On entry:
R0=flags
bit 2: don't do a garbage collection after this call
R1=heap+ ptr, 0 if system heap, -1 if subtask heap
R2=signed change in bytes
R3=handle of block
On exit:
R1=updated heap+ ptr if R1<>0 on entry
R2=new size of block
R3=new handle of block
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to change the size of a claimed block. If R1=0, the filename in tfs:
remains unchanged.
Note that the new size of the block may be larger than you intended. This
is alright: just take care to redo any future resizing decisions (ie; if
storing the size, don't store previous size - amount requested to decrease
by, store the size returned by R2).
The new handle for the block will be the same if the block was
relocatable, but note it is good programming practice if you restore the
handle anyway, in case you may later have to alter the relocatable nature of
the data.
Unless you specifically ask otherwise, an automatic garbage collection
will be performed after this call, and the repercussions are as for
Tornado_Getblk and Tornado_Freeblk.
Related calls:
All tornado heap calls;
Tornado_Getsize (SWI &)
On entry:
R1=heap+ ptr, 0 if system heap, -1 if subtask heap
R3=handle of block
On exit:
R2=current size of block
R3=fragment size if the block is fragmented
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to determine the current size of a block.
Related calls:
All tornado heap calls;
Tornado_HeapInfo (SWI &)
On entry:
R1=heap+ ptr, 0 if system heap, -1 if subtask heap
On exit:
R0=size of heap
R1=heap base, filled in if R1=0 on entry
R2=largest free block in heap
R3=amount of free space available
R4=number of relocatable blocks in heap
R5=number of non-relocatable blocks in heap
R6=bytes occupied by relocatable blocks
R7=bytes occupied by non-relocatable blocks
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to determine the current state of a heap+ heap.
Related calls:
All tornado heap calls;
Tornado_ExtHeap (SWI &)
On entry:
R1=heap+ ptr
R2=signed change in size
On exit:
R2=new size
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to manually change the size of a Heap+ heap. Usually automated. Note
this may cause auto-extending heaps above this to garbage and also change
size.
Related calls:
All tornado heap calls;
Tornado_Getaddr (SWI &)
On entry:
R0=flags
bit 0: make data loaded contiguous, and load R4 bytes
R1=heap+ ptr, 0 if system heap, -1 if subtask heap
R2=offset within block you wish to access (if block fragmented)
R3=handle of block
R4=number of bytes to be made contiguous
On exit:
R2=actual address of block (points to offset given by R2)
R3=actual address of the start of this block in memory, or reloc handle of
block if bit 0 was set on entry
R4=number of bytes from R2 you can access before you must call this SWI
again
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to determine the actual address of a claimed block. If the handle passed
is non-negative, then the same handle is currently returned in R2.
The offset contained within R2 is the patch of data within the block you
wish to access. This should be given even if the block isn't fragmented, as
the user may have specified that a cap be placed on requests.
You can work out what memory can be accessed using R3 ie; you won't need
to call this SWI to access as far as this. You can still do anyway, and this
call is quite quick so little difference in speed will be noticed.
Note you can only access R4 bytes from where you asked for. This is
because only that much data has been loaded within that block.
Setting bit 0 on entry means that a new reloc block is created of R4
bytes, and one or more fragmented blocks are loaded into it to make it a
contiguous area of data. Make sure that when you're finished with this block
and the data (ie; before calling Tornado_Getaddr again), free the block. Note
finally that setting bit 0 is quite slow in operation, and having blocks
already in memory doesn't matter - they remain in memory - and thus, quite a
lot of memory can be wasted. Use a routine capable of using fixed size data
blocks to manipulate the data if possible.
This call also resets the time elapsed since last access to this block, or
fragment of a block. This is used for virtual memory, where when the system
heap becomes full the oldest blocks get dumped to disc. Using this call
indicates that you want to use this block. If the block is currently on disc,
it is reloaded into the heap and its address returned to you. Note no garbage
collection occurs when this happens.
You can be guaranteed that this address will remain the same until the
next specific call to Tornado_<call>, as all the calls done under
interrupts/vectors etc. by Tornado do not garbage collect the heap.
PLEASE NOTE: When preempting code and referring to the system heap, you
MUST use Tornado_GarbageHeap to force disabling of garbaging. If you do this,
you must be prepared to regularly do a Tornado_GarbageHeap followed with
another Tornado_Getaddr to ensure fragmentation does not become endemic. This
is because other Tornado apps may cause the heap to be garbaged.
Related calls:
All tornado heap calls;
Tornado_GarbageHeap (SWI &)
On entry:
R0=flags
bit 0:disable auto-garbaging (if R1=0)
bit 1:reenable auto-garbaging (if R1=0)
bit 2:do not garbage heap
R1=0, the system heap
On exit:
R1=updated heap+ ptr if R1<>0 on entry
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
Used to disable auto-garbaging on the system heap, and to force a garbage
collection.
If bit 0 is set, garbaging on the system heap is disabled and it is stored
that it was your task which requested it.
Note that this call may not garbage the heap if someone else has disabled
it (R1=0, system heap). Also, if reenabling garbaging and no-one else has
disabled it, an immediate garbage is done.
This call with flags %000 is performed after every Tornado_Getblk,
Tornado_Freeblk and Tornado_Extblk. If the system heap isn't being referred
to then there is nothing the task can do to stop auto-garbaging ie; you
cannot disable garbaging on private Heap+ heaps.
Note again treed auto-extending heaps may have to garbage and change size.
Related calls:
All tornado heap calls;
Tornado_DrawHeap (SWI &)
On entry:
R0=flags
bit 0: render as a OS_Heap style heap (ie; compatible with OS_Heap)
if set, use R7 as allocated, R8 ignored and preserved
R1=heap+ ptr, 0 if system heap, or an OS_Heap ptr (if so set bit 0)
R2=x pos of left (inc) R3=y pos of bottom (inc)
R4=x pos of right (inc) R5=y pos of top (inc)
R6=&BBGGRR00 of free space
R7=&BBGGRR00 of reloc blocks, or allocated blocks if bit 0 set
R8=&BBGGRR00 of non-reloc blocks
On exit:
All registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call renders a graph of the heap pointed to by R1. The graph is squashed
into the bounding box as specified R2,R3,R4,R5, and the Tornado_ColourTrans
call is used to calculate anti-aliasing to display detail not possible with
the available screen resolution. This is why the colours are specified using
the absolute 24 bit method.
Note this call is provided for the exclusive use of the Tornado graphic
renderer used to render heaps. Do not use otherwise.
Related calls:
All tornado heap calls; Tornado_ColourTrans
Tornado_StartPreemption (SWI &)
On entry:
R0=interval in ms given to Wimp (may be overriden by !Options or by
general decree)
R1=reloc ptr to list of 17,18,19 messages that should be acknowledged.
On exit:
All registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call starts premption on the Tornado task calling it, or restarts it if
preemption is paused. Any result codes returned are stored in the Tornado
system heap until they can be collected by the task.
Note the following restrictions that must be observed while under
preemption:
1: Any relocatable blocks in the system heap are liable to move due to
another task doing ops on the system heap. Thus, getting the address of a
block using Tornad_Getaddr and using it cannot be done as the address may
change in mid-processing. To get around this, set up a post-slot heap, which
is very easy using Tornado_InitHeap, and allocate all your preemptive code
data requirements from it. If you _must_ access a block in the system heap,
copy the system heap block into your own postslot heap, and do the processing
there, recopying it back after (preemption won't occur during all SWI's
running in SVC mode so you shouldn't need to disable garbaging if you're
using Tornado_QCopyMem).
However, it may be possible that all the processing must be done on a
block in the system heap, and it must remain there during processing because
something else is relying on the *_absolute_* latest results (this is NOT
encouraged), or perhaps altering data there in response to your alterations
(note then that you should really use Tornado_SendMessage then). If this is
the case, disable garbaging using Tornado_GarbageHeap and do your processing
_as_ _quickly_ _as_ _possible_ in fragments, and in between fragments
reenable garbaging, do your return code enumeration, and return to processing
with another Tornado_Getaddr. This is to prevent fragmentation which happens
alarmingly quickly if garbaging is disabled, especially if virtual memory is
enabled. It is possible two apps are disabling garbaging, and one still has
it disabled when the other reenables it. If this is the case, which is
_extremely_ unlikely, too bad.
Note that rather than this 'desperate' approach, one can use the quick
memory copying routines of Tornado to copy in and out data more than might be
necessary in order to keep the data very up-to-date.
2: You should call Tornado_EnumPreemptResults to pick up on any return
codes that have occurred during processing. By right you should enumerate all
the codes until C becomes set, but if you are pushing processing speed to the
limits (unlikely as you are depending on other tasks anyway), you may go as
far as the end of 17,18 & 19. However, if absolutely possible, do process
code 1, as these tend to not only fill up memory rather quickly, but
unprocessed they also leave the display in your windows blank, which is
rather a characteristic of preempted code, and annoying to say the least (it
gives the user a rather false impression of the app being slow).
Be warned that certain return codes issued by the Wimp and others assume a
reply before the next Wimp_Poll: here you have no such luxury. You can enter
a list of 17,18,19 codes to acknowledge immediately, but this isn't a perfect
solution. TBH, avoid preemption if possible: the Wimp was never designed for
it, and actively inhibits it.
It may be possible that you have to disable menus etc. during this. Try
not to - grey out menu options etc, and remove changing pointers in the
appropriate places. Tornado has been structured as so as much application
availability is present during preemption as possible: please use it!, and
write your code to accomodate. It's usually not difficult anyway. Note not
having full application presence at any time, unless it's another apps fault,
will mean your program will automatically fail any Tornado standards test it
may be put through.
3: Finally, ask yourself why you want to preempt this code? Is it /really/
necessary, for example in order to prevent polling becoming uneven during
complex code? Are you doing a specific task or process, like doing an
operation on a file? If you are, you should be using subtasks, not
preemption. Preemption is here for use with places where normal polling is
difficult, or inconvenient, like when loading Templates, although of course
Tornado does that for you; another place is loading in a difficult file
format, although if it is a standard file format (eg; Lotus 123 spreadsheet)
then you should have written a subtask file convertor to change the file into
one you can read easily (Tornado does this for you).
Also note that during action on code 1, preemption should be disabled during
the loop between Wimp_UpdateWindow and Wimp_GetRectangle. Using
Tornado_RedrawWindow, which you should do, does this automatically.
Related calls:
Tornado_EnumPreemptResults; Tornado_PausePreemption;
Tornado_EnumPreemptResults (SWI &)
On entry: Nothing
On exit:
R0=reason code, 0=preemption now finished
The data as per Wimp_Poll is filled into the Wimp_Poll R1 as specified to
Tornado_Initialise, except for reason code 1, where:
R1+00: window handle to be redrawn
R1+04,+08,+12,+16: bounding box, all inclusive.
R1=ptr to return code data, as specified in Tornado_Initialise
The C bit is set if this is the last entry
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call removes the codes returned during preemption from memory and stores
them in task's memory at R1. The only different one is code 1, which instead
of pointing to Wimp_Poll return block points to a box in a window to be
redrawn using Tornado_RedrawWindow.
Please read the restrictions and conditions attached to using preemption
in the SWI entry Tornado_StartPreemption.
When the call returns with C set, then this is the last return code
stored. If you wish to shut down preemption, call the SWI again and R0 should
be 0. However, be prepared for it being non-zero, and possibly with C set
again. Again, do not depend of C being set. Ie; to stop preemption, keep
calling Tornado_EnumPreemptResults and acting on the codes until R0 returns
with zero. Conversely, if you wish to enumerate and act upon all the codes
currently stored, call this SWI until C returns set: then return to
processing.
Another option, if you wish to quicken processing, is to do say 25 returns
and then return to processing. Again, doing this will fail any Tornado
standards test.
Finally, if preemption is disabled when this call is made, it is
reenabled.
Related calls:
Tornado_StartPreemption, Tornado_PausePreemption
Tornado_PausePreemption (SWI &)
On entry: Nothing
On exit: All registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Full
Use:
This call pauses preemption. It is needed during code done from replies in
which having a poll would be fatal (eg; redraw code). Tornado_RedrawWindow
does this automatically for you, and by right you should be using this call
anyway.
Note this does _not_ /stop/ preemption: merely pauses it. It is not a good
idea to not restart preemption and continue on with your code.
Finally, note that this call merely prevents Wimp_Poll being called, and
user code is still interrupted as usual (actually, interrupts increase as it
is taken the callback has failed (say because of RMA failure) and so the
interrupt is rescheduled for much sooner than usual).
Related calls:
Tornado_StartPreemption, Tornado_EnumPreemptResults;
Tornado_Hourglass (SWI &)
On entry: R0=hourglass reason code
other registers change with reason code, see below.
On exit: returned registers change with reason code, see below.
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: Probably none
Use:
This command performs operations on the Tornado hourglass. These are the
currently used reason codes:
0: wake hourglass with 'multitasking process' showing
1: turn hourglass off
2: wake hourglass with 'load' showing
3: wake hourglass with 'save' showing
4: wake hourglass with 'process' showing
5: smash hourglass, irrespective of count
6: wake hourglass with a percentage of task completed.
takes value 0-100 in R1
7: wake hourglass with time to go displayed.
takes value of time to go in cs in R1
16:specify wait in cs before hourglass should be shown when called above
takes time in cs in R1, if -1 then suppress hourglass, 0 to desuppress
Related calls:
*THourglass;
Tornado_Query (SWI &)
On entry: R0=flags
bits 0 & 1: type of button default button is
%00:press and this goes away
%01:press, and an action is done
others reserved
bits 2 & 3: type of button opposite button is
same as for bits 0 & 1
bits 4 & 5: type of button auxillary button is
same as for bits 0 & 1
bit 6: return even if no selection has been made
bit 7: I am checking current status
R1=ptr to null terminated title, or a handle (see below)
title should be one of:
"Query from <appname>:"
"Message from <appname>:"
"Error from <appname>:"
R2=ptr to null terminated text for default button
R3=ptr to null terminated text for opposite to default button
R4=ptr to null terminated text for auxillary button
On exit: R0=reason code
0:pending result, in which case R1 comes into play
1:default button selected
2:opposite button selected
3:auxillary button selected
R1=query handle if R0=0,otherwise preserved
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: USR
Re-entrancy: None
Use:
This call opens a query window to either give information or ask a question.
The flags specified in R0 determine what the pointer changes to over the
button, ie; between a hand and a magic wand. This is so the user knows that
by pressing this button something will happen. With the magic wand ptr, it
means that pressing this button will cause a defined action as given byt the
text within the button, like writing to a disc, whereas the hand ptr
indicates that pressing this will pretty much make this window go away.
You can ask for control to be returned to you before the user makes a
selection, but note then you must regularly call this SWI with bit 7 set to
determine if the user has made a choice. Note also not to expect the user to
reply at all.
Note this facility can be automated from flags in Tornado_Initialise, in
which case checking is done automatically and returned if necessary to you
through Tornado_Poll. It is suggested you make use of this.
Related calls:
*TMess; *TError;
Tornado_GiveError (SWI &)
On entry: R0=flags
bit 0: this is a message, not an error. Ie; use 'Message from' in
the title and provide only the first button.
R1=number of error message to give. See below.
R2=%0, R3=%1 ...
On exit: R0=reason code
1: first button chosen
2: second button chosen
3: third button chosen
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: USR
Re-entrancy: None
Use:
This call calls Tornado_Query for you with a standard error message. The
currently defined error messages are:
0: "This application recommends having !System, the system resources
folder, present and available during operation. Without its presence the
application may not function correctly. Do you wish to continue anyway?",
"No", "Yes"
1: "This application recommends having !Scrap, the system scrap file
folder, present and available during operation. Without its presence the
application may not function correctly. Do you wish to continue anyway?",
"No", "Yes"
2: "This application recommends having the outline font renderer loaded
in, operating correctly and available during operation. Without its presence
the application may not function correctly. Do you wish to continue anyway?",
"No", "Yes"
3: "This application recommends having !Fonts, the system fonts storage
folder, present and available during operation. Without its presence the
application may not function correctly. Do you wish to continue anyway?",
"No", "Yes"
4: "Due to the absence of outline fonts, contained in !Fonts, this
application has defaulted to using <%0> font instead. You may show the
!Fonts folder later, and the application will then be able to use them"
5: "This application needs to have !Fonts, the system fonts storage
folder, present and available during operation. Without its presence the
application will not function correctly. Do you wish to continue anyway?",
"No", "Yes"
6: "This application needs to have at least v<%0> of <%1>, the <%2> loaded
in and running. Unfortunately, no such module can be found anywhere on your
system, and it is unlikely that without this, this application will function
correctly. Do you wish to continue anyway?", "No", "Yes"
7: "This application needs to have at least v<%0> of <%1>, the <%2> loaded
in and running. Unfortunately, I cannot find such a copy anywhere in your
system. The currently present version is v<%3>; do you wish to continue
anyway?", "No", "Yes"
8: "This application needs to have at least v<%0> of <%1>, the <%2> loaded
in and running. After noting the currently loaded copy of that module was
v<%3>, Tornado checked the copy in !System and found it was also too old,
being of v<%4>. What do you wish to do?", "Cancel execution of program",
"Continue with execution", "Load in copy from !System and continue"
12: "This application was refused a memory request as you have placed a
cap on solid memory claims, and this application needs to claim <%0>K of
solid memory to perform the requested operation. Do you wish to allow this
claim?", "Yes", "No", ""
256: "Please wait: loading in v<%0> of <%1>, the <%2> from !System ...",
"", "", ""
257: "Please wait: replacing v<%3> of <%1>, the <%2> with v<%0> from
!System ...", "", "", ""
258: "Warning: Tornado is about to replace v<%3> of <%1>, the <%2> with
v<%0> from !System. Do you wish to stop this?", "No", "Yes", ""
Related calls:
*TMess; *TError;
Tornado_Initialise (SWI &)
On entry: R0=latest version of Tornado known by this task * 100
R1=ptr to 256 byte block in task's slot
R2=ptr to short description of task (null terminated)
R3=flags
bit 0: I don't want to become a wimp task (NOT SUPPORTED YET!)
bit 30: The task being started is a Tornado subtask (internal)
On exit: R0=current version of Tornado * 100
R1=task handle given by the Wimp
R2=current version of the Wimp * 100
R3=slot number this task has been given
R4=ptr to environment string (ie; parameters)
R5=reloc ptr to config file
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call declares the CAO to be a Tornado task, and it wishes to also become
a Wimp task. A new record is entered into Tornado's data records and the task
becomes an official part of Tornado. From now on, this task must comply with
all Tornado regulations and will have many things done for it.
What happens upon this call:
* Tornado calls Wimp_Initialise with suitable parameters
* Tornado finds a free record and enters this task into it
* Tornado does a OS_GetEnv and reads in the parameters, checking for any
Tornado specific ones, acting if present
* Tornado opens the file "<path from environment string>.TData", and reads in
the data
* Tornado loads in the configuration file, the location of which can be
anywhere really (ie; don't assume it's in !<appname>.!Config).
Related calls:
*TMess; *TError;
Tornado_Closedown (SWI &)
On entry: R0=0 if simple shutdown,
=1 if call OS_Exit for me,
otherwise ptr to exiting error block
R1=task handle given by Wimp (optional)
R2=Tornado slot number given in Wimp_Initialise (optional)
On exit: All registers preserved, but never returns if R0=1 on entry
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call closes down the current Tornado task. In addition to removing all
data pointers associated with the task from memory, it also:
* Calls Wimp_CloseDown
* Shuts any open files this CAO has opened during execution
* Shuts down any subtasks belonging to this task currently running, and any
siblings of those subtasks.
* deallocates any blocks claimed by this task during execution from the
system heap
* removes the account for this task from tfs:
Related calls:
Tornado_Initialise;
Tornado_Poll (SWI &)
On entry: R0=mask as per Wimp_Poll
R1=flags
bit 0: Return in R2 cs if possible (NOT GUARANTEED)
R2=time given to Wimp in cs
On exit: R0=return code (see below)
R1=ptr to 256 byte block used to contain data
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call is the Tornado duplicate of Wimp_Poll and should be called as
frequently as possible.
The reason codes returned are:
-4: Subtask control messsage
R1+00: subtask return code, which can be:
=0: subtask that was run is not a subtask
R1+04: reason why Tornado thinks this
=0: subtask didn't call Tornado_InitialiseSubtask within
the first five seconds
=1: subtask failed to start up
R1+04: reason why:
=0: an error occurred before it called
Tornado_InitialiseSubtask
R1+08: standard error block
=1: an error occurred while the subtask was being loaded
in:
R1+08: standard error block
=2: an error occurred as the subtask was begun as the CAO
R1+08: standard error block
=2: subtask has begun, and has called Tornado_InitialiseSubtask
R1+04: task handle of subtask
R1+08: id no of subtask
R1+12: memory given to subtask
=3: message from subtask
R1+04: task handle of subtask
R1+08: id no of subtask
R1+12 onwards: message sent
=4: subtask has ended prior to completion
R1+04: task handle of subtask
R1+08: id no of subtask
R1+12: standard error block
=5: subtask has ended, having completed processing
R1+04: task handle of subtask
R1+08: id no of subtask
-3: In one form or other, the user has loaded/wants to load a file.
Note that this should be treated as 'replacing' an existing file,
even if the file is dragged onto the icon bar (ie; creating a new
file). So if the user drags a file onto a frame in a DTP page, the
file within that frame should be replaced if possible, and the data
previously contained in the frame thrown away.
If bit 1 in Tornado_Initialise was set then:
User has just loaded a file:
R1+0: method used to load file:
=0: loaded from the filer
R1+04: handle of window user dragged to (-2 if icon bar)
R1+08: icon handle if any
R1+12: x pos of mouse (absolute)
R1+16: y pos of mouse (absolute)
R1+20: length of file
R1+24: filetype of this file
R1+28: original filetype of this file (may be same)
R1+32: (5 bytes) datestamp of this file
R1+37: (byte) type of this file from OS_File,5
R1+38: (2 single bytes) reserved
R1+40: reloc handle of block containing loaded file
R1+44: handle of task this file came from
R1+48: handle of window this file came from
R1+52 to +255: (string) pathname of file
=1: loaded by someone copying into your a/c
R1+04: -2 always ie; create a new file
R1+08: undefined
R1+12: undefined
R1+16: undefined
R1+20: length of file
R1+24: filetype of this file
R1+28: original filetype of this file (may be same)
R1+32: (5 bytes) datestamp of this file
R1+37: (byte) type of this file from OS_File,5
R1+38: (2 single bytes) reserved
R1+40: reloc handle of block containing loaded file
R1+44: undefined
R1+48: undefined
R1+52 to +255: (string) pathname of file in tfs:
=2: loaded from another application. Note this happens when
the user drags a file out of another app into this one.
R1+04: handle of window user dragged to (-2 if icon bar)
R1+08: icon handle if any
R1+12: x pos of mouse (absolute)
R1+16: y pos of mouse (absolute)
R1+20: length of file
R1+24: filetype of this file
R1+28: original filetype of this file (may be same)
R1+32: (5 bytes) datestamp of this file
R1+37: (byte) type of this file from OS_File,5 (usually 1)
R1+38: (2 single bytes) reserved
R1+40: reloc handle of block containing loaded file
R1+44: handle of task this file came from
R1+48: handle of window this file came from
R1+52 to +255: (string) pathname of file
=3: loaded by Tornado OLE. Note that this call is also issued
to an OLE client ie; a task which is already editing an
OLEd file, in order to update zooms, move the editor
window etc. In other words, check words +44 to +52 before
creating a new file. Word +40 will always remain the same
during an OLE operation. Do not rely on other data though.
R1+04: -2 always, ie; create a new file
R1+08: undefined
R1+12: undefined
R1+16: undefined
R1+20: length of file
R1+24: filetype of this file
R1+28: original filetype of this file (may be same)
R1+32: (5 bytes) datestamp of this file
R1+37: (byte) type of this file from OS_File,5 (usually 1)
R1+38: (2 single bytes) reserved
R1+40: reloc handle of block containing loaded file
R1+44: handle of task this file came from
R1+48: handle of window this file came from
R1+52: id to know this file by
Note the following coords are absolute and should be scaled
before being used if necessary.
R1+56: min x of your editor window (-1 if open normally)
R1+60: min y of your editor window
R1+64: max x of your editor window
R1+68: max y of your editor window
R1+72: x multiplier (seperate from the screen res scaling)
R1+76: y multiplier
R1+80: x divisor
R1+84: y divisor
Note that in the title and info boxes concerned with this
file, you should show which task the file came/is from
=4: loaded from simple OLE. Essentially, when Tornado OLE
fails then a DataOpen is broadcast, and any app picking it
up is given a filename in tfs:$.<appname>.OLE.*, and after
editing the file is saved back, Tornado picks this up and
replies to the original task through this entry.
R1+04: handle of the window the user originally OLEd file
from
R1+08: undefined
R1+12: undefined
R1+16: undefined
R1+20: length of file
R1+24: filetype of this file (will be the same as your
older copy)
R1+28: original filetype of this file (may be same)
R1+32: (5 bytes) datestamp of this file
R1+37: (byte) type of this file from OS_File,5 (usually 1)
R1+38: (2 single bytes) reserved
R1+40: reloc handle of block containing loaded file
R1+44: handle of task this file came from
R1+48: handle of window this file came from
R1+52: pathname of file, usually something like "tfs:<app
name>.OLE.*". See Tornado_InitOLE.
=5: loaded by hotlink. This code is returned to replace a file
currently loaded in, as this file is hotlinked to another
file being edited in another application.
R1+04: handle of the window the user originally OLEd file
from
R1+08: undefined
R1+12: undefined
R1+16: undefined
R1+20: length of file
R1+24: filetype of this file (will be the same as your
older copy)
R1+28: original filetype of this file (may be same)
R1+32: (5 bytes) datestamp of this file
R1+37: (byte) type of this file from OS_File,5 (usually 1)
R1+38: (2 single bytes) reserved
R1+40: reloc handle of block containing loaded file
R1+44: handle of task this file came from
R1+48: handle of window this file came from
R1+52: id of file
-2: A query window has been answered
-1: An i/o operation has terminated
R1+0: result code
=0: i/o failed
=1: i/o succeeded
R1+4: handle of i/o task
R1+8: error block if applicable
00: Null reason code, no other code applicable
01: Redraw window request (call Tornado_RedrawWindow)
02: Open window
03: Close window
04: Pointer leaving window (call Tornado_AlterPointer)
05: Pointer entering window (ditto)
06: Mouse click has occurred
07: User has finished dragging a box
08: User has pressed a key
09: User has selected a menu option
10: User has scrolled a window
11: You have lost ownership of the caret
12: You have gained ownership of the caret
13-16: reserved by Acorn
17,18: Wimp message arriving
19: Wimp message previously sent has bounced
Related calls:
*TMess; *TError;
Tornado_InitOLE (SWI &)
On entry: R0=flags
bit 0:
R1=reloc ptr to file data
On exit: R0=result code
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call initiates an OLE event, whereby a file or subfile loaded into the
task calling this SWI passes that file to another task (doesn't have to be a
Tornado task) for editing.
The procedure is thus: First, Tornado checks through the tasks currently
loaded in and sees what filetypes they can edit. If it finds one, it passes
code -3 out of Tornado_Poll to the task, with R1+0=3. Depending on options
set in the TManager, the OLE client's (the task getting the OLEd file) editor
window will either be displayed as normal, or directly over the file in the
server's window, and essentially becomes a pane of that window (although they
remain unconnected).
If there are no Tornado tasks loaded, things get more complex. Any of the
following may be executed, in any order:
* Tornado looks through the list of tasks it knows about (if enabled), and
if it finds one that can load this filetype directly it loads it in and then
starts the whole process again.
* Tornado looks through the list of tasks it knows about (if enabled), and
if it finds one that can load this filetype directly or through a translator
(after obviously checking for the presence of a suitable translator first!)
it loads it in and then starts the whole process again.
* Tornado defaults to simple OLE, and broadcasts a DataOpen with a file in
"tfs:$.<appname>.OLE.*". Any file saved back to this path will be reinserted
over the file originally OLEd.
* Tornado defaults to simple OLE, checks for the option above, and if it
finds no tasks available it executes the appropriate Alias$@RunType_XXX for
it, by simply *Filer_Run-ing the file in "tfs:$.<appname>.OLE.*"
The reason the above processes are so ambiguous is simply that the user may
have chosen some options but not others, and all options depend on available
memory/resources so say if there isn't enough memory to do one option another
may be done instead (again, user configurable).
Related calls:
*TDeclareTypes;
Tornado_FileOp (SWI &)
On entry: R0=flags
R1=ptr to null terminated title, or a handle (see below)
On exit: R0=reason code
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call allows polling to continue during loads and saves.
Related calls:
*TMess; *TError;
Tornado_StartSubtask (SWI &)
On entry: R0=flags
R1=ptr to null terminated subtask name
R2=ptr to parameters
R3=signed memory change to the default amount given to subtask
On exit: R0=return code
=0: subtask has been scheduled, please wait.
=1: subtask couldn't be found
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call issues a request to begin a subtask. The request is scheduled, and
almost certainly will return code 0. All subtasks reside in TSubtasks:, and
this path may point to one of a number of directories.
The memory change given is a signed integer, denoting the alteration to
the default amount of memory allocated to the subtask. The subtask, by
default, is issued with a slot of its executable size on its storage media
plus 32k.
The ptr to the block containing the parameters has the following format:
+00: ptr to list of reloc ptr's in the system heap giving data necessary
needed by the subtask.
+04 to +256: the parameters needed by the subtask
Related calls:
*TMess; *TError;
Tornado_KillSubtask (SWI &)
On entry: R0=flags
R1=subtask's wimp task handle
R2=Tornado id no of subtask
On exit: R0=return code
=0: subtask has been destroyed
=1: subtask isn't currently running, or subtask not found
=2: subtask couldn't be destroyed. If so, R1 comes into play:
R1=ptr to standard error block
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call kills a subtask currently running. It is used internally by Tornado
when the parent task calls Tornado_Closedown, and by any task wishing to
cancel a process.
Related calls:
*TMess; *TError;
Tornado_InitialiseSubtask (SWI &)
On entry: R0=latest version of Tornado known by this task * 100
R1=ptr to name of subtask
R2=flags
On exit: R0=current version of Tornado * 100
R1=task handle given by the Wimp
R2=current version of the Wimp * 100
R3=slot number this task has been given
R4=reloc ptr to parameters passed by the parent of this subtask
R5=wimp task handle of the parent of this subtask
R6=slot number of the parent of this subtask
R7=amount of memory given to this subtask
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call initialises a subtask. Preemption of the subtask's code is started,
and from now on the subtask can begin processing. Also, it can communicate
with its parent, and can grab memory etc.
All processing must be done to and from the subtask heap, referenced by
putting -1 in Tornado heap calls. Tornado will handle the copying of data to
and from the parent task and the subtask.
What happens when this call is made:
* Tornado_Initialise is called. Two blocks of data are allocated on the
subtask's heap, and two blocks are allocated on the system heap.
* Preemption is started, and the parent task informed this task
sucessfully started.
Remember the contents of R4, as you will need it for later usage. The
block pointed to by R4 is guaranteed to be at least 256 bytes.
The block of parameters on entry has the following format:
+00: ptr to list of reloc blocks that have been passed to you
+04 onwards: any other relevent data
Note it is your responsibility to remove the blocks given to you once you've
finished with them. This is usually not necessary as the data will be needed
during the duration of the processing, and the blocks will be freed when the
subtask terminates anyway.
Related calls:
;
Tornado_GetSTMessages (SWI &)
On entry: None
On exit: R0=task handle of task sending this message (=0 if no messages)
R1=slot number of task sending this message
R2=reloc ptr to message, same as R4 from Tornado_InitialiseSubtask
R3=number of messages left to be processed
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call checks if there are any messages waiting for the subtask. It also
replies how many messages are waiting, as the subtask may wish to deal with
all outstanding messages at once.
The message block has the following format:
+00: ptr to list of reloc blocks that have been passed to you
+04 onwards: any other relevent data
Note it is your responsibility to remove the blocks once you've finished with
them.
Related calls:
;
Tornado_SendSTMessages (SWI &)
On entry: R0=task handle of task to send this message to
R1=slot number of task to send this message to
R2=reloc ptr to message block, same as R4 from
Tornado_InitialiseSubtask
On exit: All registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call sends a message to a task. The message block is of the following
format:
+00: ptr to list of reloc blocks being passed to recipient
+04: any other relevent data
Note this message can be used to pass directly small amounts of of data, and
it is preferable that portions of data are sent ie; don't send an entire file
as yet uncompleted. This is in an attempt to reduce bandwidth needed to
transmit the data.
Note it's your responsibility to remove the blocks after this call
returns, if they are of no more use to you.
Related calls:
;
Tornado_RenderFile (SWI &)
On entry: R0=flags
bit 0: What kind of file is this?
R1=ptr to heap, 0 if system heap
R2=reloc ptr to data
R3=filetype of data
R4=block containing standard header of data
On exit: R0=return code
=-1: please reschedule this call, by Tornado_ForceRedraw or
whatever (Tornado is loading in a renderer)
=0: R1 contains type of file
=1: file rendered successfuly
=2: error occurred during rendering. R1 then points to standard
error block
=3: file is being rendered (ie; movie or audio)
R1=type of file if R0=0
=-2: please reschedule this call
=-1: unknown, as there was no renderer available to say
=0: vduable sequence (Draw, Paint, Euclid, DTP etc)
=1: audio (soundtracker, simple sample etc)
=2: movie (Replay, MPEG etc)
R2=various data
If R1=1, then R2=correct replay rate to use (-1 if unknown)
If R1=2, then R2=frames per second by default
All other registers preserved
Interrupts: IRQ's enabled
Processor mode: SVC
Re-entrancy: None
Use:
This call renders a file, of any type. You can determine the type of file by
setting bit 0 on entry, and bear in mind you may be asked to reschedule while
Tornado loads in a suitable renderer. The block pointed to by R4 is of the
following type:
For type 0, a vduable sequence:
+00: absolute x position of bottom left corner
+04: absolute y position of bottom left corner
+08: absolute x position of top right corner
+12: absolute y position of top right corner
For bitmaps, no more standardised information
For 2D vectors, no more standardised information
For 3D vectors:
+16: x sweep in radians shifted up by 16 bits
+20: y sweep in radians shifted up by 16 bits
+24: z sweep in radians shifted up by 16 bits
+28: distance from object
+32: no more standardised information
For text (note only +00 and +12 are used here):
+16: font handle to be used in plotting
+20: how to treat control characters
=0: standard (I'll fill in the rest here later)
+24: tab spacing
+28: blah blah (again, I'll fill this in later)
For type 1, an audio sequence:
+00: time index in cs to start playing from (-1 if stop rendering)
+04: speed in Khz to play at (-1 if take default or stored)
For type 2, movies:
+00: absolute x position of bottom left corner
+04: absolute y position of bottom left corner
+08: absolute x position of top right corner
+12: absolute y position of top right corner
+16: time index in cs to start playing from (-1 if stop rendering)
+20: flags
bit 0: don't play sound if available
+24: quality
=0: highest possible
=1: high (say less anti-aliasing and dithering)
=2: medium (66% of high quality)
=3: course (33% of high quality)
=4: worst possible
+28: frames per second to play back at (-1 if use default)
+32: no more standardised information
Related calls:
;
****************************************************************************
Star commands not yet definitively defined:
Star commands defined for sure:
*TCheckSystem
Use:
This command checks for the presence of !System, and if it is not present a
suitable message is displayed. Note that the user may choose to continue
regardless, but otherwise the current Obey file in progress is terminated.
It is to be used in !Run files of Tornado applications.
*TCheckScrap
Use:
This command checks for the presence of !Scrap or a similar facility, and if
it is not present a suitable message is displayed. Note that the user may
choose to continue regardless, but otherwise the current Obey file in
progress is terminated.
It is to be used in !Run files of Tornado applications, but only if the
presence of <Wimp$Scrap> and <Wimp$ScrapDir> is vital to the correct
functioning of the program. Ie; checking for <Wimp$Scrap> to be used in the
data transfer protocol is not vital, especially as Tornado will do its own
scrap file if absolutely necessary.
*TCheckFonts [1|0]
Use:
This command firstly checks for the presense of the outline font manager, and
afterwards the presence of !Fonts, and if they are not present a suitable
message is displayed. Note that the user may choose to continue regardless,
but otherwise the current Obey file in progress is terminated.
It is to be used in !Run files of Tornado applications, but only if the
presence of the font manager is of vital importance. Usually, this is not the
case. Note putting 1 as a parameter makes Tornado far more serious about the
message, and it denotes that your task /needs/ the _outline_ font manager to
work correctly. Unless you are an application which bends fonts or something,
you should never need to use this.
Leaving out any parameters assumes the default, a value of 0.
*THourglass <On|Off|Load|Save|Process|Kill>
Use:
This command starts up the Tornado hourglass, which may be set to display
current actions through its parameter. Note Tornado hooks itself into Obey,
so if the obey file is closed suddenly the hourglass is killed.
Use SWI Tornado_Hourglass for the same call in code. It also allows
greater flexibility.
*TIconsprites <base pathname>
Use:
This command adds the file specified by the base pathname (appendation="") to
the lo-res Tornado sprite pool, and adds the base + "22" to the hi-res
Tornado sprite pool. In future there may be a hires mono switch to load these
into the hires pool instead, but this will be transparent to the task.
The current screen mode is then read, and the entire copy of the sprites
is copied out of the relevent sprite pool into the system sprite pool,
replacing any sprites already there. This also occurs on mode changes. Note
the user may override these default actions, so do not assume anything.
SWI Tornado_SpriteOp provides much greater flexibility than this command,
and should be used in code. This command is for !Run and !Boot files.
*TRMEnsure <module> <version> <mod lname> [<mod descript>]
Use:
This command checks for the presence of the module specified and for the
version. If it cannot find the module, it checks !System (if defined - it
will do a TCheckSystem first) for the module entitled <mod lname>, and if
present loads it. If it isn't there either, it shows a message to the user
indicating that the module isn't present on the system at all. Note the user
may still ask for program execution to continue, although he/she will be
strongly recommended not to do this.
If a copy of the module is loaded in, the module version is checked
against that in the command, and if it is too old then again an attempt is
made to load in a newer copy from !System. After this, if it is still too old
or there isn't a copy in !System, a suitable message is shown to the user
indicating that the module version available is too old. Note the user may
still ask for program execution to continue.
*TRun <name> [<params>]
Use:
This command firstly sets <[name]$Dir> to <Obey$Dir>, and then normally looks
for the !Config file within <[name]$Dir>, but if the application is on a
read-only media (like CD-ROM) then Tornado may run another config file. This
config file sets where to find !RunImage, and how to run it, along with other
preferences set.
Note that <name> is used by Tornado to refer to your application
internally, including setting your quit menu's title to it. In other words,
make it short, descriptive, and ask the Tornado group if any other
application has used that handle for itself. If it has, become a Tornado
programmer, and you will be allocated a unique hexadecimal number to be used
for every program you write.
This command reads the size of the pathnamed file, and allocates a suitable
slot for it (default=code size+32k). This slot may be increased by specifying
an increase in the first parameter. The file will be loaded multitaskingly
into its slot, and made into the CAO.
Note negative increases are permitted, and actively encouraged. Basic
programs proabably can do with 16k less, whereas C programs may need an extra
8k.
A related command to this is Tornado_File, the replacement for OS_File.
*TMess <mess>
Use:
This command displays a message in a Tornado window. It is given the
automatic default button of Ok, and is used to inform the user of things. The
command doesn't return until the user selects Ok.
This command actually uses SWI Tornado_Query.
*TError <mess>
Use:
This command displays an error in a Tornado window. It is given the automatic
default button of Cancel, and is used to inform the user of an error. The
command doesn't return, as the CAO is terminated when the user selects
Cancel.
This command actually uses SWI Tornado_Query.
*TStdError <mess no>
Use:
This command displays a standard error message in a Tornado window, as given
in Tornado_GiverError. It is given the automatic default button of Cancel,
and is used to inform the user of an error. The command doesn't return, as
the CAO is terminated when the user selects Cancel.
This command actually uses SWI Tornado_Error.
*TDeclareTypes <list of filetypes seperated by spaces>
Use:
This command is used from the !Boot file to declare to Tornado that this task
exists and that it can load directly the filetypes specified. Note that the
filetypes must be in hexadecimal and in 32bit quantities. Note also that
<Obey$Dir> should still point into the task's directory, as this path will be
stored.
****************************************************************************
****************************************************************************
Other notes:
This is the general format of a Tornado task's !Boot file:
| Boot file for View, the Tornado suite demo app
| Last updated: 09-06-1995
|
RMEnsure Tornado 0.50 Obey
TDeclareTypes 00000FFF 00000FFD
TIconsprites <Obey$Dir>.!Sprites
Simple and sweet eh? Note the direct implication of this is that if Tornado
fails to initialise, or the Tornado folder hasn't been seen, the icon for the
application in the filer window remains blank.
This is the general format of a Tornado task's !Run file:
| Run file for View, the Tornado demo app
| Last updated: 09-06-1995
|
| Make sure all the necessary system extensions are present
RMEnsure UtilityModule 2.00 Error 0 This program cannot be used with Arthur.
You need RISC-OS 2, or better
| Checks have already been made for WindowManager,Hourglass,SystemDevices,Fil
eSwitch & FileCore. Check for others.
RMEnsure Filer 1.00 Error 0 Please reinstall the Filer module before running
this again
RMEnsure SpriteExtend 0.20 Error 0 Please reinstall the SpriteExtend module b
efore running this again
RMEnsure Draw 1.01 Error 0 Please reinstall the Draw module before running th
is again
|
| Check for Tornado resources
RMEnsure Tornado 0.50 Error 0 You will need to install the Tornado resources
on your system before this program will run. You will find a copy of the Torn
ado resources on any major Acorn archive.
|
| Check for !System.
TCheckSystem
| Check for !Fonts, and outline font manager
TCheckFonts
|
| Wake up the hourglass, and load in our sprites
THourglass Load
Filer_Run <Obey$Dir>.!Boot
TIconsprites <Obey$Dir>.Sprites
Set View$Dir <Obey$Dir>
THourglass Process
|
| Load in and ensure all our needed modules
TRMEnsure ColourTrans 0.52 Colours colour translator module
TRMEnsure FPEmulator 2.80 FPEmulator floating-point maths chip emulator
TRMEnsureS FPEmulator 3.00 FPEmulator floating-point maths chip emulator
|
| Load in main RunImage, located according to !Config, while multitasking
TRun View %*0
See the star command summary above for explanation. Otherwise, note how
checks are made for system extensions in case they have been removed. You
_cannot_ assume /anything/ - everything must be checked for. If you want your
program to work on RO2, it shouldn't obviously be checking for modules that
don't exist on RO2. However, you can always assume that if Tornado is active,
the ColourTrans, WimpExt and DragASprite modules will also be present, but
you will still need to check for the SharedCLibrary. More than likely it will
be present too, as it is conceived quite a bit of Tornado will be eventually
written in C.
Note the producing of the error explaining why the app won't run and where
to get the Tornado resources from. This is to aid productivity - Aim 1 - so
the user doesn't have to ring his 'techie' collegues to get him to work it
out. He can do it himself/herself, and there will be a short summary of docs
supplied to say where you get Tornado from and how with every Tornado app.
Note the use of Filer_Run - this is added to RO2 by Tornado, as is
Filer_Boot and a few other misc RO3 commands. This is done by Brian
Brunswick's Bits module, although I don't have copyright permission to use it
yet.
****************************************************************************
****************************************************************************
Protocols:
Subtask protocol:
* Task calls Tornado_StartSubtask
* Tornado broadcasts Message_StartSubtask. If this message is acknowledged,
then a server is present and from now on it does all the communicating with
the parent task. Tornado's involvement is over.
* If the message isn't acknowledged, then Tornado does the default action,
which is thus:
* It installs handlers, and runs the subtask as the new CAO. The subtask in
turn should call Tornado_InitialiseSubtask within five seconds, or the CAO is
killed and it is returned to the app that the subtask run wasn't a subtask.
* When the subtask calls Tornado_InitialiseSubtask, Tornado also calls
Tornado_Initialise and Tornado_StartPreemption, discarding most of the
results it receives.
* From hence, the subtask can communicate with its parent via
Tornado_GetSTMessages and Tornado_SendSTMessages. It can also communicate
with any sibling subtasks by this method, taking care to address the message
appropriately. The subtask must send at least one message to its parent,
giving all of the processed data.
* Upon finishing the processing, the subtask calls
Tornado_ClosedownSubtask. This also calls Tornado_Closedown, and exits out of
the CAO.
Notes on subtasks:
You may note subtasks must pass the slot number AND the task handle of the
recipient of its messages. This is because when a subtask is running on a
remote processor, the task handle is the local server and the id slot number
is the process running on the remote server. Complicated? Wait till you see
the inter-server protocols ... :-)
Special subtasks:
Inline file translators. These set of subtasks perform the automatic
conversion of filetypes between each other, say between GIF and Sprite.
When the user tries to load a GIF file (say) into a Tornado app than can
only read Sprites, the GIF file is loaded under multitasking into tfs:, and
the appropriate convertor called (known by its name: a translator capable of
reading GIFs and converting them is called by the 32bit hexadecimal of the
GIF filetype (which I can't remember what it is right now).). When the
convertor finishes, the file is loaded into the task by Tornado (if the task
has this enabled).
The parameter format is this:
+00: ptr to list of reloc blocks that have been passed to you
In this list:
+00: ptr to reloc blk containing the file data
+04: filetype of input
+08: desired filetype of output. If the convertor can't translate into
this filetype, then the convertor should call another convertor that
might be able to (ie; call the convertor called the filetype this
convertor is spitting out)
+12: size of the block of data you wish to have returned when processing
on that block is complete. In other words, when the convertor has
output more than !+12 of converted data, return the block of
completed data to the parent. This allows the parent to (say)
display bits of translated GIF as it is processed. Note the block
of converted data returned may be bigger than !+12, and it is
possible that the converter doesn't support this, in which case it
will return the fully completed data at the end. Put -1 here if you
wish all the converted data to be returned at the end, and no
prefinishing data to be returned. It is emphasised that this method
should be supported as a convertor calling another convertor may be
processing its file alongside the constant return of already
processed data.
Restrictions on code in subtasks:
* Subtasks may NOT write to the vdu in any way, including vdu 7. However,
they may use Tornado_Query to display a message to the user.
* Subtasks may NOT get input from the user in any way more complex than
Tornado_Query, except through their parent.
* Subtasks may NOT run in any mode other than baseline USR.
* Subtasks may NOT install handlers.
* Subtasks may NOT call any code that runs for extended lengths of time
(ie; >1cs) in a mode other than USR. In other words, don't call a SWI if it's
going to take a while. Do it some other way.
* Subtasks may talk to subtasks not directly related to them, but be
careful with what you're doing, and make sure the subtask can function on its
own.
* Subtasks may not access memory outside their own domain, unless it's
been allocated to them by Tornado_Getblk
* Subtasks may not access any heap other than their own heap, referenced
using -1 in heap pointers. Tornado will take care of copying blocks between
the subtask's heap and the system heap of the parent task.
****************************************************************************
Graphics renderers protocol:
* Task calls Tornado_RenderFile.
* Tornado issues the service call Service_RenderFileRq. If this is
acknowledged, then the file has been rendered, and Tornado's involvement is
over. If this isn't acknowledged, then Tornado proceeds thus:
* Tornado_RenderFile returns with code indicating 'Please reschedule this
call' (ie; exit from the redraw/update handler immediately and issue a
Tornado_ForceRedraw). Tornado then begins a process which loads in
TRenderers:XXX (which is a module), where XXX is the 32bit hexadecimal of the
filetype the renderer is capable of rendering.
Notes on graphic renderers:
* Despite the name, graphic renderers can render anything, whether they be
bitmap, vector, movie or sound.
* Graphic renderers may load in libraries of code to assist them. Do this
in the Initialise entry, even though polling stops. You do not need to remove
them in finalise, as Tornado takes care of this for you.
* Render the file as quickly as you possibly can. You will not be preempted
during rendering, and polling is effectively stopped. You may use the
hourglass if absolutely necessary, but honestly you shouldn't be taking that
long. To this end, read the current graphics rectangle and use it to clip out
any unneccessary processing.
* Renderers are common resources. Use the standard message blocks, and
where information isn't given, use appropriate defaults. If necessary read
current system settings to aid you. Do NOT structure your renderer for one
application, as any application is entitled to use your renderer, as you are
entitled to use anyone else's renderer.
NOTE: This implies that any renderer you write is freeware. YOU MAY NOT
CLAIM ANY MONEY FOR WRITING IT, OTHER THAN VOLUNTARY AND UNFORCED PAYMENTS OF
GRATITUDE. YOUR RENDERER MUST FUNCTION FULLY, IE NOT PUT 'DEMO' ALL OVER IT
OR WORK TO LESS OF A STANDARD THAN A COMMERCIALLY SUPPLIED VERSION.
****************************************************************************
General OLE and hotlinking protocol:
OLE protocol:
* User starts OLE by standard action (yet to be decided). Task calls
Tornado_InitOLE.
* Tornado checks Tornado preferences to see if there is any preferred task
to send this filetype to, and if not starts from the start of the list of
currently loaded Tornado apps, checking to see if any of them can load this
filetype directly. If this can't, Tornado sees if any of the file converters
available can translate the file before OLE. If none can, the OLE is faulted.
If no currently loaded in app can be found to load in the file, then suitable
candidates are looked for on disc (known because of the TDeclareTypes in the
!Boot file), after which any non-Tornado apps loaded in are looked at, after
which a suitable Alias$@RunType_XXX is *Filer_Run-ed.
* Either way, one way or another, a suitable Tornado application is found.
If it is non-Tornado, see later. Depending on user prefs, hotlinking may also
be started. A message is returned through Tornado_Poll indicating where to
open the editor window, and with a copy of the file. The file is edited, with
the altered copy being sent back to the caller of Tornado_InitOLE (note that
this is recursive, ie; if the OLEd file is OLEd, then it echos back through
both copies, and any other copies linked to these), not that you'll see it if
the editor window is a pane of the caller's window. File is edited, editor
window closed and new file remains in the window.
* If Tornado OLE is not possible, the following is done: a DataOpen is
broadcast, pointing to a copy of the file in tfs:. An editor changes this
file, and upon saving it back to tfs:, Tornado notices and hotlinks the copy
back into the caller.
Hotlinking:
* The only essential difference here is that Tornado does this for the
task. The user saves a file out of the task, having selected the 'Hotlink'
option. If the user dragged it to disc, then after every edit the file is
saved to disc. If the user dragged it to another app, then the two files are
hotlinked: any alteration to one affects the other. It can be considered two
views of the same document, although both documents are entirely seperate.
****************************************************************************
****************************************************************************
Ok, that's about it. Any bug reports, inconsistencies, etc. to my address by
email.
Cheers,
Niall
Examples:
Paint and Ovation are two tornado apps. Ovation has a graphics frame. User
designs a sprite file in Paint, and saves it out as a GIF into Ovation:
* Tornado receives Dragfinishevent, determines the recipiant, and notices
that it can only load in sprites.
* The conversion is quashed (HOW?), and the file is copied into another
block. Ovation's Tornado_Poll exits out with -3,2. Ovation calls
Tornado_SubfileOp.
* Now the user decides they want to edit the file in the frame. Tornado
checks the list of filetypes that can be loaded by apps currently loaded in,
and passes -3,3 out of Paint's Tornado_Poll. Paint opens its editor window
exactly over the frame
Notes:
------
Add wimp message to indicate new fonts are available.
Add wimp message to indicate new renderers are available.
Add wimp message to indicate new filetypes and their owners are available.
Do seperate multitasker for Tornado apps, allowing memory outside their
domain to be protected from unauthorised access.
Hotkey to bring an application and its windows to the foreground, a la
Windows with Alt-Tab.
Large virtual desktop, with areas selectable by subject.
Filefinder.
Support for undos and undo code
Allow the RAM transfer of text files into the filename of a file.