/---------------------------------------\
|                FednetCmp              |
| Fednet file compression/decompression |
|       Christopher Bazley, 2001       |
|      Version 1.70 (01 Aug 2022)       |
\---------------------------------------/
N.B. This text is best viewed at a display width of 77 columns.

-----------------------------------------------------------------------------
 1   Introduction and Purpose
     ========================

  This application handles files compressed with an algorithm used in old
4th Dimension and Fednet games such as 'Chocks Away', 'Stunt Racer 2000' and
'Star Fighter 3000'. Game files may be decompressed and compressed, singly
or in batches, using a simple desktop interface. FednetCmp is not likely to
be of general use, unless you fancy it as an odd-ball replacement for
Acorn's 'Squash'.

  In 'Chocks Away' and 'Stunt Racer 2000' the contents of compressed files
were extracted by a module called 'DeComp' (1993 The fourth dimension)
which provides a single command *CLoad - analogous to the standard command
*Load. In 'Star Fighter 3000' a similar module is supplied encrypted but it
is named 'FDComp' ( Gordon Key 1994) and its command is *LComp.

  Apart from an unbalanced stack bug having been fixed (when SWI OS_Find
returns an error) the two modules appear to be virtually identical. Actually
'FDComp' doesn't behave much better in the same situation because *LComp
returns with V set but R0 still pointing to the command tail rather than an
error block. It seems safe to assume that G.K. wrote both modules.

  Useless fact : if Star Fighter 3000 were not mostly compressed then it
would occupy 5.24Mb (7 DD floppy discs) rather than 1.13Mb (2 DD floppy
discs).

-----------------------------------------------------------------------------
2   Requirements
    ============

   RISC OS 3.10 or better.
   A !System directory (which must have been 'seen' by the Filer).
   The Toolbox modules (in !System or in ROM with RISC OS 3.6 and later).

  If any of the above facilities are unavailable then the program will fail
to load, with an error message describing the problem.

-----------------------------------------------------------------------------
3   Quick Guide
    ===========

  I have implemented an interface that is similar to Acorn's 'Squash', so
hopefully everyone will be familiar with this: Drag input files to the
iconbar icon and a savebox will pop up for you to set the output destination
for the operation. Interactive help is fully supported.

  FednetCmp will compress files dropped on its icon, or decompress Fednet-
typed (compressed) files dropped on it. An hourglass may appear whilst large
files are processed, displaying the percentage done. You can abort the
operation at any time by pressing the ESCAPE key.

  When compressing files, you may choose the filetype (from a list of known
Fednet types) to give the output data. This facility is incorporated for my
own convenience, when generating 'Star Fighter 3000' game files. If you are
just going to use FednetCmp as a compressor for arbitrary data, then it
would be rather anti-social to generate files that claim to be specific types
of game data. You should therefore use the general type &154.

  All data decompressed by FednetCmp will be given the generic file type &FFD
('Data') because the original file type is not preserved in a compressed
file. Unlike the Squash application, FednetCmp does not prepend a header
containing such information, since Fednet did not do so and FednetCmp is
designed for reading and creating game files.

  Drag a directory to the iconbar icon to start a batch operation: FednetCmp
will scan the directory and all subdirectories of it, processing any relevant
files encountered. When setting up a directory scan (using the 'Output to'
savebox), you must choose the mode of operation:

  If 'Decompress files' is set, then any Fednet-typed files encountered (see
list below) will be decompressed to plain Data files. If 'Compress files' is
set, then all non-Fednet files will be compressed, and given the Fednet
filetype specified. Like in the 'Compress as' savebox, a pop-up list allows
you to choose the filetype to give output files.

Other features:

  A 'Windows' submenu from the iconbar menu lists all open windows. Clicking
on this will bring the selected window to the front of the window stack, or
click SELECT on the FednetCmp icon to bring all windows to the front.

  The 'Multiple saveboxes' option on the iconbar menu controls whether to
allow multiple saveboxes, or only one at a time. You must enable this
option to meaningfully support dragging of multi-object selections from a
directory display. When not ticked (default state), opening a new savebox
will automatically close any existing savebox.

-----------------------------------------------------------------------------
4   Command line options
    ====================

  A few obscure options are only available as parameters to the command that
invokes the application's !RunImage. Parameters may be specified in any
order and are not case sensitive.

  The switch '-multi' will enable the 'Multiple saveboxes' option (see above)
on start up. This is the only way to change the default setting.

  The switch '-quit' will cause the application to quit immediately after
having decompressed any files specified on the command line. This is
intended for use with Alias$@RunType so that files may be decompressed
without the application taking up permanent residence on the iconbar (though
this is not the default behaviour). In this mode, FednetCmp will not yield to
other tasks until it has finished.

  The parameter '-timeslice' (followed by a decimal number) sets the
granularity of task switching, in centiseconds. It is analogous to
TaskWindow's '-nice' parameter: High values will cause FednetCmp to 'hog'
the computer, making the desktop unresponsive. Low values will make
multitasking very smooth but FednetCmp will run at lower priority compared
to other tasks. The default value of 10cs means that FednetCmp should
compete on a level playing field with any TaskWindows running.

  Any other parameters not preceded by '-' will be treated as paths of files
to be decompressed in-situ.

-----------------------------------------------------------------------------
5   Compression format
    ==================

  The first 4 bytes of a compressed file give the expected size of the data
when decompressed, as a 32 bit signed little-endian integer. Gordon Key's file
decompression module 'FDComp', which is presumably normative, rejects input
files where the top bit of the fourth byte is set (i.e. negative values).

  Thereafter, the compressed data consists of tightly packed groups of 1, 8
or 9 bits without any padding between them or alignment with byte boundaries.
A decompressor must deal with two main types of chunk: The first (load a
byte) consists of 1+8 bits, and the second (copy data within output buffer)
consists of 1+9+8 or 1+9+9 bits.

The type of each chunk is determined by whether its first bit is set:

0.   Decode the next 8 bits of the input file (0-255) and write them as a
   byte at the current output position. The fact that this directive requires
   9 bits to represent 8 bits of information explains the inflation that can
   occur when attempting to compress random data.

1.   Decode the next 9 bits of the input file, which give an offset (0-511)
   within the data already decompressed, relative to a point 512 bytes behind
   the current output position. If this offset is greater than or equal to
   256 (i.e. within the last 256 bytes written) then decode the next 8 bits,
   which give the number of bytes (0-255) to be copied to the current output
   position. Otherwise, the next 9 bits give the number of bytes to be copied
   (0-511).

    If the read pointer is before the start of the output buffer then zeros
  should be written at the output position until it becomes valid again. This
  is a legitimate method of initialising areas of memory with zeros.

    A quirk of 'FDComp' is that least 1 byte is always written. That is
  probably a bug, although a well-written compressor should not insert
  directives to copy 0 bytes anyway. Note also that it isn't possible to
  replicate the whole of the preceding 512 bytes in one operation.

-----------------------------------------------------------------------------
6   File types
    ==========

  The file types used by Fednet are highly non-official. Presumably they
thought that this wouldn't matter for files used internally in games. I
already know of some clashes (none serious) with other filetypes, but I
can't really alter them retrospectively.

  There follows a list of the known filetypes that a Fednet compressed file
may have. Beware that files of type &400 are not necessarily compressed
because the 'Stunt Racer 2000' track editor saves non-compressed tracks with
this type! This is one reason why FednetCmp only claims type &154, apart
from the fact that editors exist for most of the other types.

Type  Name         Contents
----  ----         --------
&154  Fednet   (1) SF3000 or SR2000 compressed code or data.
&300  SFObjGfx (4) SF3000 compressed polygonal objects set.
&400  SFBasMap (4) SF3000 compressed ground map, or
                   SR2000 track (not necessarily compressed).
&402  SFBasObj (4) SF3000 compressed objects map.
&401  SFOvrMap (4) SF3000 compressed ground map overlay, or
                   SR2000 rec file.
&403  SFOvrObj (4) SF3000 compressed objects map overlay.
&404  SFSkyCol (2) SF3000 compressed sky colours.
&405  SFMissn  (4) SF3000 compressed mission data.
&406  SFSkyPic (3) SF3000 compressed sky pictures set.
&407  SFMapGfx (5) SF3000 compressed map tile graphics set.
&408  SFMapAni (4) SF3000 compressed ground map animations.
&FFD  Data         'Chocks Away' or SR2000 compressed code or data
                    (not easily identifiable).

1) Only named if !FednetCmp or !SFcolours has been 'seen' by the Filer.
2) Only named if !SFskyedit has been 'seen' by the Filer.
3) Only named if !SFtoSpr has been 'seen' by the Filer.
4) Only named if !SFeditor has been 'seen' by the Filer.
5) Only named if !SFeditor or !SFtoSpr has been 'seen' by the Filer.

-----------------------------------------------------------------------------
7   Program history
    ===============

1.00 (19th June 2001) -------------------------------------------------------
   First version. Looks remarkably similar to SFtoSpr, doesn't it?

1.10 (8th July 2001) --------------------------------------------------------
   Added "Windows" submenu from iconbar, to allow open dialogues and scan
    progress windows to be brought to the front of the window stack.
   If a dialogue is already open for a file then attempting to load it
    again will cause this to be shown.

1.11 (15th August 2001) -----------------------------------------------------
   Fixed problem where Savebox would be shown, but not respond to drag of
    icon.
   Changes to ViewsMenu to avoid errors removing premature (file double-
    click launched app) dialogue from menu.
   Fixed progress window bug where wrong path shown with "Reading" message.
   Window names on list now include truncated not full filepaths.
   Increased verbosity and downgraded seriousness of errors on load/save.
   Error reporting is now slightly prettier for RISC OS 3.5+ computers.
   No longer lies about needing SpriteExtend 0.99.
   If app launched to load double-clicked file, errors cause it to quit
    again.
   Changed text/label widths in ProgInfo window to fit big fonts.

1.12 (17th August 2001) -----------------------------------------------------
   Fixed bugs causing progress window to open in a zombified state - bad
    string causing OS_GBPB error, in conjunction with failure to expand
    window to show error.

1.13 (19th September 2001) --------------------------------------------------
   Fixed bug in Loader component regarding multi-stage RAM transfers.

1.20 (22nd December 2001) ---------------------------------------------------
   Total overhaul of sourcecode from the ground up, with many improvements
    and fixes not really externally visible.
   Now uses flexlib to buffer data in memory. The effect of this is that
    having expanded to buffer data, the Wimpslot now reduces again when the
    memory is freed.
   Double-clicks in a Filer window on compressed files of type 'Fednet'
    (&154) will now instantly decompress them to Data files.
   Redesigned saveboxes along more minimalist lines.
   Now defers removal of entries from 'Windows' menu until such time as it
    is closed. This prevents potentially serious problems when scan progress
    windows are closing.
   Saveboxes now pop-up neatly over iconbar rather than on top of it.
   Double-clicking on a file of type 'Fednet' now instantly decompresses it
    (as with a 'Squash' file) rather than bringing up a savebox.
   Fixed bug in Loader component with !Scrap transfer from other apps,
    where suggested leafname was shorter than "<Wimp$Scrap>".
   General improvements to directory scanning code, including elimination
    of depth limit and reduced memory usage.

1.21 (4th January 2002) -----------------------------------------------------
   Fixed bug where first word was lost, when saving decompressed data to
    another application via RAM transfer.

1.22 (17th March 2002) ------------------------------------------------------
   No longer null polls when all progress windows are idle (e.g. paused or
    error).
   Added warning dialogue to confirm that user wants to quit with
    operations still in progress.
   Added '-multi' and '-quit' command line options, as for SFtoSpr. These
    control whether we quit after parsing command line, and the default
    setting of the multiple-saveboxes flag.

1.23 (11th November 2002) ---------------------------------------------------
   Uses Wimp_PollIdle rather than Wimp_Poll to limit frequency of null
    polling.
   Improvements to some widely used error-checking macros allowed code size
    to be reduced together with increased efficiency.
   Added signal handler.
   Minor corrections to messages / interactive help.
   Corrected mistake in !Run file where the CallASWI module was not being
    loaded on RISC OS 3.6, despite being required on all OSes prior to 3.7.
   Simultaneous directory scans now share a single OS_GBPB buffer, thus
    using less memory.
   Recompiled using the official Castle release of 32-bit Acorn C/C++.

1.23b (14th November 2002) --------------------------------------------------
   Removed signal handler - the new Shared C Library does a much better job
    of displaying signal errors from Wimp tasks than previously.

1.30 (15th December 2002) ---------------------------------------------------
   The compression and decompression code has been incorporated directly
    into the front-end application, which no longer invokes external modules.
    This allowed improvement to the quality of multi-tasking and a reduction
    in overall code size.
   In particular, the granularity of multi-tasking no longer depends upon
    the size of the files being processed. Instead, file operations are
    effectively pre-empted after a certain time has elapsed.
   A round-robin system is used so that the amount of work done per wimp
    poll no longer varies according to the number of simultaneous batch
    operations.
   For file-to-file operations a progress bar shows the state of the
    current operation. This replaces the (fairly useless) 'files scanned'
    count.
   Quick in-situ file decompression (e.g. double-click on a compressed
    file) also multi-tasks smoothly, using the same code as that for batch
    operations.
   Non-interactive load and save operations (e.g. with an hourglass) now
    display the percentage done, and may be safely aborted by the user
    pressing ESCAPE.

1.40 (9th June 2003) --------------------------------------------------------
   Moved the "Help" entry to the top of iconbar menu, as suggested by
    Castle.
   More sensible response to error on Toolbox_Initialise (doesn't rely on
    messages file, which isn't open).
   All dialogue boxes can now be reset by ADJUST-clicking on the 'Cancel'
    button.
   Gave custom saveboxes back-icons, as they're not ever transient.
   Now creates root output directory before replying to SaveAs_SaveToFile
    event, just to be nice to whoever is on the other end.
   Integrates much better with the pinboard - any iconised window icon is
    removed when that window is re-opened independently by the application.
   Now uses the Toolbox's standard 'Quit' dbox object - hence the DCS
    module is now a requirement. The default action is now 'Cancel' rather
   than 'Quit'.
   When closed, transient dialogue boxes that claim the input focus now
    restore it to the previous owner. Implementing this required special code
    to work around deficiencies in the Toolbox and/or Window Manager.
   Added work-around for a Toolbox bug that causes non-delivery of
    Window_HasBeenHidden events for windows opened with Wimp_CreateMenu
    semantics, when OS 4 !Help is running. This bug could cause permanent
    suspension of all running threads after the 'Quit' dbox had been opened!
   Parsing of command line parameters is no longer case sensitive.
   Added new command line option '-timeslice' to control the granularity of
    multi-tasking.
   No longer uses Wimp_PollIdle. Programs running under TaskWindow poll as
    often as possible so why shouldn't we?
   Fixed the command line '-quit' option, which had effectively been broken
    by the introduction of multi-tasking in-situ file decompression. (The
    application always quit before any work had been done!)
   Where possible reports file errors using the OS error messages rather
    than custom ones, for example 'The disc has no more available space'
    rather than 'Error writing to...'
   File paths are now canonicalised before being displayed or compared
    (i.e. "IDEFS::Tamzin.$.!Boot.Choices" rather than "<Choices$Write>")

1.41 (19th August 2003) -----------------------------------------------------
   Even if upon receipt of a PreQuit message we do not object to dying, we
    now wait for the Quit message rather than dying prematurely.
   During batch operations, 'image' files (which can be accessed as
    directories) are now treated as plain data rather than being ignored
    completely.
   Where possible, changed to use SWIs instead of Star Commands for file
    access. This is faster and also reduces code size.
   Now demands version 5.43 of the shared C library, since this is the
    earliest version documented as supporting C99 functions (some of which
    are used).
   Formatted the manual text for a fixed-width 77 column display (Zap's
    default).

1.42 (5th September 2003) ---------------------------------------------------
   Changed to an alternative method of loading and saving flex blocks, in
    order to combat the appearance of 'Not enough memory for I/O buffer'
    errors while heap expansion is disabled.
   Minor changes to filetypes documentation to reflect the new name decided
    upon for type &407.

1.43 (8th September 2003) ---------------------------------------------------
   Fixed bug a introduced into the loading of uncompressed data in v1.42.
    On encountering EOF the last bit of data was discarded, which meant that
    up to 64 bytes at the end of the loaded file would be garbage.

13th September 2003
   Re-released with source code under the GNU General Public Licence.

1.44 (23rd October 2003) ----------------------------------------------------
   Internal changes.

1.45 (7th November 2003) ----------------------------------------------------
   On shutdown, no longer quits immediately that 'Quit' is selected from
    the quit confirm dbox. Instead all batch operations are aborted and we
    wait for a Quit message (analogous to what Paint, Edit & Draw do).
   Now restarts desktop shutdown by sending a keypress event to the task
    that sent us the PreQuit message (as recommended by the PRM), instead of
    using SWI Wimp_ProcessKey.

1.46 (1st March 2004) -------------------------------------------------------
   Re-compiled with release 9 of CBLibrary.

1.47 (7th November 2004) ----------------------------------------------------
   Now uses dedicated OS_GBPB veneer provided by Acorn library kernel, which
    is faster than generic SWI calling methods and type-safe.
   Made changes necessary and/or desirable to compile with release 12 of
    CBLibrary.
   We no longer restore the initial savebox filename when a user clicks
    ADJUST on the Cancel button, because by rights this should be handled by
    the SaveAs module (which will hopefully be fixed, as Scale has been).
   Added system variables to !Boot file for Castle's proposed help system.

1.48 (19th November 2004) ---------------------------------------------------
   English default messages are now used to report flex memory errors
    because a bug in the library prevents use of our messages file.

1.49 (14 May 2005) ----------------------------------------------------------
   Many internal changes - notably to processing of Toolbox events (now use
    our own event numbers) and tidying up upon object deletion. Code size
    has actually shrunk compared with previous versions!
   An error will now be reported if any of the files specified on the
    command line are not found.
   Now uses global 'BadParm' message instead of similar hard-wired English
    message.

1.50 (05 Aug 2005) ----------------------------------------------------------
   Fixed bug where insufficient memory upon initialisation of a batch
    operation would go unreported.
   Updated ResFind from version 2.01b to latest version 2.12 (improved
    support for truncated country names & long paths).
   Built with release 18 of CBLibrary (which it requires).
   No longer requires the new (C99, APCS-32) shared C library or a version
    of the floating point emulator that supports LFM/SFM instructions.

1.51 (11 Aug 2005) ----------------------------------------------------------
   Moved definition of system variables for Castle's proposed help system
    from !Boot file to Obey file in subdirectory for relevant country (to
    allow internationalisation).
   !Run file no longer invokes ResFind a second time, having executed !Boot
    (which does so).

1.52 (02 Feb 2006) ----------------------------------------------------------
   General tidy up of excessive brackets and casting in source code.
   Expanded manual text with information about 'Chocks Away' and the two
    modules that this application is designed to emulate. Also updated
    section on file types (many of which have been renamed).
   Updated string set in Window template "FednetWin" to use new names for
    file types.
   Updated our LoaderPreFilter function for compatibility with release 19
    of CBlibrary.

1.53 (09 Nov 2006) ----------------------------------------------------------
   Added a 'Web' button to the 'About this program' window. This requires
    a later version of the ProgInfo module.
   No longer neglects to deregister any event handlers already registered
    for a save dialogue box or scan progress window, if an error occurs
    during initialisation.
   Fixed memory leaks caused by the fact that event handlers registered
    for the Window object underlying a SaveAs object were never deregistered.
   Updated source code for compatibility with release 24 of CBLibrary.
   Experimentally removed dependence on CBLibrary's Loader module.
   Moved the naming of file type &154 into the country-specific Obey file
    'FednetCmpRes:SysVars'.

1.54 (18 Nov 2006) ----------------------------------------------------------
   No significant changes.

1.55 (25 Jun 2009) ----------------------------------------------------------
   Minor changes to messages.
   Minor changes to code for handling files dragged from other applications.
   Documented the decompression algorithm here.

1.56 (15 Sep 2009) ----------------------------------------------------------
   All command-line arguments are now parsed together after initialisation,
    rather than only the input file names. Syntax checking is more stringent:
    switches must now be specified before file names.
   Now shows any existing save dialogue box instead of creating a new one,
    if the same file or directory icon is dragged to FednetCmp again.
   Now reports an error if the user drags a directory from another
    application to FednetCmp's icon on the iconbar (which isn't supported).
   Rewrote some of the interactive help messages.
   A binary search is now used to find which initialisation function to call
    (if any) for the template named in a Toolbox_ObjectAutoCreated event.
   Reduced duplication between the code used for dealing with objects
    dragged from a directory display and from another application's save
    dialogue box.
   Simplified the implementation of RAM transfer: it isn't necessary to
    disable budging of the flex heap (which prevents expansion of the regular
    heap) between delivery of one SaveAs_FillBuffer event and the next, or
    the final SaveAs_SaveCompleted.
   Errors when dealing with activation of the 'Quit' button in the query
    dialogue box displayed during desktop shutdown are now treated as fatal.
   Utilises new CBLibrary functions instead of custom code to set file
    types, get the screen size, show and hide gadgets, fade and unfade
    gadgets.
   Stopped using reserved identifiers (those starting with an underscore
    followed by a capital letter).
   Reduced the decompressed executable size from 52688 to 51224 bytes by
    substituting data for code and hand-optimising.

1.57 (28 Jun 2010) ----------------------------------------------------------
   Specified the appropriate switches to prevent the Norcroft C compiler
    from generating unaligned memory accesses incompatible with ARM v6 and
    later (for RISC OS on BeagleBoard).
   Expunged references to type and function names deprecated in release 34
    of CBLibrary.
   Gave names to many 'magic' values (numeric constants). Anonymous
    enumerations are now used in preference to macro definitions.
   Removed references to CBLibrary header file "TboxBugs.h". Kept the
    work-arounds for non-delivery of Quit_DialogueCompleted events and
    failure to reassign input focus after closing a transient window. I
    also enabled some existing code to record the filetype selected in a
    savebox, in case the Toolbox doesn't hide it after a save triggered by
    an ADJUST click.
   Removed some superfluous casts from 'void *' to other pointer types.
   Reworded the advice appended when reporting error messages to the user.

1.58 (09 Jan 2011) ----------------------------------------------------------
   Linked against release 40 of CBLibrary, in which the compression and
    decompression code have been rewritten from scratch.
   Fixed a memory leak (of the input buffer) if an error occurs while
    loading a file during a batch operation.
   Sets the type of files created during a batch operation only when all
    of the data has been written, instead of every time it is interrupted to
    poll the event library.

1.59 (28 Jan 2011) ----------------------------------------------------------
   Linked against release 42 of CBLibrary, in which the speed of compression
    and error detection during decompression have been improved.

1.60 (13 Feb 2011) ----------------------------------------------------------
   Updated the amount of free memory required to start the application from
    72K to 92K (of which 72K is assigned to the application memory slot).

1.61 (02 Jan 2015) ----------------------------------------------------------
   Linked against release 47 of CBLibrary, which provides new string buffer
    and directory iterator objects which are utilised. CBLibrary
    functionality is used in preference to calling the Acorn library kernel
    directly.
   Much code refactoring: reduced use of 'goto', heap block addresses are
    now used in preference to toolbox object IDs, and generic savebox-related
    code is now implemented as a superclass to avoid code duplication.
   Older saveboxes are no longer deleted upon unticking the 'Multiple
    saveboxes' option (kludgy implementation of questionable behaviour).
   Wrote unit tests to properly test error-handling paths.
   Removed author credit for David O'Shea because this application no longer
    uses code derived from his (since version 1.58).

1.62 (19 Feb 2016) ----------------------------------------------------------
   Fixed a bug where PreQuit messages were always assumed to incorporate a
    flags word, making it unpredictable whether or not desktop shutdown was
    restarted if no flags were present. That had little practical effect
    because the extra word is always present from RISC OS 3 onward.
   Linked against release 50 of CBLibrary, which has some internal changes
    but probably nothing noteworthy for this application.
   Minor changes to use fewer magic numbers in the source code and make
    tests complete successfully with the latest version of CBLibrary.
   Optimised the makefile by using $(addprefix ) and suffix-based rules.

1.63 (26 Sep 2016) ----------------------------------------------------------
   Simplified OS error handling by reporting errors as early as possible
    and not making subsequent code conditional unless absolutely necessary.
   Errors during parsing of command line arguments are now fatal.
   Successfully creating a top-level output directory is now considered
    sufficient to signal success via the SaveAs_FileSaveCompleted method.
   Created an alternative makefile for use with GNU Make and the GNU C
    compiler.

1.64 (09 Feb 2019) ----------------------------------------------------------
   Moved command line argument parsing to a separate module.
   The command line parser uses decode_load_exec instead of custom code.
   Deleted unused named constant definitions.
   Added 'const' qualifiers to event handler function arguments.
   Deleted the build configuration in which OLD_SCL_STUBS was not defined.
   Updated the Makefiles to share a common list of source files and link
    with separate C libraries instead of the old monolithic CBLibrary.

1.65 (24 Feb 2020) ----------------------------------------------------------
   Compressed files dragged to the iconbar are no longer decompressed until
    the user has specified an output location.
   Compressed files dragged from a savebox to another application can now be
    saved via the RAM transfer protocol if supported by the recipient.
   Uses abstract data streams for input and output as required by the
    'Entity2', 'Saver2' and 'Loader3' components in release 58 of CBLibrary.
   Eliminated 'extern' linkage specifiers and pre-declaration of 'static'
    functions where possible.
   Tweaked the application icons to have an irregular outline as is normal.

1.66 (28 Oct 2020) ----------------------------------------------------------
   Fixed use-after-free upon abnormal termination of a batch operation.
    This could cause assertion failure in writer_flex_destroy (because the
    freed buffer's size appeared smaller than the no. of bytes written).
   Downgraded the SaveAs object template version for compatibility with
    ROOL's ResEd.
   Specified a list of messages of interest upon task initialization for
    improved efficiency.
   Defined a custom Toolbox event number for bringing all windows to the
    front, to allow the user interface to be reconfigured using ResEd alone.

1.67 (02 Dec 2020) ----------------------------------------------------------
   Linked with a bugfixed version of my streams library that cannot become
    stuck in an infinite loop when writing to a compressed file.
   A new CBlibrary function, loader3_load_file(), is used to load files
    dragged from a directory display to the iconbar icon.

1.68 (09 Dec 2020) ----------------------------------------------------------
   Linked with a bugfixed version of my streams library that cannot produce
    truncated output when writing to a compressed file. (Previous attempted
    bugfix had this bad side-effect.)
   Minor refactoring: more use of compound literal assignment and struct
    initializers for robustness and succinctness. Used multiple exits from
    functions where doing so simplifies the code.
   The 'Retry' button in the dialogue box displayed for an error during a
    batch operation now reprocesses the faulty file from scratch instead of
    just retrying the specific action that failed.

1.69 (10 Dec 2020) ----------------------------------------------------------
   Save dialogue boxes are now explicitly hidden after a successful save
    (because ROOL's version of SaveAs doesn't do that automatically).

1.70 (01 Aug 2022) ----------------------------------------------------------
   Fix missing 'return' statement in the main() function of a test program.
   Use a new library function to remove all event handlers and delete a
    Toolbox object.
   Intercept #include of library headers (for debugging purposes) using
    local files of the same name, which requires use of "" instead of <>.
   Prefer to minimise declaration scope.
   Use CONTAINER_OF() in preference to assuming the layout of structs.
   Remove redundant 'const' qualifiers from function declarations.

-----------------------------------------------------------------------------
8   Compiling the program
    =====================

  If you did not receive source code with this program then you can download
it from http://starfighter.acornarcade.com

  This program incorporates code from several C libraries created by the same
author: CBLibrary, CBOSLib, CBUtilLib, SF3KLib and GKeyLib. Source code for
those libraries is available at http://starfighter.acornarcade.com/mysite/

  To compile and link the program you will also require ISO 'C' (9899:1999)
library headers, stubs for the shared C library, and the flex, toolbox, event
and wimp libraries supplied with the Acorn C/C++ Development Suite. You must
ensure that the library directories clib, tboxlibs and flexlib are on your
C$Path, otherwise the compiler won't be able to find the required headers.

  Two make files are supplied:

   'Makefile' is intended for use with Acorn Make Utility (AMU) and the
    Norcroft C compiler supplied with the Acorn C/C++ Development Suite.
   'GMakefile' is intended for use with GNU Make and the GNU C Compiler.
    I have used it experimentally to compile but not to link the program.

  The APCS variant specified for the Norcroft compiler is 32 bit for
compatibility with ARMv5 and fpe2 for compatibility with older versions of
the floating point emulator. Generation of unaligned data loads/stores is
disabled for compatibility with ARMv6. When building the code for release,
it is linked with RISCOS Ltd's generic C library stubs ('StubsG').

-----------------------------------------------------------------------------
9   Licence and Disclaimer
    ======================

  This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public Licence as published by the Free
Software Foundation; either version 2 of the Licence, or (at your option)
any later version.

  This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licence for
more details.

  You should have received a copy of the GNU General Public Licence along
with this program; if not, write to the Free Software Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.

-----------------------------------------------------------------------------
10  Credits
    =======

  FednetCmp was designed and programmed by Christopher Bazley.

  Credit goes to David O'Shea and Keith McKillop for working out the
Fednet compression algorithm. David wrote a DeComp module for use with the
Stunt Racer track designer, which early versions of FednetCmp relied upon.

  The application name "FednetCmp" (including associated sprites/system
variables) has been officially registered with RISCOS Ltd.

  The game Star Fighter 3000 is  FEDNET Software 1994, 1995.

-----------------------------------------------------------------------------
11  Contact details
    ===============

  Feel free to contact me with any bug reports, suggestions or anything else.

  Email: mailto:cs99cjb@gmail.com

  WWW:   http://starfighter.acornarcade.com
         http://starfighter.acornarcade.com/mysite/
