![]() |
Добро пожаловать, гость ( Вход | Регистрация )
![]() |
Siberian GRemlin |
![]() ![]()
Сообщение
#1
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 222 раз(а) ![]() |
Итак, пока есть время перед экзаменами и играть поднадоело + зависоны, я решил поковырять четвёртых Поселенцев, о чём давно мечтал. А точнее начал пока с формата [.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 |
![]()
Сообщение
#2
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 222 раз(а) ![]() |
Поковырялся ещё. Оказалось в 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. |
![]() ![]() |
Упрощённая версия | Сейчас: 1st May 2025 - 01:13 |