IMG архив — различия между версиями

Материал из GTAModding.ru
Перейти к: навигация, поиск
(Убрал листинг кода, это все-таки было излишне. Немного подправил остальное.)
Строка 21: Строка 21:
  
 
[[Изображение:IMG_file_alloc.png|center|Схема распределения файлов в IMG архиве]]
 
[[Изображение:IMG_file_alloc.png|center|Схема распределения файлов в IMG архиве]]
 +
 +
===Версия 1А - GTA:LCS и GTA:VCS===
 +
Структура [[IMG]]-архива Stories не отличается от структуры версии 1. Отсутствует <code>.dir</code> файл (исключение - <code>CUTS.IMG</code>). Имена файлов, их смещение и размер содержатся в [[DTZ|game.dtz]] архиве. То есть для того чтобы открыть такой архив нужно либо извлечь данные директории из [[GAME.DTZ]], либо сделать <code>.dir</code> таблицу файлов самостоятельно (причем второй вариант оказался гораздо более простым и данная функция есть в [[YAIE]] - таблица директории формируется исходя из заголовков самих файлов).
  
 
=== Версия 2 - GTA SA ===
 
=== Версия 2 - GTA SA ===
Строка 37: Строка 40:
  
 
Недостаток этого формата - это его расширяемость. Если вы добавите слишком много файлов, директория начнёт записываться ''поверх первых файлов в архиве'', поэтому вам нужно будет записывать первые файлы в конец архива.
 
Недостаток этого формата - это его расширяемость. Если вы добавите слишком много файлов, директория начнёт записываться ''поверх первых файлов в архиве'', поэтому вам нужно будет записывать первые файлы в конец архива.
 
<div class="NavFrame collapsed"><div class="NavHead">'''Пример программы на Delphi по работе с форматом GTAIII/VC/SA'''</div>
 
<div class="NavContent">
 
 
<source lang="delphi" line>
 
 
{В глобальные переменные}
 
 
  Stream, DIRStream: TFileStream;  //Stream - переменная для загрузки архива, DIRStream - переменная для загрузки DIR файла
 
  Size, Offset, FileNum, A : Integer; //Целые данные - размер, смещение, количество файлов
 
  ID:Array [0..3] of AnsiChar;    //Для идентификатора формата
 
  FileName, DirName : String;    //Для названия IMG и DIR
 
 
procedure TForm1.Close1Click(Sender: TObject);  //'''Процедура открытия архива'''
 
var
 
  ListItem : TListItem;
 
  Name: Array [0..23] of AnsiChar;  //Переменная для сохранения имен
 
  Z: Integer;
 
  DestFile : TFileStream;  // Сюда будем загружать файл для сохранения
 
 
begin
 
  if OpenDialog1.Execute then    //Вызываем диалог открытия
 
  begin
 
    CFileName.Text := OpenDialog1.FileName;
 
    DirName:= CFileName.Text;  //Присваиваем DirName название самого архива
 
    Delete (DirName, Length (DirName)-3, 4); //Удаляем расширение
 
    DirName:=DirName+'.dir';  //Ставим расширение ".dir"
 
    Size := 0;
 
    Offset := 0;
 
    CFileList.Clear;
 
    FileName := OpenDialog1.FileName;
 
    Stream := TFileStream.Create(FileName, fmOpenReadWrite);  // Открываем архив для чтения
 
    Stream.Read(ID, 4);    // Записываем первые три байта чтобы проверить верисию архива
 
    if ID='VER2' then
 
    begin
 
        label2.Caption:='Загружен архив версии №2 - SanAndreas';
 
        Stream.Read(FileNum, 4);  // Считываем количество файлов
 
        for A := 0 to FileNum - 1 do  // Цикл считывания всех файлов
 
        begin
 
          Stream.Read(Offset, 4);  // Считываем смещение файла
 
          Stream.Read(Size, 4);  // Считываем размер файла
 
          Stream.Read(Name, 24);  // Считываем имя файла
 
          ListItem := CFileList.Items.Add;                  //
 
          ListItem.Caption := Name;                        // Добавляем файл со всеми
 
          ListItem.SubItems.Add(IntToStr(Size * 2048));    // параметрами в список файлов
 
          ListItem.SubItems.Add(IntToStr(Offset * 2048));  //
 
        end;
 
    end
 
    else begin
 
    if FileExists(DirName) then
 
        label2.Caption:='Загружен архив версии №1 - GTAIII/ViceCity'
 
    else
 
        label2.Caption:='Ошибка загрузки архива версии №2 - не найден DIR файл';
 
      Stream.Read(ID, 3);  //Считываем первые три байта
 
      DIRStream := TFileStream.Create(DirName, fmOpenReadWrite); //Создаем область памяти куда будем записывать DIR
 
      FileNum:=DIRStream.Size div 32; //Высчитываем число файлов
 
        for A := 0 to FileNum - 1 do  // Цикл считывания всех файлов
 
        begin
 
          DIRStream.Read(Offset, 4);  // Считываем смещение файла
 
          DIRStream.Read(Size, 4);  // Считываем размер файла
 
          DIRStream.Read(Name, 24);  // Считываем имя файла
 
          ListItem := CFileList.Items.Add;                  //
 
          ListItem.Caption := Name;                        // Добавляем файл со всеми
 
          ListItem.SubItems.Add(IntToStr(Size * 2048));    // параметрами в список файлов
 
          ListItem.SubItems.Add(IntToStr(Offset * 2048));  //
 
        end;
 
    end;
 
  end;
 
end;
 
 
procedure TForm1.N6Click(Sender: TObject); //'''Процедура извлечения файлов'''
 
var
 
  DestFile : TFileStream;  // Сюда будем загружать файл для сохранения
 
 
begin
 
  if CFileList.SelCount > 0 then  // Если что-либо выделено в списке файлов
 
    begin
 
    SaveDialog1.FileName := CFileList.Selected.Caption;
 
    if SaveDialog1.Execute then  //Вызываем диалог сохранения
 
    begin
 
      DestFile := TFileStream.Create(SaveDialog1.FileName, fmCreate);  // Создаём файл
 
      DestFile.Seek(0, 0);  // Смещаемся в начало файла.
 
      Size := StrToInt(CFileList.Selected.SubItems.Strings[0]);// Узнаём размер выделенного файла
 
      Offset := StrToInt(CFileList.Selected.SubItems.Strings[1]);// Узнаём смещение выделенного файла
 
      Stream.Seek(Offset, 0);  // Смещаемся к смещению (то есть, к началу) файла в архиве
 
      DestFile.CopyFrom(Stream, Size);  // Копируем количество байт, равным размеру файла в архиве
 
      DestFile.Free;  // Закрываем файл
 
    end;
 
  end;
 
end;
 
 
procedure TForm1.N9Click(Sender: TObject); //'''Процедура переименования файлов в архиве'''
 
var
 
    NameX: array [0..23] of AnsiChar;
 
    Value, Name: String;
 
    OffsetCHECK: Integer;
 
    Y, I:Integer;
 
    label RenameSA, RenameVC;
 
 
 
begin
 
if ID='VER' then  //Если архив версии SanAndreas
 
begin
 
if CFileList.SelCount > 0 then  // Если что-либо выделено в списке файлов
 
begin
 
Offset := StrToInt(CFileList.Selected.SubItems.Strings[1]);// Узнаём смещение выделенного файла
 
Name:=CFileList.Selected.Caption;  //Узнаем его имя
 
OFFSETCHECK:=Offset; //Устанавливаем проверку оффсета
 
Stream.Seek(0, 0);//Смещаемся в начало файла
 
Offset:=0;
 
Size:=0;
 
Stream.Seek(4, 0);  //Пропускаем первые 4 байта
 
Stream.Read(Y, 4);  // Считываем количество файлов
 
for A := 0 to Y - 1 do  // Цикл считывания всех файлов
 
begin
 
Stream.Read(Offset, 4); //Считываем текущий оффсет
 
if Offset * 2048 = OffsetCHECK then GOTO RenameSA; //Если это наш оффсет, переходим к блоку переименования
 
Stream.Read(Size, 4);  //А если не наш, двигаемся дальше. Пропускаем размер.
 
Stream.Read(NameX, 24); //Пропускаем имя
 
end;
 
RenameSA:  //Оффсет - наш
 
Stream.Read(Size, 4);    //Пропускаем первые 4 байта размера
 
Value:=Name;  //Присваиваем переменной типа String имя
 
Value:=InputBox('Переименовать', 'Выберите новое название файла', Value);    //Выводим табличку  переименования
 
for I := 1 to length(Value)-1 do //Цикл: повторяется N-1 раз, где N - число символов в новом имени
 
begin
 
Stream.Write(Value[I], 1);  //Записываем в файл соответствуюие символы из нового имени
 
end;
 
Stream.Write(Value[length(Value)], 24-(I+1)); //Записываем последний символ, зачищая оставшиеся байты, отведенные под имя файла
 
end;
 
CFileList.Selected.Caption:=Value; //Вносим коррективы в список файлов
 
end
 
else  //Если архив версии III/ViceCity
 
{Работа послностью анологична уже приведенному примеру с GTA:SA. Разница лишь в том что придутся  работать с DIR файлом)}
 
begin
 
if CFileList.SelCount > 0 then
 
begin
 
Offset := StrToInt(CFileList.Selected.SubItems.Strings[1]);// Узнаём смещение выделенного файла
 
Name:=CFileList.Selected.Caption;
 
OFFSETCHECK:=Offset;
 
DirStream.Seek(0, 0);
 
Offset:=0;
 
Size:=0;
 
for A := 0 to FileNum - 1 do  // Цикл считывания всех файлов
 
begin
 
Stream.Read(Offset, 4);
 
if Offset * 2048 = OffsetCHECK then GOTO RenameVC;
 
Stream.Read(Size, 4);
 
Stream.Read(NameX, 24);
 
end;
 
RenameVC:
 
DirStream.Read(Size, 8);
 
Value:=Name;
 
Value:=InputBox('Переименовать', 'Выберите новое название файла', Value);
 
for I := 1 to length(Value)-1 do
 
begin
 
DirStream.Write(Value[I], 1);
 
end;
 
DirStream.Write(Value[length(Value)], 24-(I+1));
 
end;
 
CFileList.Selected.Caption:=Value;
 
end;
 
end;
 
 
</source>
 
</div></div>
 
 
===Версия 2А - GTA:LCS и GTA:VCS===
 
Структура [[IMG]]-архива Stories почти не отличается от структуры версии 1. Отсутствует <code>.dir</code> файл (исключение - <code>CUTS.IMG</code>). Имена файлов, их смещение и размер содержатся в [[GAME.DTZ]] архиве (ближе к началу файла). То есть для того чтобы открыть несжатый архив, нужно либо извлечь данные из [[GAME.DTZ]], либо сделать <code>.dir</code> таблицу файлов самостоятельно (причем второй вариант оказался гораздо более простым и данная функция есть в [[YAIE]]).
 
  
 
===Версия 3 - GTA IV===
 
===Версия 3 - GTA IV===
Строка 215: Строка 49:
 
Заголовок файла всегда равен '''20 байтам'''.
 
Заголовок файла всегда равен '''20 байтам'''.
  
  4 byte - DWORD      - Идентификатор (0xA94E2A52) Если, это поле имеет другое значение, архив зашифрован
+
  4 байта - DWORD      - Идентификатор (0xA94E2A52) Если, это поле имеет другое значение, архив зашифрован
  4 byte - DWORD      - Версия (всегда 3)
+
  4 байта - DWORD      - Версия (всегда 3)
  4 byte - DWORD      - Количество объектов
+
  4 байта - DWORD      - Количество объектов
  4 byte - DWORD      - Размер каталога (в байтах)
+
  4 байта - DWORD      - Размер каталога (в байтах)
  2 byte - WORD      - Размер элемента каталога (всегда должен быть равен 0x10)
+
  2 байта - WORD      - Размер элемента каталога (всегда должен быть равен 0x10)
  2 byte - WORD      - Неизвестно
+
  2 байта - WORD      - Неизвестно
  
 
==== Каталог архива ====
 
==== Каталог архива ====
Строка 228: Строка 62:
 
В начале идет массив описателей по 16 байт:
 
В начале идет массив описателей по 16 байт:
  
  4 byte - DWORD      - Размер объекта и флаги  
+
  4 байта - DWORD      - Размер объекта и флаги  
  4 byte - DWORD      - Версия ресурса (только для RSC, для остальных объектов не используется)
+
  4 байта - DWORD      - Версия ресурса (только для RSC, для остальных объектов не используется)
  4 byte - DWORD      - Смещение от начала IMG в блоках (2048 байт)
+
  4 байта - DWORD      - Смещение от начала IMG в блоках (2048 байт)
  2 byte - WORD      - Количество используемых блоков
+
  2 байта - WORD      - Количество используемых блоков
  2 byte - WORD      - Размер неиспользуемого места в последнем блоке
+
  2 байта - WORD      - Размер неиспользуемого места в последнем блоке
  
За описателями следуют имена файлов, разделенные '\x0', в том же порядке, что и описатели.
+
За описателями следуют имена файлов, разделенные '\x0' (нулевым байтом), в том же порядке, что и описатели.
  
 
==== Чтение зашифрованных архивов ====
 
==== Чтение зашифрованных архивов ====
  
Если идентификатор архива не равен 0xA94E2A52, архив считается зашифрованным.
+
Если идентификатор архива не равен <code>0xA94E2A52</code>, архив считается зашифрованным.
 
Для чтения такого архива, следует прочитать заголовок (20 байт), но дешифровать только первые 16 байт.
 
Для чтения такого архива, следует прочитать заголовок (20 байт), но дешифровать только первые 16 байт.
 
После этого, следует снова проверить идентификатор. Если идентификатор корректный, следует считать каталог (размер берется из расшифрованного заголовка) и дешифровать его, округлив размер до числа кратного 16, вниз. (Например, если указан размер 259 байт, дешифруются только первые 256).
 
После этого, следует снова проверить идентификатор. Если идентификатор корректный, следует считать каталог (размер берется из расшифрованного заголовка) и дешифровать его, округлив размер до числа кратного 16, вниз. (Например, если указан размер 259 байт, дешифруются только первые 256).
 +
 +
Шифрование - стандартное для IV - [[AES]].
 +
 
{{Formats}}
 
{{Formats}}
 
[[Категория:GTA 3]][[Категория:GTA VC]][[Категория:GTA SA]][[Категория:GTA 4]][[Категория:Форматы файлов]]
 
[[Категория:GTA 3]][[Категория:GTA VC]][[Категория:GTA SA]][[Категория:GTA 4]][[Категория:Форматы файлов]]

Версия 13:30, 19 июня 2010

В IMG архивах GTA в основном хранятся игровые модели, текстуры, транспортные и пешеходные пути, анимации, а так же внешние скрипты. IMG архив имеет расширение .img. Эти архивы разделяются на версии и имеют схожий между собой формат (за исключением версии, используемой GTA 4).

Содержание

Структура

Версия 1 - GTA III & VC

Архивы первой версии, используемые в GTA III и Vice City, разделены на два файла: директория содержимого архива .dir и сам архив, содержащий файлы .img.

Директория содержит список файлов, их имена, смещение и размер. Изначально формат IMG оптимизировался для использования на DVD или CD, поэтому размер и смещение файлов кратны сектору DVD (2048 байт). Даже если файл имеет размер менее 2-х КБ (например, 218 байт), то в архиве он будет занимать 2 КБ. Файлы (обычно) не сортированы, не сжаты и располагаются "друг за другом" (никакой древовидной иерархии).

Чтобы найти общее количество элементов (файлов) в IMG архиве, необходимо разделить размер .dir файла на 32.

Файл директории не имеет заголовка, просто массив элементов по 32 байта на каждый:

Элемент (повторяется n-раз, где n - общее количество элементов):

 4 байта  - DWORD	- смещение файла (в блоках) в .img архиве, относительно его начала
 4 байта  - DWORD 	- размер файла (в блоках) в .img архиве
24 байта  - CHAR[24] 	- имя файла

Сам IMG архив не имеет заголовка, просто файлы, как говорилось ранее, расположенные в блоках по 2 КБ.

Схема распределения файлов в IMG архиве

Версия 1А - GTA:LCS и GTA:VCS

Структура IMG-архива Stories не отличается от структуры версии 1. Отсутствует .dir файл (исключение - CUTS.IMG). Имена файлов, их смещение и размер содержатся в game.dtz архиве. То есть для того чтобы открыть такой архив нужно либо извлечь данные директории из GAME.DTZ, либо сделать .dir таблицу файлов самостоятельно (причем второй вариант оказался гораздо более простым и данная функция есть в YAIE - таблица директории формируется исходя из заголовков самих файлов).

Версия 2 - GTA SA

Архивы второй версии, используемые в GTA San Andreas, содержат .dir и .img файлы в одном IMG файле. Директория имеет такой же формат, как и в формате 1-ой версии, но располагается в начале IMG файла. Файлы так же размещены в блоках по 2 КБ. Смещения файлов задаются от начала самого архива, а не от конца списка файлов.

Заголовок:

 4 байта	 - CHAR[4]	- сигнатура архива, всегда имеет значение "VER2"
 4 байта	 - DWORD	- общее количество элементов (файлов)

Элемент: (повторяется n-раз, где n - общее количество элементов):

 4 байта - DWORD     - смещение файла (в блоках) в архиве
 4 байта - DWORD     - размер файла (в блоках)
24 байта - CHAR[24]  - имя файла

Недостаток этого формата - это его расширяемость. Если вы добавите слишком много файлов, директория начнёт записываться поверх первых файлов в архиве, поэтому вам нужно будет записывать первые файлы в конец архива.

Версия 3 - GTA IV

Данная версия архива имеет более сложную структуру. Общим со старыми версиями осталось только то, что файлы выравнены по размеру сектора (2048 байт). Каталог архива может быть зашифрован.

Заголовок

Заголовок файла всегда равен 20 байтам.

4 байта - DWORD      - Идентификатор (0xA94E2A52) Если, это поле имеет другое значение, архив зашифрован
4 байта - DWORD      - Версия (всегда 3)
4 байта - DWORD      - Количество объектов
4 байта - DWORD      - Размер каталога (в байтах)
2 байта - WORD       - Размер элемента каталога (всегда должен быть равен 0x10)
2 байта - WORD       - Неизвестно

Каталог архива

Каталог архива состоит из двух частей: описателей файлов, содержащих смещение и размер файла внутри архива и имен файлов.

В начале идет массив описателей по 16 байт:

4 байта - DWORD      - Размер объекта и флаги 
4 байта - DWORD      - Версия ресурса (только для RSC, для остальных объектов не используется)
4 байта - DWORD      - Смещение от начала IMG в блоках (2048 байт)
2 байта - WORD       - Количество используемых блоков
2 байта - WORD       - Размер неиспользуемого места в последнем блоке

За описателями следуют имена файлов, разделенные '\x0' (нулевым байтом), в том же порядке, что и описатели.

Чтение зашифрованных архивов

Если идентификатор архива не равен 0xA94E2A52, архив считается зашифрованным. Для чтения такого архива, следует прочитать заголовок (20 байт), но дешифровать только первые 16 байт. После этого, следует снова проверить идентификатор. Если идентификатор корректный, следует считать каталог (размер берется из расшифрованного заголовка) и дешифровать его, округлив размер до числа кратного 16, вниз. (Например, если указан размер 259 байт, дешифруются только первые 256).

Шифрование - стандартное для IV - AES.


п · о · р
Форматы файлов
GTA 4 GTA IV.dat.gxt.ide.img.ipl.nod.sco.rpf.rrr.wad.wbd/.wbn.wdd.wdr.wft.whm.wpl.wtd
GTA VCS VCS/LCS.anim.at3.chk.xtx.dtz.img.lvz.wrld.mdl.raw.scm
San Andreas GTA SA.dat.dff.gxt.ide.img.ipl.scm.rrr.txd
Vice City GTA VC.anm.adf.dat.dir.dff.gxt.ide.img.ipl.scm.txd