Формат Sims3Pack и его декодирование: Часть практическая, реализация декодера

Формат Sims3Pack и его декодирование: Часть практическая, реализация декодера
Автор: AnriRS

Реализация декодирования формата Sims3Pack содержится в файле siS3PackDecoder.pas

Статьи по теме

Реализация декодера

Декодер представляет собой наследника класса TComponent и может (и должен во избежание багов с парсером xml) устанавливаться на форму. Для работы с исходным файлом используется первичный поток, в его качестве допустим любой (естественно неабстрактный) потомок TStream; он должен быть создан и файл загружен в него – сделано это для того чтобы не привязываться к размещению исходного файла. Для освобождения первичного потока нельзя использовать его "родные" методы, для этого используется метод FreeStream декодера.

type
TS3PackDecoder = class(TComponent)
...
protected
function Alloc: TS3PackItem;
// добавляет запись в индексную таблицу и возвращает ее
public
constructor Create(AOwner: TComponent); override; // контруктор класса
destructor Destroy; override; // деструктор класса
procedure FreeStream;
// освобождает вторичные потоки, освобождает первичный поток
procedure Decode(AReader: TStream);
// связывает поток декодирования, декодирует индексную таблицу
property Items: TS3PackItems read; // декодированная индексная таблица
property Count: integer read; // число записей в индекной таблице
property Header: TS3PackHeader read; // заголовок файла
property PackageName: string read; // имя пакета
property PackageDescription: string read; // описание пакета
end; // TS3PackDecoder class

Свойства

  • Items: TS3PackItems – массив записей по каждому из файлов в пакете;
  • Count: integer – число файлов в пакете;
  • Header: TS3PackHeader – заголовок пакета, содержит те самые 17 байт, категорически не рекомендуется лезть в него грязными руками (чистыми, кстати, тоже) – свойство информационное для отладки;
  • PackageName: string, имя пакета, если есть русская локализация, то берется из LocalizedNames\ru-RU, иначе какая есть (обычно английская) из DisplayName манифеста;
  • PackageDescription: string, описание пакета, если есть русская локализация, то берется из LocalizedDescriptions\ru-RU, иначе какая есть (обычно английская) из Description манифеста;

Методы

constructor Create (AOwner: TComponent) – конструктор класса;

destructor Destroy – виртуальный деструктор освобождает все связанные потоки (и первичный и вторичные) – естественно вместо него лучше использовать метод Free;

 

procedure FreeStream – освобождает вторичные потоки, освобождает первичный поток, после его вызова нельзя использовать остальные поля и методы для данного файла, для освобождения потока нельзя использовать его "родные" методы;

procedure Decode(AReader: TStream) – связывает поток декодирования с декодером, декодирует индексную таблицу, должен вызывается первым, все остальные поля и методы используются после нее, до ее вызова состояние полей неопределенно, кроме Count, который равен 0;

 

function Alloc: TS3PackItem – защищенный метод, увеличивает индексную запись на один элемент и вызывает его конструктор;

Пример использования

Практическое использование может быть, например, такое:

procedure TfrmMain.btnSims3PackClick(Sender: TObject);
var
i:integer;
begin
if not dlgOpenS3Pack.Execute then exit;
lstLog.Clear;
S3PackDecoder.Decode(
TFileStream.Create(dlgOpenS3Pack.FileName, fmOpenRead)); // (1)
AddDebug('file=%s', [dlgOpenS3Pack.FileName]); // (2)
AddDebug('name=%s', [S3PackDecoder.PackageName]);
AddDebug('description=%s', [S3PackDecoder.PackageDescription]);
AddDebug('-------------------', []);
barProgress.Max:= S3PackDecoder.Count-1;
Application.ProcessMessages;
for i:= 0 to S3PackDecoder.Count-1 do with S3PackDecoder.Items[i] do begin // (3)
AddDebug('name=%s', [FileName]); // (4)
AddDebug(' offset=%.6Xh, size=%.6Xh, type=%s', [Offset, Length, ContentType]);
Decode(TMemoryStream.Create); // (5)
Stream.SaveToFile('unpack\'+FileName);
FreeStream;
barProgress.Position:= i;
Application.ProcessMessages;
end;
S3PackDecoder.FreeStream; // (6)
end;

В примере, выбранный пользователем файл:

  1. открывается и декодируется;

  2. в лог добавляются данные манифеста;

  3. затем для каждой записи:

  4. - в лог добавляются данные о ней;

  5. - она декодируется и сохраняется на диск;

  6. первичный поток закрывается;

Пример довольно условный, т.к. для записи на диск TFileStream подходит лучше – зато иллюстрирует правильное создание, доступ и уничтожение вторичных потоков.

Обратите внимание на необходимость использования вызова Application.ProcessMessages в теле цикла декодирования, в случае его отсутствия при больших файлах заметна "заморозка" программы.

The Sims 3

The Sims 2

The Sims

MySims

Sims-игры

Даты релизов

the_sims_3_store_saleshymn_bunnersimovod_3simovod2Журнал «Симовод»Prosims - магазин сувениров