Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Compression;
- using System.Linq;
- using System.Text;
- namespace Mygod.LittleInferno.Resource.Unpacker
- {
- public class Program
- {
- private static void Main(string[] args)
- {
- if (args == null || args.Length == 0)
- {
- Console.WriteLine("Drag files onto the program to start unpacking!");
- Console.ReadKey();
- return;
- }
- var output = new StreamWriter(File.Create("output.txt"));
- Console.SetOut(output);
- const string directory = "EXTRACTED";
- const string temp = directory + "_TEMP";
- Directory.CreateDirectory(directory);
- Directory.CreateDirectory(temp);
- Package lastPackage = null;
- foreach (var arg in args.Where(File.Exists))
- {
- Console.WriteLine("INFO: Unpacking file: {0}", arg);
- ErrorCount = WarningCount = 0;
- InformationCount = 1;
- try
- {
- (lastPackage = new Package(arg)).ExtractAll(temp);
- }
- catch (Exception exc)
- {
- Console.WriteLine("ERROR: {0}", exc.Message);
- ErrorCount++;
- }
- Console.WriteLine("Unpacking done. {0} error(s), {1} warning(s), {2} info(s).", ErrorCount, WarningCount, InformationCount);
- Console.WriteLine();
- }
- if (lastPackage != null) lastPackage.MoveFiles(directory, temp);
- output.Close();
- }
- public static int ErrorCount, WarningCount, InformationCount;
- }
- public class Package : IDisposable
- {
- public Package(string filePath)
- {
- path = filePath;
- stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
- if (!stream.CanRead || !stream.CanSeek) throw new NotSupportedException("The file stream is terrible!");
- reader = new BinaryReader(stream);
- PackageVersion = reader.ReadInt32();
- if (PackageVersion != 1) throw new NotSupportedException("Unsupported package version: " + PackageVersion);
- var count = reader.ReadInt32();
- Records = new List<FileRecord>(count);
- for (var i = 0; i < count; i++) Records.Add(new FileRecord(reader));
- }
- private static string ReadString(BinaryReader reader)
- {
- var strBytes = new List<byte>();
- int b;
- while ((b = reader.ReadByte()) > 0) strBytes.Add((byte)b);
- return Encoding.UTF8.GetString(strBytes.ToArray());
- }
- public void ExtractAll(string directory)
- {
- foreach (var record in Records) Extract(record, Path.Combine(directory, record.ID.ToString()));
- }
- public void Extract(FileRecord record, string filePath)
- {
- int unpackedSize;
- byte[] data;
- lock (reader)
- {
- stream.Seek(record.Offset, SeekOrigin.Begin);
- var packedSize = reader.ReadInt32();
- unpackedSize = reader.ReadInt32();
- data = reader.ReadBytes(packedSize);
- }
- if (record.Flags == 0)
- {
- File.WriteAllBytes(filePath, data);
- Console.WriteLine("INFO: Unpacking item #{0} done.", record.ID);
- Program.InformationCount++;
- return;
- }
- using (var fileStream = File.Create(filePath))
- using (var memoryStream = new MemoryStream(data))
- using (var deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress))
- {
- memoryStream.ReadByte();
- memoryStream.ReadByte();
- try
- {
- deflateStream.CopyTo(fileStream);
- if (fileStream.Length != unpackedSize)
- {
- Console.WriteLine("WARNING: File size does not match. (item #{0})", record.ID);
- Program.WarningCount++;
- }
- Console.WriteLine("INFO: Unpacking item #{0} done.", record.ID);
- Program.InformationCount++;
- }
- catch (InvalidDataException)
- {
- Console.WriteLine("ERROR: Unpacking item #{0} failed.", record.ID);
- Program.ErrorCount++;
- }
- }
- }
- public void MoveFiles(string directory, string temp)
- {
- var map = Path.Combine(temp, "3085189639");
- if (!File.Exists(map))
- {
- Console.WriteLine("ERROR: Maps not found!");
- Program.ErrorCount++;
- return;
- }
- using (var fileStream = new FileStream(map, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- if (!fileStream.CanRead || !fileStream.CanSeek) throw new NotSupportedException("The file stream is terrible!");
- using (var mapReader = new BinaryReader(fileStream))
- {
- BinaryHeaderPointer maps = new BinaryHeaderPointer(mapReader), stringTableBytes = new BinaryHeaderPointer(mapReader);
- fileStream.Seek(maps.Offset, SeekOrigin.Begin);
- var dic = new Dictionary<uint, int>(maps.Count);
- for (var i = 0; i < maps.Count; i++) dic.Add(mapReader.ReadUInt32(), mapReader.ReadInt32());
- fileStream.Seek(stringTableBytes.Offset, SeekOrigin.Begin);
- int numStrings = mapReader.ReadInt32(), numPointers = mapReader.ReadInt32();
- var stringPointers = new List<StringPointer>(numStrings);
- for (var i = 0; i < numStrings; i++) stringPointers.Add(new StringPointer(mapReader));
- var pointerPointers = new List<LanguagePointer>(numPointers);
- for (var i = 0; i < numPointers; i++) pointerPointers.Add(new LanguagePointer(mapReader));
- var baseOffset = fileStream.Position;
- // Console.WriteLine(pointerPointers.Min(p => p.Offset)); // for debugging purpose
- foreach (var file in new DirectoryInfo(temp).EnumerateFiles())
- {
- try
- {
- var id = uint.Parse(file.Name);
- var stringPointer = stringPointers[dic[id]];
- var pointer = default(LanguagePointer);
- for (var i = 0; i < stringPointer.Count; i++)
- {
- pointer = pointerPointers[stringPointer.Index + i];
- if (pointer.LanguageID == 25966) break; // ne
- }
- if (pointer.LanguageID != 25966) throw new Exception("Language ne not found!");
- fileStream.Seek(baseOffset + pointer.Offset, SeekOrigin.Begin);
- string realPath = ReadString(mapReader), absolutePath = Path.Combine(directory, realPath);
- Directory.CreateDirectory(Path.GetDirectoryName(absolutePath));
- file.MoveTo(absolutePath);
- Console.WriteLine("INFO: File moved successfully: {0}", realPath);
- Program.InformationCount++;
- }
- catch (Exception exc)
- {
- Console.WriteLine("ERROR: ({0}) {1}", exc.GetType(), exc.Message);
- Program.ErrorCount++;
- }
- }
- }
- }
- }
- public void Dispose()
- {
- reader.Close();
- stream.Close();
- }
- private readonly FileStream stream;
- private readonly BinaryReader reader;
- private readonly string path;
- public int PackageVersion;
- public List<FileRecord> Records;
- }
- public struct FileRecord
- {
- public uint ID, Flags;
- public int Offset, Size;
- public FileRecord(BinaryReader reader)
- {
- ID = reader.ReadUInt32();
- Flags = reader.ReadUInt32();
- if (Flags > 1)
- {
- //throw new NotSupportedException("Unsupported file record flags: " + Flags);
- Console.WriteLine("WARNING: Unsupported file record flags value {0}. (item #{1})", Flags, ID);
- Program.WarningCount++;
- }
- Offset = reader.ReadInt32();
- Size = reader.ReadInt32();
- }
- }
- public struct BinaryHeaderPointer
- {
- public int Count, Offset;
- public BinaryHeaderPointer(BinaryReader reader)
- {
- Count = reader.ReadInt32();
- Offset = reader.ReadInt32();
- }
- }
- public struct StringPointer
- {
- public int Index, Count;
- public StringPointer(BinaryReader reader)
- {
- Index = reader.ReadInt32();
- Count = reader.ReadInt32();
- }
- }
- public struct LanguagePointer
- {
- public uint LanguageID;
- public int Offset;
- public LanguagePointer(BinaryReader reader)
- {
- LanguageID = reader.ReadUInt32();
- Offset = reader.ReadInt32();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement