APD file structure
------------------

The APD file is a GZip compressed version of the original APD file.

Compressed file always starts:
    1F 8B 08 00 00 00 00 00 00 0B
    ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
    |  |  |  |  |  |  |  |  |  |
    |  |  |  |  |  |  |  |  |  +- OS
    |  |  |  |  |  |  |  |  +---- xfl
    |  |  |  |  +--+--+--+------- time
    |  |  |  +------------------- gzip flags
    |  |  +---------------------- gzip compression*
    |  |
    +--+------------------------- gzip header

*  Compression method: 8 is the only supported format

Original APD file structure:
           0 - 7   "APDX0001" identifier
           8 - B   t0sd - Track 0 SD length in bits
           C - F   t0dd - Track 0 DD length in bits
          10 - 13  t0qd - Track 0 QD length in bits
          14 - 1F  t1sd - Track 1 SD length in bits
          20 - 23  t1dd - Track 1 DD length in bits
          24 - 27  t1qd - Track 1 QD length in bits
...                repeated to Track 159
        77C - 787  Track 160 (blank)
        7C4 - 7CF  Track 166 (blank)

              7D0  Track 0 SD data
+ (t0sd + 7) >> 3  Track 0 DD data
+ (t0dd + 7) >> 3  Track 0 QD data

+ (t0qd + 7) >> 3  Track 1 SD data
+ (t1sd + 7) >> 3  Track 1 DD data
+ (t1dd + 7) >> 3  Track 1 QD data

SD    data is big-endian raw FM words
DD/QD data is big-endian raw MFM words

As far as I can tell, the tracks are always sequential, so
physical tracks translate as:

Physical         APD
--------------   -------
Side 0 Track 0 > Track 0
Side 1 Track 0 > Track 1
Side 0 Track 1 > Track 2
etc.



MFM details:
------------

Sectors start at the byte following &44895545 - which may not be
byte aligned, so you have to step though a bit at a time

MFM track header (not in an APD, here for reference):

MFM    Byte
---    ----
5224   C2
5224   C2
??     FC (sector ID marker)
9254   4E (repeated 50 times)


MFM sector header:

MFM    Byte
----   ----
4489   A1
4489   A1
4489   A1
5554   FE (sector ID marker)
tttt
hhhh
ssss
LLLL
crc1      (CRC of ID)
crc2
9254   4E (repeated 22 times)
AAAA   00 (repeated 12 times)
4489   A1
4489   A1
4489   A1
5545   FB (data ID marker)
1<<(L+7) bytes of data
crc1      (CRC of data)
crc2
9254   4E (repeated 40 times)


FM details:
----------

FM sector header:

FM     Byte
----   ----
AAAA   00
AAAA   00
AAAA   00
AAAA   00
AAAA   00
AAAA   00
F57E   FE (sector ID marker)
tttt
hhhh
ssss
LLLL
crc1      (CRC of ID)
crc2
AAAA   00 (repeated 17 times)
F56A   FB (data ID marker)
1<<(L+7) bytes of data
crc1      (CRC of data)
crc2
AAAA   00 (repeated 10 times)


Where:
 tttt - Track number
 hhhh - Side (0 / 1)
 ssss - Sector number
 LLLL - Sector length (1 << LLLL+7)



Calculating sector timing:

The following equation is used to calculate each sectors timing
from the start of the track, whilst reading an APD file:

200 - ( (200 / (track length in bits))) * (bits left) )



JFD file structure
------------------

A JFD file is a gzip compressed version of the original JFD
file.

Official files should be named "[optional text name] Fxxxxxnn"
(see below for xxxx / nn explanation) eg "Fire & Ice (1995)
 (Warner Interactive Entertainment) F1015401" or shortened to
"F1015401" on an Arc that doesn't support long file names.

Compressed file always starts with a gzip header:
+0  1F 8B 08 00 00 00 00 00 02 0D
    ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
    |  |  |  |  |  |  |  |  |  |
    |  |  |  |  |  |  |  |  |  +- OS (RISCOS)
    |  |  |  |  |  |  |  |  +---- xfl
    |  |  |  |  +--+--+--+------- time
    |  |  |  +------------------- gzip flags
    |  |  +---------------------- gzip compression*
    |  |
    +--+------------------------- gzip header

*  Compression method: 8 is the only supported method


NOTE: From ADFFS 2.86 the JFD header uses Z_NO_COMPRESS.  ie it's not compressed

JFD header then follows:
+0   "JFDI" identifier
+4   Min. version of ADFFS required to handle file * 100
      eg 1.25 would be 125
+8   Memory allocation required to load file in uncompressed bytes
      Header + Track Table + Sector Table + Data Table + Obey file

      NOTE: This does not include the size of the Delta tables

+12  Disc sequence number - SSSSnnnn
      Where:
        SSSS is the number of discs in this set
        nnnn is the number of this disc
+16  Game ID number (xxxxx) - official release ID of this
      floppy set.  Unofficial releases should be an ID of zero
+20  Image version number: VVVwwwww
      Where:
        VVV - major release version, 0 being initial release
      wwwww - minor version, reset to 0 on a major release
              and is incremented on each flush / save as
+24  Offset to Track Table, the end of which is denoted by
      the start of the Sector Table
+28  Offset to Sector Table, end of which is denoted by
      the start of the Data Table
+32  Offset to Data Table
+36  0 or Offset to optional Delta Track Table
      If this exists, it supersedes the Track Table at +24
      End is denoted by the start of the Delta Sector Table
      NOTE: This is the offset in the file, not the compressed stream
      ADFFS will use OS_Args to seek to this offset to read the delta track table
+40  0 or Offset to optional Delta Sector Table
      If this exists, it supersedes the Track Table at +24
      End is denoted by the start of the Delta Data Table
+44  0 or Offset to optional Delta Data Table
+48  Disc title.  eg "Fire & Ice (1995) (Warner Interactive
      Entertainment)", zero terminated
+304 ... future expansion space (additions in 2.06+)

+304 Bit flags:
      0 - Disk write protected
      1 - Automatically write changes back to the JFD
      2 - Protect CMOS required
      3 - Protect Modules required
      4 - Hide Hourglass
      5 - Requires Shift-Break to load
      6 - Remap video memory to match RISC OS 2 thru 3.1x
      7 - reserved, should be 0
      8 - ARM3 compatible
      9 - ARM250 compatible
     10 - ARM610/710 compatible
     11 - ARM7500 compatible
     12 - StrongArm compatible
     13 - ARMv5/v5/v7 compatible
     14 - reserved, should be 0
     15 - reserved, should be 0
     16 - RiscOS 2 compatible
     17 - RiscOS 3.1 compatible
     18 - RiscOS 3.5 compatible
     19 - RiscOS 3.7 compatible
     20 - RiscOS 3.8 / 4.x compatible
     21 - RiscOS 5.x compatible
     22 - RiscOS 6.x compatible
     23-32 - reserved, should be 0
+308 FPS of the original game * 2 (eg for 12.5 FPS use 25)
+309 - 311 reserved
+312 Length of Obey file in bytes
+316 ... future expansion space (currently 0 bytes)

When writing a JFD, a full flush using Z_FINISH should be performed after writing the header.

[Track Table]
+0 Track 0 offset within Sector Table
+4 Track 1 offset within Sector Table
...
+n*4 Track n offset within Sector Table
       n can be any value, although to allow writes should be at
       least 160.  For reference, APD's are 166
       A track with no imaged sectors is denoted by FFFFFFFF

[Sector Table]
+0 ttBdnnCs - Sector Header description (see below)
+4 Offset within Data Table of sector data, if this value is
     FFFFFFFF no data is associated with the sector.  In the
     case of a sector with a CRC flag set in C, the sector
     is a stub to produce a specific error.

.. repeats for all sectors in track, two doubles (ie 8 bytes) per
     sector

+n FFFFFFFF - end of track marker

The above repeats for all tracks containing sector data.

[Data Table]
... X bytes of sector data in native byte format.
     Not necessarily in disc order, as sectors are located
     individually during reads.

[Obey file]
... Obey file used to boot the floppy

When writing a JFD, a full flush should be performed here, before
compressing the delta tables.  The OS_Args file pointer for
the Delta track table should be written to +36 in the header

[Delta Track Table]
... same structure as [Track Table]
    NOTE: ADFFS uses the Track table pointed to at +24 as the starting
          point for this table.  The delta track table always supercedes
          the track table from +24

[Delta Sector Table]
... same structure as [Sector Table]
    NOTE: ADFFS uses the Sector table pointed to at +28 as the starting
          point for this table.  The delta sector table always supercedes
          the sector table from +28

[Delta Data Table]
    NOTE: Sector data is written in order, starting from the first sector in the
          list for track 0. eg in pseudo code:

    track=0
    while track<last_track
      sector=track_table[track]
      if sector!=&FFFFFFFF then
        repeat
          if sector_table[sector.header].modified then
            compress sector_table[sector.offset], 1<<(sector_table[sector.header].size + 7)
          endif
          sector+=8
        until sector_table[sector_pointer.header]=&FFFFFFFF
       endif
    endwhile


Sector Header description:  ttBdnnCs
Where:

tt - time of sector from start of index marker in milliseconds
     max being 200 (optional, required for duplicate sectors)
B  - Option bits
       bit 0 - sector data contains DiscOp 3 data for the track
       bit 1 - reserved
       bit 2 - reserved
       bit 3 - modified flag.  Set if the sector has been altered
d  - Density value, where:
       1 - single
       2 - double
       4 - quad
       8 - octal
nn - Sector number
C  - CRC bits, where:
       bit 0 - ID CRC invalid
       bit 1 - Data CRC invalid
       bit 2 - Sector not found
       bit 3 - Slow sector (read at normal floppy speed)
s  - 1772 sector size, where:
       0 - 128 bytes
       1 - 256 bytes
       2 - 512 bytes
       3 - 1024 bytes



ConvRec internal structures
---------------------------

ConvRec sector table (16 bytes per entry):

+0  - sector
+1  - track
+2  - x bits from the recording entry (see below)
+3  - reserved (byte)
+4  - density
+5  - heads
+6  - secspertrack
+7  - log2secsize
+8  - discsize
+12 - 0 or DiscOp 3 data length
+16 - DiscOp 3 data (optional)



ADFFS recording structure (20 bytes per entry):
-------------------------

+0  - 00x000bc

 Where:
  c - DiscOp 0 / 1 / 2 / 3
        0 - verify
        1 - read sectors
        2 - write sectors
        3 - read track
        F - manually forced sector ID without data
  b -   DiscOp bits
         bit 0 - IDs requested on a DiscOp3
         bit 1 - scatter list
         bit 2 - escape conditions are ignored
         bit 3 - ignore timeout, wait forever
  x - Manually forced entry
         bit 0 - known protection, not de-duped
         bit 1 - perform a DiscOp 3 reading data instead of sector ID's
         bit 2 - slow read sector (it's read at actual floppy speed when read
                                   back through ADFFS)
         bit 3 - duplicate sector (re-read the sector until two differing
                                   sectors have been captured)

+4  - disc address
+8  - size of data read
+12 - ddhhssll - DiscRec
+16 - disc size

 Where:
  ll - log2 sector size (ie 8 - 256 byte)
  ss - Sectors per track
  hh - Number of heads
  dd - Density (1 - single, 2 - double, 3 - double+, 4 - quad, 8 - octal)




HFE structure (as created by ADFFS)
-------------
+0  - "HXCPICFE" (v1/v2) or "HXCHFEV3" (v3)
+8  - 0   - 0=v1/v3 or 1=v2
+9  - 80  - number of tracks
+10 - 2   - number of disc sides
+11 - 255 - track encoding mode.  255=unknown
+12 - 250 - bit rate in kbits
+14 - 0   - floppy RPM
+16 - 255 - floppy interface mode. 0=IBM DD, 1=IBM HD, 254=disable
+17 - 0   - reserved
+18 - 1   - track list offset/512.  eg 1 = +512
+20 - 255 - 0=write protect or 255=unprotected
+21 - 255 - 255=single step or 0=double step
+22 - 255 - 0=use alternative track encoding for side 0 or 255=unused
+23 - 255 - encoding method for side 0 or 255=unused
+24 - 255 - 0=use alternative track encoding for side 1 or 255=unused
+25 - 255 - encoding method for side 1 or 255=unused

Track list
+512 - offset to track 0/512 (eg 2 = +1024)
+514 - length of track in bytes
repeats
+678 - offset to track 83/512
+680 - length of track 

+1024 - Track data, raw stream of FM or MFM
  +0  side 0
  +512 side 1