IPB

Добро пожаловать, гость ( Вход | Регистрация )

 
Reply to this topicStart new topic
> The Settlers (все части), Запнулся на сжатии
Siberian GRemlin
Jun 6 2007, 15:58
Сообщение #1


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Итак, пока есть время перед экзаменами и играть поднадоело + зависоны, я решил поковырять четвёртых Поселенцев, о чём давно мечтал. А точнее начал пока с формата [.LIB]. Но, вот? незадача, я думал, там обычный ZLib, но разжать не смог =( Порылся в файлах, нашёл RTComp.dll логично подумал, что Comp от Compress и, кажется, был прав в этом файле видны строчки с "zlib". Но почему-то у меня не получилось разжать файл. Погуглил на RT Compression и сокращения, нашёл только какую-то чушь (вроде) про Real-Time Compression.

Работаю с последней английской версией игры и версией от 1С. Демку можно скачать с AG.ru
CODE
program Settlers4_LIB_Info;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  Windows,
  Classes;
type
  TFAT = record
    Unknown1,
    Unknown2,
    Unknown3,
    FolderCount,
    Unknown5,
    FilesCount: Dword;
  end;
  TFileInfo = record
    Offset,
    PackedSize,
    UnPackedSize,
    FolderNum,
    IsPacked,
    CheckSum: Dword;
  end;
  TFile = record
    Name:String;
    Info:TFileInfo;
  end;
var
  MSTR: TMemoryStream;
  FATOffset: Dword;
  F:TFAT;
  Folders: array of string;
  Files: array of TFile;
  i,j: dword;
  outf: textfile;
begin
  Assign(outf,'D:\Games\The Settlers IV\gfx.txt');
  ReWrite(outf);
  MSTR:=TMemoryStream.Create;
  Mstr.LoadFromFile('D:\Games\The Settlers IV\gfx.lib');
  Mstr.Position:=Mstr.Size-4;
  Mstr.ReadBuffer(FATOffset,4);
  WriteLn(outf,'Header Offset: '+IntToHex(FATOffset,4));
  Mstr.Position:=FATOffset;
  Mstr.ReadBuffer(F,sizeof(f));
  WriteLn(outf);
  WriteLn(outf,'Unknown1: '+IntToStr(F.Unknown1));
  WriteLn(outf,'Unknown2: '+IntToStr(F.Unknown2));
  WriteLn(outf,'Unknown3: '+IntToStr(F.Unknown3));
  WriteLn(outf,'Folder Count: '+IntToStr(F.FolderCount));
  WriteLn(outf,'Unknown5: '+IntToStr(F.Unknown5));
  WriteLn(outf,'Files Count: '+IntToStr(F.FilesCount));
//папки
  SetLength(Folders,F.FolderCount);
  for i:=1 to F.FolderCount do begin
    j:=1;
    SetLength(Folders[i-1],1);
    Repeat
      Mstr.ReadBuffer(Folders[i-1][j],1);
      inc(j);
      SetLength(Folders[i-1],Length(Folders[i-1])+1);
    Until ord(Folders[i-1][j-1])=0;
    SetLength(Folders[i-1],Length(Folders[i-1])-2);
  end;
//файлы
  SetLength(Files,F.FilesCount);
  for i:=1 to F.FilesCount do begin
    j:=1;
    SetLength(Files[i-1].Name,1);
    Repeat
      Mstr.ReadBuffer(Files[i-1].Name[j],1);
      inc(j);
      SetLength(Files[i-1].Name,Length(Files[i-1].Name)+1);
    Until ord(Files[i-1].Name[j-1])=0;
    SetLength(Files[i-1].Name,Length(Files[i-1].Name)-2);
  end;
//данные
  for i:=1 to F.FilesCount-1 do begin
    Writeln(outf);
    Mstr.ReadBuffer(Files[i-1].Info,sizeof(Files[i-1].Info));
    if F.FolderCount>1 then
    WriteLn(outf,IntToStr(i)+': '+Folders[Files[i-1].Info.FolderNum]+'\'+Files[i-1].Name)
    else
    WriteLn(outf,IntToStr(i)+': '+Folders[0]+'\'+Files[i-1].Name);
    WriteLn(outf,Format('Offset: %s Packed Size: %s UnPacked Size: %s Compressed: %s ?ChekSum?: %s',[IntToHex(Files[i-1].Info.Offset,8),IntToHex(Files[i-1].Info.PackedSize,8), IntToHex(Files[i-1].Info.UnPackedSize,8),IntToHex(Files[i-1].Info.IsPacked,1), IntToHex(Files[i-1].Info.CheckSum,8)]));
  end;
  Mstr.Free;
  CloseFile(outf);
  WriteLn('Complete!');
  Readln;
end.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Jun 7 2007, 04:29
Сообщение #2


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Поковырялся ещё. Оказалось в GFX.LIB последней английской версии игры, указатель на номер папки хранит вобще левое значение. У того же файла в версии от Фирмы "1С" такого нету. Немного исправил код, чтобы работал с таким вариантом - схитрил немного, но пока это единственный для меня вариант. Если кто, что найдёт - сообщайте. Также разобрал архив со звуками. Графика вроде, тоже по такому же принципу и не сложно, но у меня с ней не всегда лады, особенно с палитрой.
CODE
program Settlers4_SND;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  Windows,
  Classes;
type
  TFileInfo = record
    Offset,
    Flag,
    PackedSize: DWord;
  end;
  THeader = record
    ArcType,
    Unknown1,
    Unknown2,
    Unknown3,
    Unknown4,
    Unknown5:Dword;
  end;
var
  MSTR,TmpStr: TMemoryStream;
  F:THeader;
  Files: array of TFileInfo;
  i: dword;
  outf: textfile;
begin
  Assign(outf,'D:\Games\The Settlers IV\snd\0.txt');
  ReWrite(outf);
  MSTR:=TMemoryStream.Create;
  Mstr.LoadFromFile('D:\Games\The Settlers IV\snd\0.sil');
  Mstr.Position:=0;
  Mstr.ReadBuffer(F,sizeof(f));
  WriteLn(outf,'Archive Type: '+IntToStr(F.ArcType));
  WriteLn(outf,'Unknown1: '+IntToStr(F.Unknown1));
  WriteLn(outf,'Unknown2: '+IntToStr(F.Unknown2));
  WriteLn(outf,'Unknown3: '+IntToStr(F.Unknown3));
  WriteLn(outf,'Unknown4: '+IntToStr(F.Unknown4));
  WriteLn(outf,'Unknown5: '+IntToStr(F.Unknown5));
//Смещения
  SetLength(Files,1);
  Repeat
    Mstr.ReadBuffer(Files[Length(Files)-1].Offset,4);
    SetLength(Files,Length(Files)+1);
  Until Mstr.Position=Mstr.Size;
  SetLength(Files,Length(Files)-2);
  Mstr.Free;
//Файлы
  MSTR:=TMemoryStream.Create;
  Mstr.LoadFromFile('D:\Games\The Settlers IV\snd\0.snd');
  Mstr.Position:=0;
  Mstr.ReadBuffer(F,sizeof(f));
  WriteLn(outf,'Archive Type: '+IntToStr(F.ArcType));
  WriteLn(outf,'Unknown1: '+IntToStr(F.Unknown1));
  WriteLn(outf,'Unknown2: '+IntToStr(F.Unknown2));
  WriteLn(outf,'Unknown3: '+IntToStr(F.Unknown3));
  WriteLn(outf,'Unknown4: '+IntToStr(F.Unknown4));
  Mstr.Position:=Mstr.Position-4;
  for i:=0 to Length(Files)-1 do begin
    Mstr.ReadBuffer(Files[i].Flag,4);
    Mstr.ReadBuffer(Files[i].PackedSize,4);
    TmpStr:=TMemoryStream.Create;
    TmpStr.Position:=0;
    TmpStr.CopyFrom(Mstr,Files[i].PackedSize);
    TmpStr.SaveToFile(Format('D:\Games\The Settlers IV\Snd\unpacked\%3d.wav',[i{IntToStr(i)}]));
    TmpStr.Free;
    Writeln(i);
    Writeln(outf,IntToStr(i)+': Offset: '+IntToHex(Files[i].Offset,8)+': Flag: '+IntToHex(Files[i].Flag,8)+': Size: '+IntToHex(Files[i].PackedSize,8));
  end;
  WriteLn('Last Position: '+IntTostr(Mstr.Position)+' File Size: '+IntTostr(Mstr.Size)+' Missed bytes: '+IntTostr(Mstr.Size-Mstr.Position));
  Mstr.Free;
  CloseFile(outf);
  WriteLn('Complete!');
  Readln;
end.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
jTommy
Jun 8 2007, 13:11
Сообщение #3


Наблюдающий
***

Группа: CTPAX-X
Сообщений: 197
Регистрация: 4-February 08
Из: деревня Москва
Пользователь №: 6
Спасибо сказали: 19 раз(а)



Раздобыл полную версию. Заодно и пятую часть скачал.
Посмотрел. Если там и есть сжатие, то это точно не zlib. Надо разбираться. А тот zlib, который ты нашел, используется для поддержки PNG графики.

Вот в пятой части точно zlib, но за-то имен файлов в открытом виде нет. Да и FAT/TOC тоже не наблюдается.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Jun 14 2007, 03:59
Сообщение #4


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Ты уверен, что в пятой zlib? т.к. на wiki.xentax была инфа что там вобще какой-то левый алгоритм сжатия.

Если zlib, то надо поколупать - я на днях золотое издание купил =) Там даже защиты от копирования нету - я так рад, что ломать не надо и/или образы в алкоголе делать!
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
jTommy
Jun 14 2007, 20:04
Сообщение #5


Наблюдающий
***

Группа: CTPAX-X
Сообщений: 197
Регистрация: 4-February 08
Из: деревня Москва
Пользователь №: 6
Спасибо сказали: 19 раз(а)



QUOTE(Siberian GRemlin @ Jun 14 2007, 07:59 AM) *
Ты уверен, что в пятой zlib? т.к. на wiki.xentax была инфа что там вобще какой-то левый алгоритм сжатия.
Да, уверен. Во-первых ее просто видно по сигнатуре. Во-вторых STUNS находит и распаковывает огромное кол-во файлов.

QUOTE(Siberian GRemlin @ Jun 14 2007, 07:59 AM) *
Если zlib, то надо поколупать - я на днях золотое издание купил =) Там даже защиты от копирования нету - я так рад, что ломать не надо и/или образы в алкоголе делать!
Вот только я не нашел TOC aka FAT. Возможно она тоже упакована zlib'ом.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Jun 15 2007, 05:59
Сообщение #6


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Я думал, ты меня сразу носом натыкаешь! =)
Я спутал, я читал на wiki.xentax про алгоритм шифровки заголовка + там есть описание самого заголовка: http://wiki.xentax.com/index.php/Settlers_...ritage_Of_Kings
Вот здесь про алгоритм и код на си: http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm

Ваши предложения?
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Jun 17 2007, 13:48
Сообщение #7


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Вот, на нашем родном языке =)
http://www.shokhirev.com/nikolai/programs/...TeaSet_pas.html

-=CHE@TER=-
Переименуй, пожалуйста, тему в "The Settlers (Все части)"

Всем, кто ещё дышит
У меня экзамен через 36 часов где-то, а я ещё не готовился даже... какой ужас! А ещё только что обнаружил, что у меня не все лекции!

Но я тут колупал два формата графики The Settlers 2... дак, вот если есть кто дышит, то не могу понять что тут за один извращённый формат графики. Каждая строчка картинки разной ширины, но вместо их ширины есть только смещения до их начала. А вот как их рисовать не понятно, в одних рисунках д.б. выравнивание на лево, а других по центру, как я понял, но где это написано неясно. Дак вот, у меня косячит выравнивание по центру у файла cast_01 и подобных.

Вот код + примеров пачка
Пароль: www.Васю_Зашкурирло.ru
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Oct 3 2018, 07:03
Сообщение #8


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Вернулся к разбору четвёртой части. Демо-версия.

Файлы в архивах зашифрованы, а сжатие похоже на LZ. Кто-нибудь может посмотреть точнее? Особенно шифрование. Интересует файл game.lib.

CODE
Procedure Extractor(name_in: string);
var
  Mstr, OutStr: TMemoryStream;
  i, Offset, Unk1, Unk2, FolderSz, FolderCnt, FilesSz, FilesCnt: LongWord;
  Folders, Files: array of string;
  FileInfo: array of record
    Offset,
    PackedSize,
    UnPackedSize,
    FolderNum,
    IsPacked,
    CheckSum: LongWord;
  end;
begin
  if FileExists(name_in) then begin
    Mstr:=TMemoryStream.Create;//(name_in, fmOpenRead);
    Mstr.LoadFromFile(name_in);
    Mstr.Position:=Mstr.Size-4;
    Mstr.ReadBuffer(Offset,4);
    Mstr.Position:=Offset;
    Mstr.ReadBuffer(Unk1,4);
    Mstr.ReadBuffer(Unk2,4);
    Mstr.ReadBuffer(FolderSz,4);
    Mstr.ReadBuffer(FolderCnt,4);
    Mstr.ReadBuffer(FilesSz,4);
    Mstr.ReadBuffer(FilesCnt,4);
    Writeln(inttohex(Unk1,8),' | ',inttohex(Unk2,8),' | ',inttohex(FolderSz,8),' | ',inttohex(FolderCnt,8),' | ',inttohex(FilesSz,8),' | ',inttohex(FilesCnt,8));
    SetLength(Folders,FolderCnt);
    for i:=0 to FolderCnt-1 do begin
      Folders[i]:=ReadStr(Mstr);
      Writeln(i,': ',Folders[i]);
    end;
    SetLength(Files,FilesCnt);
    for i:=0 to FilesCnt-1 do begin
      Files[i]:=ReadStr(Mstr);
      Writeln(i,': ',Files[i]);
    end;
    SetLength(FileInfo,FilesCnt);
    for i:=0 to FilesCnt-1 do begin
      Mstr.ReadBuffer(FileInfo[i].Offset,4);
      Mstr.ReadBuffer(FileInfo[i].PackedSize,4);
      Mstr.ReadBuffer(FileInfo[i].UnPackedSize,4);
      Mstr.ReadBuffer(FileInfo[i].FolderNum,4);
      Mstr.ReadBuffer(FileInfo[i].IsPacked,4);
      Mstr.ReadBuffer(FileInfo[i].CheckSum,4);

      WriteLn(inttohex(FileInfo[i].Offset,8),' ',inttohex(FileInfo[i].PackedSize,8),' ',inttohex(FileInfo[i].UnPackedSize,8),' ',inttohex(FileInfo[i].FolderNum,8),' ',inttohex(FileInfo[i].IsPacked,8),' ',inttohex(FileInfo[i].CheckSum,8));
      WriteLn(Folders[FileInfo[i].FolderNum],'\',Files[i]);
    end;

    for i:=0 to FilesCnt-1 do begin
      Mstr.Position:=FileInfo[i].Offset;
      OutStr:=TMemoryStream.Create;
      OutStr.CopyFrom(Mstr,FileInfo[i].PackedSize);
      Recreate(Folders[FileInfo[i].FolderNum]+'\'+Files[i]);
      OutStr.SaveToFile(Folders[FileInfo[i].FolderNum and $FFFF]+'\'+Files[i]);
      OutStr.Free;
    end;

    Mstr.Free;
  end;
end;
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Oct 3 2018, 18:31
Сообщение #9


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,197
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 286 раз(а)



Там, действительно, какая-то модификация LZW, пришлось на ассемблере выдирать.
unlibs4.zip
Я так задолбался выдирая распаковку (там же ср@ные классы, где регистр ecx указывает на структуру, в которой хрен пойми что лежит - т.е. ты не можешь вот так просто взять и выдрать код распаковки), что на расшифровку забил. В demo ничего не шифровали, так что сделай при распаковке перенаправление вывода в файл (unlibs4.exe filename.lib > output.txt) и смотри, есть ли там "Warning: encrypted file, but decryption not supported - saving as is." и, если есть, то выложи куда-нибудь самый мелкий такой архив посмотреть.

CODE
#pragma pack(push, 1)
typedef struct {
DWORD headsize; // размер заголовка со всеми таблицами
DWORD revision; // должно быть равно 0x1000 иначе игра считает архив битым
DWORD dnamelen; // длина блока с именами директорий
DWORD dcounter; // количество директорий в блоке
DWORD fnamelen; // длина блока с именами файлов
DWORD fcounter; // количество файлов
} headinfo;

// после этого идут char[dnamelen] и char[fnamelen]
// затем описание файлов fcounter раз:

typedef struct {
DWORD floffs; // смещение файла, минимальное 1 (.LIB всегда должен начинаться с нулевого байта)
DWORD pksize; // упакованный размер
DWORD unsize; // распакованный размер (0 если не упакован)
DWORD dindex; // номер директории в массиве строк выше
DWORD xflags; // флаги: 1 - упакован; 2 - зашифрован (расшифровывать, ПЕРЕД, распаковкой)
DWORD crcsum; // контрольная сумма (16 бит), может быть ноль (только для запакованных?)
} fileinfo;
#pragma pack(pop)
Распаковка идёт так:
1) Проверка контрольной суммы, если она не ноль.
2) Если контрольная сумма совпала или ноль, то расшировать если (xflags & 2).
3) Если задан флаг (xflags & 1), то распаковать.
В принципе, игра не использует файлы из архива, если нужные уже есть на диске в соответствующем подкаталоге - т.е. достаточно распаковать и всё, можно переводить.

P.S. Как экзамен-то сдал? (*улыбается*)
P.P.S. Если не сложно, можешь чего-нибудь на копилку закинуть - мы на этой неделе как раз оплачивать хостинг будем. Спасибо.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Oct 3 2018, 18:58
Сообщение #10


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Спасибо. Наконец-то адаптирую переводы под последнюю версию и буду готов к переизданию в ноябре.

Да, я знаю, что игра сначала проверят файлы в папке, а потом лезет в архив.

На кошелёк «Яндекса» с главной страницы кину.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Oct 5 2018, 15:03
Сообщение #11


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Можешь проверить - у тебя кириллица будет в демке отображаться или нет?
txt.7z

Не могу найти причину, почему у меня отображается, а на другом ПК - нет. Возможно, из-за какого-то параметра в реестре. Причём, у себя не могу добиться, чтобы кириллица перестала отображаться. Игра использует жирный Arial (guiengine2.dll), но у меня он родной, как и на другом ПК. Системный язык не влияет.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Oct 5 2018, 19:44
Сообщение #12


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,197
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 286 раз(а)



Проверил. Закинул твой файл в демку, меню стало на русском, прошёл первое обучение, там тоже всё на русском, проблем не заметил. Русский Windows XP SP3 + все дополнения (официальные, POS Ready не ставил).
Может на другом ПК что-то перекосило, вот русский шрифт и не грузится?
А ещё заглянул в упомянутый тобой guiengine2.dll от demo в IDA, там в IGuiEngine::Init такой код:
CODE
<...>
  nCharSet = 0; // ANSI_CHARSET
  switch (a7) {
    case 16:
      nCharSet = 204; // RUSSIAN_CHARSET
      break;
    case 5:
    case 11:
    case 13:
      nCharSet = 238; // EASTEUROPE_CHARSET
      break;
    default:
      break;
  }
  v9 = &h;
  pFntData = (BYTE *)&unk_18809900;
  do {
    if (*v9) { DeleteObject(*v9); }
    v11 = CreateFontA(
            *((_DWORD *)pFntData - 8),
            *((_DWORD *)pFntData - 7),
            0,
            0,
            *((_DWORD *)pFntData - 6),
            0,
            0,
            0,
            nCharSet,
            0,
            0,
            *pFntData != 0 ? 4 : 0,
            0,
            (LPCSTR)pFntData + 2);
    *v9 = v11;
    if (!v11) { BBSupportTracePrintF(0, aGuiEngineCan_2); }
    pFntData += 84;
    v9++;
  } while ( (signed int)pFntData < (signed int)&unk_18809F3C );
<...>

Как я понимаю ANSI_CHARSET = RUSSIAN_CHARSET, если в системе установлен русский язык.
Можно попробовать либо 238 на 204 заменить, либо сделать так, чтобы всегда 204 было.
А ещё можно посмотреть откуда лезет параметр a7 входной со значениями 5, 11 или 13 - может в ресурсах где-то язык задаётся, а потом этот номер в эту функцию уходит.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Oct 5 2018, 20:51
Сообщение #13


Advanced Member
***

Группа: CTPAX-X
Сообщений: 473
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 201 раз(а)



Спасибо. Вроде бы разобрался. Теперь надо проверить на всех ПК.

a7 это язык игры, который хранится в текстовике MiscData1.cfg. Локализации лежат в этих файлах с номерами. 0 - английский, 1 - немецкий, и так далее. Прописал 13 — язык стал чешским и подменил файл с ним, а кириллица перестала отображаться.


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 16th June 2019 - 19:06