The Settlers (все части), Запнулся на сжатии |
Добро пожаловать, гость ( Вход | Регистрация )
The Settlers (все части), Запнулся на сжатии |
Siberian GRemlin |
Jun 6 2007, 15:58
Сообщение
#1
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Итак, пока есть время перед экзаменами и играть поднадоело + зависоны, я решил поковырять четвёртых Поселенцев, о чём давно мечтал. А точнее начал пока с формата [.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. |
Siberian GRemlin |
Jun 7 2007, 04:29
Сообщение
#2
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Поковырялся ещё. Оказалось в 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. |
jTommy |
Jun 8 2007, 13:11
Сообщение
#3
|
Наблюдающий Группа: CTPAX-X Сообщений: 197 Регистрация: 4-February 08 Из: деревня Москва Пользователь №: 6 Спасибо сказали: 19 раз(а) |
Раздобыл полную версию. Заодно и пятую часть скачал.
Посмотрел. Если там и есть сжатие, то это точно не zlib. Надо разбираться. А тот zlib, который ты нашел, используется для поддержки PNG графики. Вот в пятой части точно zlib, но за-то имен файлов в открытом виде нет. Да и FAT/TOC тоже не наблюдается. |
Siberian GRemlin |
Jun 14 2007, 03:59
Сообщение
#4
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Ты уверен, что в пятой zlib? т.к. на wiki.xentax была инфа что там вобще какой-то левый алгоритм сжатия.
Если zlib, то надо поколупать - я на днях золотое издание купил =) Там даже защиты от копирования нету - я так рад, что ломать не надо и/или образы в алкоголе делать! |
jTommy |
Jun 14 2007, 20:04
Сообщение
#5
|
Наблюдающий Группа: CTPAX-X Сообщений: 197 Регистрация: 4-February 08 Из: деревня Москва Пользователь №: 6 Спасибо сказали: 19 раз(а) |
Ты уверен, что в пятой zlib? т.к. на wiki.xentax была инфа что там вобще какой-то левый алгоритм сжатия. Да, уверен. Во-первых ее просто видно по сигнатуре. Во-вторых STUNS находит и распаковывает огромное кол-во файлов.Если zlib, то надо поколупать - я на днях золотое издание купил =) Там даже защиты от копирования нету - я так рад, что ломать не надо и/или образы в алкоголе делать! Вот только я не нашел TOC aka FAT. Возможно она тоже упакована zlib'ом. |
Siberian GRemlin |
Jun 15 2007, 05:59
Сообщение
#6
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Я думал, ты меня сразу носом натыкаешь! =)
Я спутал, я читал на wiki.xentax про алгоритм шифровки заголовка + там есть описание самого заголовка: http://wiki.xentax.com/index.php/Settlers_...ritage_Of_Kings Вот здесь про алгоритм и код на си: http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm Ваши предложения? |
Siberian GRemlin |
Jun 17 2007, 13:48
Сообщение
#7
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Вот, на нашем родном языке =)
http://www.shokhirev.com/nikolai/programs/...TeaSet_pas.html -=CHE@TER=- Переименуй, пожалуйста, тему в "The Settlers (Все части)" Всем, кто ещё дышит У меня экзамен через 36 часов где-то, а я ещё не готовился даже... какой ужас! А ещё только что обнаружил, что у меня не все лекции! Но я тут колупал два формата графики The Settlers 2... дак, вот если есть кто дышит, то не могу понять что тут за один извращённый формат графики. Каждая строчка картинки разной ширины, но вместо их ширины есть только смещения до их начала. А вот как их рисовать не понятно, в одних рисунках д.б. выравнивание на лево, а других по центру, как я понял, но где это написано неясно. Дак вот, у меня косячит выравнивание по центру у файла cast_01 и подобных. Вот код + примеров пачка Пароль: www.Васю_Зашкурирло.ru |
Siberian GRemlin |
Oct 3 2018, 07:03
Сообщение
#8
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Вернулся к разбору четвёртой части. Демо-версия.
Файлы в архивах зашифрованы, а сжатие похоже на 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; |
-=CHE@TER=- |
Oct 3 2018, 18:31
Сообщение
#9
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Там, действительно, какая-то модификация 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. Если не сложно, можешь чего-нибудь на копилку закинуть - мы на этой неделе как раз оплачивать хостинг будем. Спасибо. Спасибо сказали:
|
Siberian GRemlin |
Oct 3 2018, 18:58
Сообщение
#10
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Спасибо. Наконец-то адаптирую переводы под последнюю версию и буду готов к переизданию в ноябре.
Да, я знаю, что игра сначала проверят файлы в папке, а потом лезет в архив. На кошелёк «Яндекса» с главной страницы кину. Спасибо сказали:
|
Siberian GRemlin |
Oct 5 2018, 15:03
Сообщение
#11
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Можешь проверить - у тебя кириллица будет в демке отображаться или нет?
txt.7z Не могу найти причину, почему у меня отображается, а на другом ПК - нет. Возможно, из-за какого-то параметра в реестре. Причём, у себя не могу добиться, чтобы кириллица перестала отображаться. Игра использует жирный Arial (guiengine2.dll), но у меня он родной, как и на другом ПК. Системный язык не влияет. |
-=CHE@TER=- |
Oct 5 2018, 19:44
Сообщение
#12
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Проверил. Закинул твой файл в демку, меню стало на русском, прошёл первое обучение, там тоже всё на русском, проблем не заметил. Русский 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 - может в ресурсах где-то язык задаётся, а потом этот номер в эту функцию уходит. Спасибо сказали:
|
Siberian GRemlin |
Oct 5 2018, 20:51
Сообщение
#13
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Спасибо. Вроде бы разобрался. Теперь надо проверить на всех ПК.
a7 это язык игры, который хранится в текстовике MiscData1.cfg. Локализации лежат в этих файлах с номерами. 0 - английский, 1 - немецкий, и так далее. Прописал 13 — язык стал чешским и подменил файл с ним, а кириллица перестала отображаться. Спасибо сказали:
|
Упрощённая версия | Сейчас: 1st November 2024 - 22:35 |