[RFSFiles

 A ResourceFS file manager module.
]
[Display

 Use StrongED$Mode=Document for folded and coloured text in this manual. Remove the first character of every line to convert to plain text.
]
[Introduction

 There are several free applications that will create a ResourceFS module containing a selection of files to be registered in Resources. These have to be prepared in advance and require recompiling if any changes are made to the files. There is no way of selectively removing or replacing a file.

 The RiscOS command *AddApp can create a pseudo-application in 'Resources:$.Apps' that will call an application on disc, but it cannot do anything with files.

 As far as I know there is no utility for interactively adding and removing files in Resources, and that is what RFSFiles does.
]
[Getting started

 The RFSFiles module is loaded in the usual way, in a !Run file eg:

> RMEnsure RFSFiles 0.80 RMLoad System:Modules.RFSFiles

  or by double-clicking on it.

 When it is loaded you can add a file to Resources with, eg:

> *RFSAdd Resources.MyApp.Messages <MyApp$Dir>.Messages

  which adds the file 'Resources:$.Resources.MyApp.Messages'.

 A file can be removed with, eg:

> *RFSRemove Resources.MyApp.Messages

 Of course, only files added using RFSFiles can be removed.

 Alternatively, files can be added and removed by tasks using the corresponding SWI calls, which may provide more flexibility.
]
[How it works

 To add a file to Resources, RFSFiles first checks that the given filename is a valid file, which excludes image files and directories.

 It then claims space in the relocatable module area (RMA) for the Resource file data, which comprises a header and the contents of the file.

 It constructs the header, which includes the RFSName, and loads the file. Then it searches its list of added files, removes any existing file with the same RFSName, then registers the new file with ResourceFS.

 There is a flag that prevents a previous RFS file being replaced by a new version. This is useful for Resources files that are shared by several tasks, but which need to keep the same data addresses. The address returned by the SWI is that of the current data. See Appendix 'Shared resources'.

 There is a flag to set up a block of useful data, simplifying the access to sprites and messages files etc directly. See Appendix 'Special files'.

 To remove a file from Resources, RFSFiles searches its list of added files for the given RFSName. If this is found it deregisters the file with ResourceFS, unlinks it from the list and frees the RMA.

 A message protocol is defined so that a task can find out if a file is being used by another task before removing it.

 If RFSFiles is killed or reinitialised, all the files in its list are deregistered and the RMA freed.

 RFSFiles responds to service call &60, 'ResourceFSStarting', which is issued when the ResourceFS module is reloaded or reinitialised. This is needed so that files in the list can be re-registered with ResourceFS.

 There are regrettably few applications that take this call into account.

 RFSFiles integrates with my Basil module for sharing BASIC libraries.
]
[SWIs

{RFS_Add

(SWI &51480)

 Adds a file to the ResourceFS structure.

-On Entry

. R0 = pointer to the RFSName
. R1 = pointer to the full pathname of the file to add
. R2 =  0 - an existing RFS file will be replaced
.    else - will not be replaced
. R3 =  0 - no special initialisation of user block
.    else - user block initalised according to filetype

-On exit

. R0 = pointer to the user block
. R1 = pointer to the size word of the RFS file

-Use

 For the default action, with R2=0, a copy of the file named in R1 is loaded into the RMA and registered with the Resources filing system using the RFSName in R0. Any existing added file with the same RFSName is removed and the RMA freed.

 If R2 is not 0, the file does not get added if it would replace an existing RFS file maintained by the RFSFiles module. See Appendix 'Shared resources'.

 The address returned in R0 is to a 4-word block. It is used to return information and internally. See Appendix 'User block'.

 Possible error is 'Not a valid file'

-Related SWIs

 RFS_Remove

-Related commands

 *RFSAdd, *RFSRemove
}
{RFS_Remove

(SWI &51481)

 Removes a file from the ResourceFS structure.

-On Entry

. R0 = pointer to the RFSName

-On exit

. R0 preserved

-Use

 The file with the RFSName in R0 is deregistered from the Resources filing system and the RMA freed.

 Possible error is 'RFSName not found'

-Related SWIs

 RFS_Add

-Related commands

 *RFSAdd, *RFSRemove
}
{RFS_Data

(SWI &51482)

 Returns the address of the size word for any file in the ResourceFS structure.

-On Entry

. R0 = pointer to the RFSName of the file

-On exit

. R0 = pointer to the word after the file
. R1 = pointer to the size word of the RFS file

-Use

 The address returned in R0 is the user block for files added by RFSFiles. It is otherwise meaningless.

 The address returned in R1 is the one needed to treat a sprites file as a sprites area. It holds the value of filesize+4. See Appendix 'Special files'.

 Possible error is 'File <rfsname> not found' from the filer.

-Related SWIs

 None

-Related commands

 None
}
]
[Commands

{*RFSAdd

 Adds a file to the ResourceFS structure.

-Syntax

 *RFSAdd <rfsname> <filename> [-ensure -init]

-Parameters

. rfsname	the RFSName
. filename	the full pathname of the file to add to Resources
. -ensure	optional switch to prevent an existing RFS file being replaced
. -init		optional switch to initialise the RFS file

-Use

 This call is a straight interface to SWI "RFS_Add"

 A copy of the file named is loaded into the RMA and registered with the Resources filing system using the RFSName. Any existing added file with the same RFSName is removed and the RMA freed.

 If the '-ensure (-e)' switch is present an existing file is not replaced.

 If the '-init (-i)' switch is present the user block is initialised according to the filetype.

 Possible error is 'Not a valid file'

-Example

> *RFSAdd Resources.MyApp.Messages <MyApp$Dir>.Messages -i

 This adds the file 'Resources:$.Resources.MyApp.Messages' and initialises the user block.

-Related commands

 *RFSRemove

-Related SWIs

 RFS_Remove, RFS_Add
}
{*RFSRemove

 Removes a file from the ResourceFS structure.

-Syntax

 *RFSRemove <rfsname>

-Parameters

. rfsname	the RFSName

-Use

 This call is a straight interface to SWI "RFS_Remove"

 The file with the RFSName is deregistered from the Resources filing system and the RMA freed.

 No error is generated if the RFSFile does not exist.

-Example

> *RFSRemove Resources.MyApp.Messages

 This removes the file 'Resources:$.Resources.MyApp.Messages'.

-Related commands

 *RFSAdd

-Related SWIs

 RFS_Remove, RFS_Add
}
]
[Errors

{&814910, "Not a valid file"

 The object to be added to Resources is not a file or is not found.

 Image files will provoke this error as they cannot be opened in ResourceFS.
}
{&814911, "RFSName not found"

 The RFSName to be removed was not found in the list of files added by RFSFiles. The file may have been added by another module.
}
]
[Messages

{Message_AddingRFSFile (&51480)

 A task may want to add an RFSFile, but if it has already been added by another task, the old version will be replaced. Other tasks sharing the file may need to take this into account or object.

 Before adding a shared RFS file, broadcast this message with event code 18, to inform other tasks. They can then adjust their pointers or object to the file being replaced.

 The message block is:

 R1+16    &51480
 R1+20    RFSName of the file that will be added, control terminated

 Another task that wants to object should acknowledge the message by copying my_ref to your_ref and returning it with event code 19. Do not acknowledge a broadcast from your own task!

 Trap Wimp_Poll events with reason code 19, User_Message_Acknowledge, and this message number.

 If your_ref is unchanged (=0), the message has been returned by the Wimp and it is clear to add the RFS file. Otherwise, another task has objected.

 See Appendix 'Shared resources' for an example.
}
{Message_RemovingRFSFile (&51481)

 A task may want to remove an RFSFile, usually on quitting, but if other tasks are sharing the file they may need to take this into account or object.

 Before removing an shared RFS file, broadcast this message with event code 18, to check whether it is essential to another task.

 The message block is:

 R1+16    &51481
 R1+20    RFSName of the file that will be removed, control terminated

 Another task that wants to object should acknowledge the message by copying my_ref to your_ref and returning it with event code 19. Do not acknowledge a broadcast from your own task!

 Trap Wimp_Poll events with reason code 19, User_Message_Acknowledge, and this message number.

 If your_ref is unchanged (=0), the message has been returned by the Wimp and it is clear to remove the RFS file. Otherwise, another task has objected.

 See Appendix 'Shared resources' for an example.
}
]
[ResourceFS

 ResourcesFS is not a filing system in the same sense as ADFS, and does not have true directory objects. It has much in common with the RomIt system on the BBC B, and RomFS on Archimedes ROM/RAM cards.

 An RFSName (my own term) reads like a pathname, and the filer interprets it as such, putting all files in a pseudo root directory 'Resources:$'. Directories themselves cannot be created.

 Although it would be possible to add an image file to Resources, it cannot be opened as a directory, so RFSFiles excludes them.

 It is possible to include any characters in RFSNames, but the filer will not allow access to files with ambiguous names. RFSFiles does not check the validity of RFSNames.

  There appears to be an upper limit of 63 characters for the whole path of an RFSName, which is the same as RomFS. All other thing being alright the filer will open files with a leaf name up this maximum, but it would be wise to keep to the normal lengths.

 Sometime I will write the !RFSFiler application which will make an attempt to simulate Copy, Delete, Rename etc, and this will have appropriate checks.

 Adding and removing RFS files is slow, especially when a filer window is open for ResourceFS.

 There are some strict guidelines for the way files should be added to Resources, in order to avoid name clashes. The PRM 2-408 has details. Developers, including major ones, do not seem to abide by these, so care should be taken.

 RFSFiles itself avoids duplicate RFSNames, but ResourceFS uses the most recently registered file if there is a clash. This, of course, is the way to overwrite rom-resident files.

{RFSNames

 The RFSName of an RFS file is the part following the path 'Resources:$.', and only this is stored by ResourceFS.

 RFSFiles will accept an RFSName in all the usual filer forms, and will strip the path if it is present; eg, the following will add the
same file:

. Set Res$Dir Resources:$.Resources.MyDir
. Set Res$Path <Res$Dir>.
. Set MyDir Resources.MyDir
. SYS"RFS_Add",Resources.MyDir.Test,<My$Dir>.Test
. SYS"RFS_Add",<Res$Dir>.Test,<My$Dir>.Test
. SYS"RFS_Add",<MyDir>.Test,<My$Dir>.Test
. SYS"RFS_Add",Res:Test,<My$Dir>.Test

 Note that "Resources:" is identical to "Resources:$.", and a path variable used as pseudo-filesystem must start "Resources:"
}
]
[Special files

{Sprites files

 ResourceFS is designed so that Sprites files have the size word that is necessary to treat them as user sprite areas.

 No special initialisation is required, as SWI RFS_Add returns the address of the sprites area in R1, but it is best done so that the RFS type, etc, are setup:

> SYS"RFS_Add",rfsname$,filename$,,-1 TO ,Sprites%

 Sprites% is the handle for the sprites area.

 No action is needed when a Sprites file is removed.

 For a file already in Resources, whether added by RFSFiles or not, use:

> SYS"RFS_Data",rfsname$ TO ,Sprites%
}
{Messages files

 Messages files are usually opened automatically in the RMA, or loaded into a application's workspace. In either case a descriptor block and filename have to be held in the RMA by each task. RFSFiles by-passes the file handling of MessageTrans and sets up a pseudo-descriptor.

 When filetype=&FFF, SWI <RFS_Add> returns the address of the descriptor in the user block at R0:

> SYS"RFS_Add",rfsname$,filename$,,-1 TO Tokens%
> ...
> SYS"MessageTrans_Lookup",Tokens%,"test" TO ,,test$

 SWI <RFS_Remove> will remove the descriptor.

 For a file already in Resources which has been set up by RFSFiles, use:

> SYS"RFS_Data",rfsname TO Tokens%

 For other Messages files use:

> DIM Tokens% 3
> SYS"RFS_Data",rfsname TO ,!Tokens%
> Tokens%-=8

-MessageTrans file descriptors

 The descriptor created by MessageTrans is 4 words, and it is linked into a list:

. +00 pointer to the next descriptor in the list
. +04 where file data is held:
.  = 0 Application workspace
.  = 1 ResourceFS
.  = 2 RMA
.    ? others
. +08 pointer to the size word of the messages data
. +12 pointer to the name of the file

 It seems that only the pointer at +08 is used when tokens are found, by SWI MessageTrans_Lookup for example. The other data is for maintaining the list for universal use by programs.

 The pseudo-descriptor sets +00 to 0, +12 to the RFS type and copies the required information into +04 and +08.

 If this descriptor is used for token operations they seem to be alright, but it should not be used for SWIs MessageTrans _OpenFile, _CloseFile and _CopyError.

 Since this by-passes the MessageTrans module it should not affect the normal way of doing things by other programs, but use with care.
}
{Templates files

 Only one Templates file can be open at a time, so there is less scope for simplifying their use.

 I have judged the following feature has little practical use, and removed it in Version 0.92, saving a little time and code. There is no special initialisation, but I am thinking of doing a LoadTemplate on the first object.

 However, it is usual to find the required sizes of the template and workspace buffers before loading templates.

 When the filetype=&FEC, SWI RFS_Add will calculate the size of the largest template and the total data workspace required, returning them in the user block at R0+04 and R0+08. R0+00 points to the string "Resources:$.", which might be useful for opening the RFS template file:

> SYS"RFS_Add",rfsname$,filename$,,-1 TO ,user%
> SYS"OS_Module",6,,,user%!04 TO ,,buff%
> DIM data% user%!08
> last%=data%+user%!08
> name%=B%: REM B% is a global buffer
> next%=0
> SYS"Wimp_OpenTemplate",,$!user%+rfsname$
> REPEAT
>  $name%="*"
>  SYS"Wimp_LoadTemplate",,buff%,data%,last%,,name%,next% TO ,,,data%,,,,next%
>  SYS"Wimp_CreateWindow",,buff% TO handle%
>  FN@Let($name%,handle%):REM assign handle to variable
> UNTIL next%=0
> SYS"Wimp_CloseTemplate"
> SYS"OS_Module",7,,buff%

 SWI <RFS_Remove> will release the block.
}
{BASIC Library files

 Library files containing BASIC procedures and functions are usually loaded into an application's workspace using the LIBRARY or OVERLAY statements. Separate copies are taken by each task.

 My Basil module can be used to share libraries using the redundant INSTALL pointer; they are held in RMA but not visible to the user. RFSFiles can interact with Basil to provide an alternative way of sharing libraries. It should usually be used with the flag in R2 set, to prevent replacing libraries that are in use.

 When the filetype=&FFB, SWI <RFS_Add> will attempt to link to Basil and install the file to Basil's list, returning 0 in the user block at R1+00 if this was successful, or -1 if not:

> SYS"RFS_Add",rfsname$,filename$,-1,-1 TO user%
> IF !user% THEN LIBRARY filename$

 SWI <RFS_Remove> will remove the file from Basil's list.

 If Basil is reset or re-initialised the availability of the library is dealt with in a controllable way. See Appendix 'Service calls'.
}
]
[User block

 When a RFSFiles adds a file to ResourcesFS it puts a 4 word user block at the end. This is used to return information, and internally.

 The format of the block is:

. +00 depends on initialisation - default 0
. +04 depends on initialisation - default 0
. +08 depends on initialisation - default 0
. +12 RFS type:
.  = 0 no initialisation
.  = 1 Sprites as a user sprites area
.  = 2 Messages with descriptor block
.  = 3 Templates
.  = 4 Library of BASIC routines linked to Basil
]
[Shared resources

{General

 The ResourceFS structure provides a very useful way to store data in memory that can be shared among several applications. It has advantages over using the RMA directly because its file system gives a very handy way to get access to data, and for some purposes the data should be in a file format. It was surely designed with this in mind.

 A task that accesses data from ResourceFS files by opening and closing them within a Wimp poll is not concerned with the address of a ResourceFS file. However, ResourceFS files will often be left open, or the data accessed directly, so they should not move around in memory. This is a particular problem with shared files, which might be added or removed by any task.

 The simplest way to avoid replacing a file added by another task is to just use the flag word in R2, eg:

>  SYS"RFS_Add",rfsname$,filename$,-1

 Then never attempt to remove files. All applications that I know which add files to ResourcesFS do not remove them when quitting, so there will be nothing unusual.

 However, to allow tasks that share files to interact and to loose their data when it is finished with, you should use the methods outlined below.

 Because RFSFiles uses it own RMA and re-registers its files, no special action is needed if ResourceFS is reinitialised. This should mean that the problems of direct pointers into Messages files that Service Call &5E, Service_MessageFileClosed, is intended to cope with, should not occur. (I hope)
}
{Adding shared files

-NOT TESTED

 A task ought to find out if any other task is using an RFS file before replacing it with, eg:

> ...
> PROCRFS_Add("Resources.My.Sprites","<My$Dir>.!Sprites")
> ...
>
> DEF PROCRFS_Add(rfsname$,filename$)
>   B%!00=(LEN(filename$)+88) AND NOT 3
>   B%!12=0
>   B%!16=&51480
>   $(B%+20)=rfsname$   :REM max size of RFS file is 63
>   $(B%+84)=filename$  :REM max total message size is 255
>   SYS"Wimp_SendMessage",18,B%
> ENDPROC

This broadcasts Message_AddingRFSFile for the RFS file that is to be added or replaced, in the UserMessageRecorded form, expecting a reply.

It should then handle the reply messages in response to Wimp_Poll reason code 19 with, eg:

> DEF PROCPoll_UserMessageAcknowledge
>  CASE B%!16 OF
>  ...
>  WHEN &51480
>   PROCRFS_Adding($(B%+20),$(B%+84),B%!12<>0)
>  ...
> ENDPROC

> DEF PROCRFS_Adding(rfsname$,filename$,protect%)
>  SYS"RFS_Add",rfsname$,filename$,protect%,-1 TO user%
>  CASE user%!12 OF
>  WHEN 1
>   Sprites%=user%!08
>  WHEN 2
>   Tokens%=user%
>  WHEN 3
>   PROCWindow_Load(user%!00,user%!04)
>  WHEN 4
>   IF !user% THEN LIBRARY filename$
>  ENDCASE
> ENDPROC

. B% is the address of a 256 byte block.

 This sets protect%=FALSE if the message is returned unaltered from the Wimp (B%!12=0), in which case it is safe to add the file. Otherwise, your_ref will have been changed from 0 by a task wanting to prevent replacement so protect%=TRUE.

 The parameter R3=-1 and the CASE structure are only needed if you want initalisation of the user data. RFS_Add returns the user block whether the file is replaced or not. The decoding is by the RFS types.

A task wanting to prevent an RFS file being replaced should handle messages in response to Wimp_Poll reason code 18 (usually identical to reason code 17) with, eg:

> DEF PROCPoll_UserMessage
>  CASE B%!16 OF
>  ...
>  WHEN &51480
>   IF B%!04<>Task% THEN PROCMessage_AddingRFSFile
>  ...
> ENDPROC

> DEF PROCMessage_AddingRFSFile
>  CASE $(B%+20) OF
>  WHEN "Resources.MyApps.Sprites","Resources.MyApps.Messages"
>   B%!12=B%!08
>   SYS"Wimp_SendMessage",19,B%,B!%04
>  ENDCASE
> ENDPROC

. Task% is the task handle returned by SWI Wimp_Initialise.

 If the message originated from another task and the RFS file is one it wants to keep, it returns the message with the your_ref field set to the value in my_ref. Otherwise no action is taken and the Wimp will return the message unaltered to the originating task.

 Note that PROCMessage_AddingRFSFile and PROCMessage_RemovingRFSFile, below, are identical if the only action is to object..
}
{Removing shared files

-NOT TESTED

 A task must find out if any other task is using an RFS file before removing it with, eg:

> ...
> PROCRFS_Remove("Resources.MyApps.Sprites")
> ...
>
> DEF PROCRFS_Remove(rfsname$)
>  B%!00=(LEN(rfsname$)+24) AND NOT 3
>  B%!12=0
>  B%!16=&51481
>  $(B%+20)=rfsname$
>  SYS"Wimp_SendMessage",18,B%
> ENDPROC

This broadcasts Message_RemovingRFSFile for the RFS file that is to be removed in the UserMessageRecorded form, expecting a reply.

It should then handle the reply messages in response to Wimp_Poll reason code 19 with, eg:

> DEF PROCPoll_UserMessageAcknowledge
>  CASE B%!16 OF
>  ...
>  WHEN &51481
>   IF B%!12=0 SYS"RFS_Remove",$(B%+20)
>  ...
> ENDPROC

. B% is the address of a 256 byte block.

 This checks whether the message is returned unaltered from the Wimp (B%!12=0), in which case it is safe to remove the file. Otherwise, your_ref will have been changed from 0 by a task wanting to prevent removal, and no action is taken.

A task wanting to prevent an RFS file being removed should handle messages in response to Wimp_Poll reason code 18 (usually identical to reason code 17) with, eg:

> DEF PROCPoll_UserMessage
>  CASE B%!16 OF
>  ...
>  WHEN &51481
>   IF B%!04<>Task% THEN PROCMessage_RemovingRFSFile
>  ...
> ENDPROC

> DEF PROCMessage_RemovingRFSFile
>  CASE $(B%+20) OF
>  WHEN "Resources.MyApps.Sprites","Resources.MyApps.Messages"
>   B%!12=B%!08
>   SYS"Wimp_SendMessage",19,B%,B!%04
>  ENDCASE
> ENDPROC

. Task% is the task handle returned by SWI Wimp_Initialise.

 If the message originated from another task and the RFS file is one it wants to keep, it returns the message with the your_ref field set to the value in my_ref. Otherwise no action is taken and the Wimp will return the message unaltered to the originating task.

 Note that PROCMessage_RemovingRFSFile and PROCMessage_AddingRFSFile, above, are identical if the only action is to object.
}
]
[Service calls

 RFSFiles responds to these service calls.

{BasilResetting

 RFSFiles responds to service call 'BasilResetting' when it has any BASIC library files initialised to be linked to the Basil module's installed list.

 Libraries are removed from the list, but remain in memory at the same address. This means that BASIC routines that have already been used by a program will still be found and they will not crash because the routines have disappeared. However, if a new routine is called there will be the controllable 'No such function/procedure' error.
}
{BasilStarting

 RFSFiles responds to service call 'BasilStarting' when it has any BASIC library files initialised to be linked to the Basil module's installed list.

 Libraries are re-linked to the list, and can be used as before. Note that if the initialisation had failed because Basil was not present, the library will not then link after this call.
}
{ResourceFSStarting

 RFSFiles responds to service call 'ResourceFSStarting' to re-register all the files in its list. Note that this call is going to be very unusual, and most (all?) other users of ResourceFS seem to ignore it, so they are likely to crash anyway!
}
]
[History

 Some years ago I produced a crude ResourceFS module creator that worked to my own specification, as I could not get on with any of the several other such PD programs. Then, as part of my development of Basil, I played around with this code in order to put BASIC libraries into Resources and get their addresses, so that they could be installed in BASIC programs.

 I abandoned this method for Basil, but realised that the code could be developed to allow files to be added to Resources interactively using a *command. This has become RFSFiles.

{Version 0.01 (22-Jan-98)

 This was crudely put together to prove the concept and had one command, *RFSAdd.
}
{Version 0.01-0.04 (Jan 98)

 The original was refined, *RFSRemove added, corrsponding SWIs added, and service call ResourceFSStarting handled. *RFSAdd was changed to remove existing files with same name.
}
{Version 0.10beta (31-Jan-98)

 This is the previous code with basic supporting documents and application. It is released to the public with no warranty.

 The SWI chunk used is in the user range and may conflict with other modules.
}
{Version 0.20beta (02-Feb-98)

 The code has been more thoroughly checked and small revisions made to gain efficiency and cope with some remote possibilties.

 Documentation is more complete, but a StrongHelp manual is pending.

 An Acorn SWI chunk allocation is used.
}
{Version 0.21beta (05-Feb-98)

 The address returned by SWI RFS_Add is now the size word before the data. This is the address needed to treat a sprite file as a sprite area.
}
{Version 0.30beta (08-Feb-98)

 Error numbers are now from an allocated chunk.

 After using RFSFiles in a current project, I have added facilities to help with the use of RFSFiles as a handler of shared resources:

 *WARNING*
 The syntax of *RFSAdd and SWI RFS_Add have been changed so that the RFSName is the first parameter. This is for conceptual reasons (?).

 SWI RFS_Add can be given a parameter to indicate that an existing RFS file should not be replaced by a new one. This is to preserve addresses of shared data.

 SWI RFS_Data returns the data address of any file in Resources.
}
{Version 0.32beta (17-Feb-98)

 A message protocol is defined so that tasks sharing resources can check whether an RFS file is being used before replacing it.

 SWI RFS_Add now returns the address of a 4 word block that is initialised to help use Messages files. Help with other special files will follow.

 There is a StrongHelp manual.
}
{Version 0.34beta (23-Feb-98)

 There is a minor change to the syntax of SWI RFS_Add; all information is returned in the user block.

 SWI RFS_Add can now initilise user data for Sprites, Messages, Templates and BASIC Library files.

 The error number in the code was incorrect, and has been changed.
}
{Versions 0.40-0.70 (Mar-May 98)

 While developing my 'Basilisk' object-oriented BASIC programming aid I changed the facilites of RFSFiles several times to match my needs. Version 0.80 reflects my final decisions.
}
{Version 0.80beta (09-Jun-98)

 SWI RFS_Add has changed slightly again, returning the user block and file address in separate registers. It now correctly returns this data when the file is not replaced.

 SWI RFS_Data returns the same data as SWI RFS_Add.

 *RFSAdd can be used with the switches in SWI RFS_Add.

 *RFSRemove does not give an error if the RFS file does not exist.

 The interaction with 'Basil' is handled fully and should be much more difficult to fool.
}
{Version 0.82beta (14-Jun-98)

 The SWIs, as well as the *commands, now use GSTrans on RFS names, which means that system variables can be included in them.

 Some minor errors which crept into the in the documentation have been corrected.
}
{Version 0.90beta (26-Jun-98)

 RFSNames are now fully canonicalised, so they can be specified as before, or with a full path, including the use of pseudo-filesystem paths from path variables starting "Resources:".
}
{Version 0.92beta (15-Jul-98)

 Bug: Using the -ensure flag on a new file cause the RMA to report it had run out of space!.

 Bug: Errors were not correctly passed back to calling task from the canonicalisation routine, preventing use of the 'X' form of SWI's.

 Initialisation of Templates files now does nothing; it was not a practical feature.
}
{Version 0.93beta (29 Aug 2000)

 This only fixes a bug in the unknown SWI routine.
}
{Version 0.94beta (21 Mar 2001)

 This is only a reorganization of the StrongHelp manual.
}
{Version 0.95 (31 Mar 2004)

 32-bit compatible version
}
{Version 0.96 (22 May 2015)

 I decided to resurrect RFSFile after contemplating the resurrection of RISC OS with the Raspberry Pi etc. This was in part stimulated by the problem of using throwback with libraries.

 The source has been re-written in my current style and various minor changes made to the code and the documentation.
}
{Version 0.97 (29 Mar 2020)

 Bug:A missing ALIGN in the data block provokes an error with the latest ARM processors that cannot ignore unaligned loads.
}
]
[Copyright

 RFSFiles is written by Steve Drain:

> http://www.kappa.me.uk
> mailto:steve@kappa.me.uk

 It is released under a Modified BSD Licence:

 Copyright (c) 2020, Steve Drain, Kappa

 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

 *	Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

 This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright holder or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
]
