                Описание формата FDI-файла
                Версия 1.0 (Углеков К.)
                Версия 2 (deathsoft)

Пример реализации чтения/записи fdi версий 1 и 2 можно посмотреть в
wldr_fdi.cpp эмулятора UnrealSpeccy v0.38.3

Общую структуру fdi файла можно представить в следующем виде:

TFdiHdr - присутствует всегда
TFdiAddInfo - присутствует в формате 2 и выше (в формате 1 отсутствует)
TTrkHdr[c*h] - массив заголовков дорожек
...
FdiTrkData[] - массив переменной длины с данными дорожек
...
(формат 2 тип 1 (информация о сбойных байтах))
TFdiTrkAddInfo[] - массив переменной длины с дополнительной информацией о дорожках
...
FdiTrkAddData[] - массив переменной длины с данными сбойных байтов для тех дорожек где они есть


                        Формат заголовка файла
Структура TFdiHdr:
------------------------------------------------------------------------------
Смещение Длина поля     Описание
------------------------------------------------------------------------------

0       3       Ключевая метка 'FDI'
3       1       Флаг защиты записи      (0 - write enabled, 1 - write disabled)
4       2       Число цилиндров
6       2       Число поверхностей
8       2       Смещение текста (короткий комментарий к диску)
A       2       Смещение данных
С       2       Длина дополнительной информации в заголовке.
                В версии 1.0 - 0x0000
                В версии 2 - размер структуры TFdiAddInfo (см. "Формат дополнительной информации")

E       "Длина дополнительной информации" (если 0, то дополнительной информации нет)
                см. "Формат дополнительной информации"

E+"длина дополнительной информации"
        ???
                Область заголовков треков. Здесь собрана вся информация о
                формате дискеты. Эта область должна содержать не меньше
                "Число цилиндров"*"Число поверхностей" заголовков. Заголовки
                идут в порядке Cyl 0 Head 0, Cyl 0 Head 1, Cyl 1 Head 0 и т.д.
                Формат заголовка описан ниже.

"Смещение текста"
        ???
                Комментарий к диску.Конец комментария - нулевой символ.
                MAKEFDI при создании нового файла позволяет вводить комментарий
                не более 64 символов с завершающим нулем,но при работе с файлом
                длина этого поля будет определяться по положению завершающего
                нулевого символа

"Смещение данных"
        ???
                Здесь лежат собственно данные из секторов. Сколько здесь будет
                секторов, их длина и порядок следования - зависит от формата.

-------------------------------------------------------------------------------

Формат FDI-файла допускает пропуски между областями заголовков треков,текстовым
комментарием и областью данных.


                        Формат заголовка трека
Структура TTrkHdr:
------------------------------------------------------------------------------
Смещение Длина поля     Описание
------------------------------------------------------------------------------

0       4       Смещение трека - начало области данных этого трека
                        относительно "Смещения данных"
4       2       Всегда содержит 0 (резерв для модернизации)
6       1       Число секторов на треке

7       (Число секторов)*7
                Информация о секторах на треке. Каждый сектор описывается 7
                байтами. Первые 4 байта - стандарные параметры C,H,R,N из
                адресного маркера. Следующий байт - флаги:

                 bit 7=0 - маркер нормальных данных, 1 - удаленных данных;
                 bit 0-5: флаги CRC. Единица в одном из разрядов означает, что
                 при считывании этого сектора на длину 128,256,1024,2048 или
                 4096 байт получается правильная контрольная сумма. Если во всех
                 разрядах 0 - сектор записан с ошибкой контрольной суммы.
                 bit 6: В данной версии всегда 0. Возможно, 1 в данном разряде
                  будет обозначать адресный маркер без области данных.

                Последние 2 байта - смещение данных этого сектора относительно
                начала области данных трека. Чтобы получить абсолютный адрес
                в файле, к этому числу надо добавить "Смещение данных" и
                "Смещение трека"
------------------------------------------------------------------------------
7*(Число секторов+1)    длина заголовка трека

        Заметим, что байт флагов в описании сектора пока никак не используется
эмулятором.

                        Формат дополнительной информации (FDI 2 и выше)

Типы данных:
u8  - беззнаковый 8бит  (1 байт)
u16 - беззнаковый 16бит (2 байта)
u32 - беззнаковый 32бит (4 байта)

Описание структуры TFdiAddInfo:
struct TFdiAddInfo
{
    // Заголовок, одинаковый для всех форматов
    u16 Ver; // 2 - FDI 2
    u16 AddInfoType; // Тип дополнительной информации:
                     // 1 - bad bytes info (информация о сбойных блоках)

    // Для AddInfoType == 1 (для других форматов информация ниже будет другой)
    u32 TrkAddInfoOffset; // Смещение массива структур TFdiTrkAddInfo в байтах от начала файла
                          // число структур равно "Число цилиндров" * "Число поверхностей" из FDI
                          // заголовка (Внимание! структуры имеют переенный размер)
    u32 DataOffset; // Смещение данных с дополнительной информацией (от начала файла)
};

Описание структуры TFdiTrkAddInfo:
struct TFdiTrkAddInfo(int n) // n - Число секторов на дорожке, дорожки имеют сквозную нумерацию
                             // от 0 до "Число цилиндров" * "Число поверхностей"-1
{
    u32 TrkOffset;  // Смещение в байтах дополнительной информации для данной дорожки
                    // относительно FdiAddInfo.DataOffset
                    // 0xFFFFFFFF - дополнительная информация для данной дорожки отсутствует
    if(n && (TrkOffset != 0xFFFFFFFF))
    {
        TFdiSecAddInfo Sec[n]; // Описатели дополнительной информации о секторах (если n==0, то отсутствует)
    }
};

Описание структуры TFdiSecAddInfo:
struct TFdiSecAddInfo
{
    u8 Flags; // 1 - Массив сбойных байтов присутствует

    // Смещение битового массива сбойных байтов внутри дорожки относительно TFdiTrkAddInfo[i].TrkOffset;
    // Число битов определяется размером сектора
    // Один бит соответствует одному сбойному байту
    // Для вычисления смещения конкретного бита нужно сложить 
    // u32 offs = FdiAddInfo.DataOffset + FdiAddInfo[i].TrkOffset + (FdiAddInfo[i].Sec[s].Flags & 1) ? (128 << FdiHdr.Trk[i].Sec[s].n) : 0;
    // (где i - текущая дорожка, s - текущий сектор, Sec[s].n - код размера сектора 0-128байт, 1-256байт,2-512байт,3-1024байт и т.д.)
    // номер байта определяется как offs>>3, а номер бита в байте как offs&7
    u16 DataOffset;
};

При записи в байты помеченные как сбойные эмулятор должен искажать записываемые данные
(наприер делать xor с псевдослучайно последовательностью).
При чтении из байты помеченных как сбойные эмулятор должен искажать данные
(наприер делать xor с псевдослучайно последовательностью) и выдавать ошибку CRC сектора.
