Some notes on BigFiles
======================

Historically, FileCore has limited the maximum object size to &7FFFFFFF (ie. all extents are positive) despite the FileSwitch API being able to express objects up to &FFFFFFFF in size. Hereafter shorthanded to 4G-1.

The 'BigFiles' switch enhances FileCore to make full use of the FileSwitch range.

FileSwitch API
==============
FSEntry_Open
------------
The return value in R4 saturates at 4G-1 to mean "allocated 4G". While the PRM states must be a multiple 
of buffer size this clearly can't be expressed in a 32 bit register when rounded up to the nearest LFAU.
FileSwitch doesn't use the value of R4 internally, it is merely stored in case a client of FileSwitch requests
it.

FSEntry_Args
------------
Args 4, R2 (out) can be 4G-1 to mean "allocated 4G". The PRMs are vague on this API, could be byte sizes, in
which case this is not unusual.
Args 7, R2 (out) can be 4G-1 to mean "allocated 4G". The PRMs are vague on this API, could be byte sizes, in
which case this is not unusual.

Allocations
===========
For internal functions relating to allocations, internal maths has been extended to 33 bit (or in a few 
cases 64 bit) through careful use of the carry bit. On exit from these functions it is mapped to a special
value "RoundedTo4G" which has been set to a value that cannot otherwise be encountered because it is not
any supported sector size.

This ensures the calling standard doesn't require any new registers, minimising the differences between the
switch being enabled and not.

Read ahead/write behind
=======================
It is questionable what read-ahead achieves with modern media. Drives made post year 2000 will all feature
1Mbyte or more of on board read-ahead cache. This far exceeds the maximum supported read-ahead buffers in FileCore
of 255 (ie. 255kBytes). 

Other media is now solid state, hence doesn't benefit from read-ahead either - there is no step, seek, or settle
overhead since the media is not a spinning platter.

Some gain is still possible with floppy discs by speculatively reading to the end of a track, though how
often the logical fragmentation of a file actually makes this worthwhile is unclear.

Write behind is still useful, since it decouples the blocking FileSwitch API from the media which is often on
an I/O interface that is slower than a memory to memory copy.

There be many dragons in FileCore80!

The simplest approach was deemed to update the background transfers to use unsigned arithmetic and compares but
to limit the read-ahead/write-behind to &FFFFFC00, ie. one FileCore buffer of 1k less than 4G. In principle this
threshold could adapt to the sector size of the media (hence get as close as 256B from 4G) but this extra
complexity didn't merit the possible gain of a cache hit on just 768 bytes.

Attempts to read that last 1k are simply done in the foreground. This can be analysed with the following cases

1. Request to load all 4G-1 directly (OS_File) to the application's memory
   Not possible, since the ARM only has 4G of address space.

2. Request to load bytes one at a time (OS_BGet) of the last, say, 1MB of the file
   FileSwitch breaks this up into one-FileSwitch-buffer-at-a-time sized transfers from the media, depending
   of the LFAU that FileCore reported on return from FSEntry_Open. Therefore the read ahead applies for all
   but the last 1k of the file - an acceptable trade off for OS_BGet.

3. Request to load bytes in blocks (OS_GBPB) of the last, say, 1MB of the file
   As the end offset is within &FFFFFC00-&FFFFFFFF this actually gets split by FileSwitch to load most
   of the sectors direct into application memory, then the last LFAU sized piece is loaded into FileSwitch's
   buffer in order that it can copy out LFAU-1 bytes from it. This is because the FSEntry_GetBytes for a
   buffered file is guaranteed to only request FileSwitch buffer sized multiples, and since &FFFFFFFF is
   not modulo 64/128/256/512/1024/2048 it has to buffer it then memcpy() it out again.

4. Request to save all 4G-1 directly (OS_File) from the application's memory
   In theory this is possible, but generally RISC OS doesn't actually map all the logical address space in
   at once in a contiguous lump. Assuming it was, then write behind would rapidly fill up (255kB max) and
   the bottleneck becomes I/O as the transfer has saturated the buffer. 
   As noted above, this implementation will push it all into the foreground, at the expense of 255kB out
   of 4G that could have been deferred.

5. Request to save bytes one at a time (OS_BPut) of the last, say, 1MB of the file
   See notes on OS_BGet. Write behind applies for all FileSwitch to FileCore buffer transfers up until 
   the very last, which is pushed into the foreground.

6. Request to save bytes in blocks (OS_GBPB) of the last, say, 1MB of the file
   See notes on OS_GBPB. The last part of the transfer is not a whole FileSwitch buffer size so it will
   linger in FileSwitch's buffer until either an explicit flush is requested or the file is closed.
   This last write is forced into the foreground, but both flushes and closing already wait for write
   behinds to complete, so little net change.
