*****************************************************************************
Автор : Бесчетнов Михаил Константинович
Web   : http://extractor.far.ru
E-Mail: collapse_forever@mail.ru
Источник форматов: Heroes of Might and Magic III
*****************************************************************************
*** Формат LOD
В начале заголовок:

LODHeader: record
  id: array[1..8]of char;       //Идентификатор формата
  Files: LongInt;               //Количество файлов
End;

Таблица размещения файлов располагается по смещению $5C.
Описание формата записи о файле:

FATRecord: record
  Name: array[1..12]of char     //Имя файла
  Junk: array[1..4]of char;     //Хлам
  Offset: LongInt;              //Смещение до файла
  RealSize: LongInt;            //Реальный размер файла
  Junk: array[1..4]of char;     //Хлам
  Size: LongInt;                //Размер файла
End;  

*** Формат SND
В начале заголовок:

SNDHeader: record
  Files: LongInt;               //Количество файлов
End;

Таблица размещения файлов располагается по адресу $04.
Описание формата записи о файле:

FATRecord: record
  Name: array[1..12]of char     //Имя файла
  Junk: array[1..28]of char     //Хлам
  Offset: LongInt;              //Смещение до файла
  Size: LongInt;                //Размер файла
End;

*** Формат VID
В начале заголовок:

VIDHeader: record
  Files: LongInt;               //Количество файлов
End;

Таблица размещения файлов располагается по адресу $04.
Описание формата записи о файле:

FATRecord: record
  Name: array[1..12]of char     //Имя файла
  Junk: array[1..28]of char     //Хлам
  Offset: LongInt;              //Смещение до файла
End;

*** Формат PCX
Заголовок:

PCXHeader: record
  Size: LongInt;                //Размер данных
  Width: LongInt;               //Ширина изображения
  Height: LongInt;              //Высота изображения
End;

По полю  PCXHeader. Size  можно определить тип  изображения: 8bit или 24bit. Не
знаю, кто как, а я произвожу две проверки:
1. Если PCXHeader.Size=PCXHeader.Width*PCXHeader.Height то изображение 8-ми битное.
2. Если PCXHeader.Size=3*PCXHeader.Width*PCXHeader.Height то изображение 24-х битное.
3. Если не то, и не другое, значит это вообще не .pcx

По адресу $0C находятся сами графические данные. Тут все просто: если изображе-
ние  8-ми   битное,  то  читаем  строки  длиной  PCXHeader.Width,  в  противном
случае - PCXHeader.Width*3. Заметьте: к 8-ми битным  изображениям должна прила-
гаться палитра! Так оно и есть - отсчитайте 256*3 байт от конца файла и попаде-
те на  RGB описание  нулевого цвета. В 24-х битных изображениях  палитра, разу-
меется, отсутствует.

*** Формат DEF

Один из  самых навороченых из  встреченых мной форматов.  Представляет из  себя
"сборник" нескольких (от одного до  нескольких десятков) спрайтов. По сему, бу-
дем файл  DEF называть условно Архивом  (хотя, по большому счету, он таковым не
является). В общих чертах, структура его такова:
  I. Заголовок
  II. Палитра 256x3 (BGR)
  III. Таблица расположения спрайтов внутри архива DEF
  IV. Спрайты

I. Заголовок

DEFHeader: record
  ID: LongInt;                  //Идентификатор изображения. При распаковке его
                                  значение не  играет никакой  роли.  Нужен по-
                                  видимому, только самой игре.
  FullWidth: LongInt;           //Полная ширина изображения
  FullHeight: LongInt;          //Полная высота изображения
  TotalBlocks: LongInt;         //Общее количество блоков спрайтов
End;

Все изображения в  архиве DEF связаны между собой.  Связь может быть логической
(например, изображения  всех видов одной кнопки), и графической, когда спрайты,
будучи просмотрены подряд, образуют  анимированное изображение.  В этом случае,
первый спрайт  представляет собой  полное изображение  объекта (ris1.gif), а на
остальных спрайтах хранятся только изменяющиеся области изображения (ris2.gif).
Обратите внимание, что часть  изображения мной  выделена розовым цветом. Именно
эта часть хранится  в виде спрайта, а потом подставляется по определенным коор-
динатам в полное  изображение. Координаты  подстановки указываются в  заголовке
каждого спрайта, До которых мы ее дойдем. В результате наложения  всех спрайтов
на первый получается приличная анимация (ris3.gif).

II. Палитра

Палитра располагается по  смещению $10 и представляет собой массив записей фор-
мата RGB общим размером 256x3 байт.

III. Таблица расположения спрайтов

Смещение таблицы - $310. Таблица  представляет собой не сплошную последователь-
ностей записей, а  несколько блоков записей. Количество блоков определяется пе-
ременной DEFHeader.TotalBlocks. Ниже записана структура каждого блока:

BlockHeader: record
  Junk_1: array[1..4]of char;          //Хлам
  TotalSprites: LongInt;               //Количество спрайтов в блоке
  Junk_2: array[1..8]of char;          //Хлам
  Names: array of array[1..13]of char; //Таблица имен спрайтов. Количество  за-
                                         писей = TotalSprites
  Offsets: array of LongInt;           //Таблица адресов  спрайтов.  Количество
                                         записей = TotalSprites
End;

IV. Спрайты

Заголовок:

SpriteHeader: record
  Junk_1: array[1..4]of char;   //Хлам (иногда - размер данных спрайта)
  SpriteType: LongInt;          //Тип спрайта
  FullWidth: LongInt;           //Полная ширина изображения
  FullHeight: LongInt;          //Полная высота изображения
  SpriteWidth: LongInt;         //Ширина спрайта
  SpriteHeight: LongInt;        //Высота спрайта
  LeftMargin: LongInt;          //Смещение спрайта от левого края изображения
  TopMargin: LongInt;           //Смещение спрайта от верхнего края изображения
End;

Дальше действуем в зависимости от типа спрайта. Всего их четыре, но я разобрал-
ся только с тремя.

Тип 0:

  Просто читаем матрицу пикселов размером SpriteWidth*SpriteHeight

Тип 1:

  Читаем таблицу смещений на  каждую строку. Каждая запись - типа LongInt. Сме-
  щение отсчитывается от начала этой таблицы.
  В данном типе  каждая строка  записывается в виде отдельных сегментов. Каждый
  сегмент состоит  из байта - типа сегмента, байта - длины сегмента, и последо-
  вательности  байтов -  пикселей.  Типа сегментов  всего два: $00 - обозначает
  последовательность прозрачных  пикселов; $FF - обозначает  последовательность
  обычных  пикселов. Например,  запись 00 20 FF 02 78 01 означает,  что сначала
  следует  последовательность из 32 ($20) прозрачных  пикселов, а затем следует
  прочитать 2 обычных пиксела, т.е. строку 78 01

Тип 3:

  Читаем таблицу смещений на каждую строку. Каждая запись - типа Word. Смещение
  отсчитывается от начала этой таблицы.
  Здесь система таже,  что и у типа 1,  типов сегментов побольше. Байт-тип сег-
  мента и байт-длина  сегмента совмещены в  один байт-описатель,  где левые три
  бита определяют тип сегмента, а остальные пять - его длину. Фактически, после
  определения длины надо  ее значение увеличить на 1. Ниже  приведена таблица с
  описанием всех типов сегмента.

  $00 - Пишем блок прозрачных пикселов. Цвет пиксела выбирается произвольно
  $01 - Пишем блок полупрозрачных пикселов (тень). Цвет пиксела выбирается про-
        извольно
  $04 - Пишем блок полупрозрачных пикселов  (густая тень). Цвет пиксела выбира-
        ется произвольно
  $05 - Пишем блок прозрачных пикселов  (в игре на их месте будут пикселы цвета
        игрока, которому принадлежит объект (например - флаг в изображениях ге-
        роев)). Цвет пиксела выбирается произвольно
  $07 - Переписываем последовательность пикселов