Advertisement
Mygod

Little Inferno Resource Unpacker Source

Dec 6th, 2012
348
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.72 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.IO.Compression;
  5. using System.Linq;
  6. using System.Text;
  7.  
  8. namespace Mygod.LittleInferno.Resource.Unpacker
  9. {
  10.     public class Program
  11.     {
  12.         private static void Main(string[] args)
  13.         {
  14.             if (args == null || args.Length == 0)
  15.             {
  16.                 Console.WriteLine("Drag files onto the program to start unpacking!");
  17.                 Console.ReadKey();
  18.                 return;
  19.             }
  20.             var output = new StreamWriter(File.Create("output.txt"));
  21.             Console.SetOut(output);
  22.             const string directory = "EXTRACTED";
  23.             const string temp = directory + "_TEMP";
  24.             Directory.CreateDirectory(directory);
  25.             Directory.CreateDirectory(temp);
  26.             Package lastPackage = null;
  27.             foreach (var arg in args.Where(File.Exists))
  28.             {
  29.                 Console.WriteLine("INFO: Unpacking file: {0}", arg);
  30.                 ErrorCount = WarningCount = 0;
  31.                 InformationCount = 1;
  32.                 try
  33.                 {
  34.                     (lastPackage = new Package(arg)).ExtractAll(temp);
  35.                 }
  36.                 catch (Exception exc)
  37.                 {
  38.                     Console.WriteLine("ERROR: {0}", exc.Message);
  39.                     ErrorCount++;
  40.                 }
  41.                 Console.WriteLine("Unpacking done. {0} error(s), {1} warning(s), {2} info(s).", ErrorCount, WarningCount, InformationCount);
  42.                 Console.WriteLine();
  43.             }
  44.             if (lastPackage != null) lastPackage.MoveFiles(directory, temp);
  45.             output.Close();
  46.         }
  47.  
  48.         public static int ErrorCount, WarningCount, InformationCount;
  49.     }
  50.  
  51.     public class Package : IDisposable
  52.     {
  53.         public Package(string filePath)
  54.         {
  55.             path = filePath;
  56.             stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
  57.             if (!stream.CanRead || !stream.CanSeek) throw new NotSupportedException("The file stream is terrible!");
  58.             reader = new BinaryReader(stream);
  59.             PackageVersion = reader.ReadInt32();
  60.             if (PackageVersion != 1) throw new NotSupportedException("Unsupported package version: " + PackageVersion);
  61.             var count = reader.ReadInt32();
  62.             Records = new List<FileRecord>(count);
  63.             for (var i = 0; i < count; i++) Records.Add(new FileRecord(reader));
  64.         }
  65.  
  66.         private static string ReadString(BinaryReader reader)
  67.         {
  68.             var strBytes = new List<byte>();
  69.             int b;
  70.             while ((b = reader.ReadByte()) > 0) strBytes.Add((byte)b);
  71.             return Encoding.UTF8.GetString(strBytes.ToArray());
  72.         }
  73.  
  74.         public void ExtractAll(string directory)
  75.         {
  76.             foreach (var record in Records) Extract(record, Path.Combine(directory, record.ID.ToString()));
  77.         }
  78.         public void Extract(FileRecord record, string filePath)
  79.         {
  80.             int unpackedSize;
  81.             byte[] data;
  82.             lock (reader)
  83.             {
  84.                 stream.Seek(record.Offset, SeekOrigin.Begin);
  85.                 var packedSize = reader.ReadInt32();
  86.                 unpackedSize = reader.ReadInt32();
  87.                 data = reader.ReadBytes(packedSize);
  88.             }
  89.             if (record.Flags == 0)
  90.             {
  91.                 File.WriteAllBytes(filePath, data);
  92.                 Console.WriteLine("INFO: Unpacking item #{0} done.", record.ID);
  93.                 Program.InformationCount++;
  94.                 return;
  95.             }
  96.             using (var fileStream = File.Create(filePath))
  97.             using (var memoryStream = new MemoryStream(data))
  98.             using (var deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress))
  99.             {
  100.                 memoryStream.ReadByte();
  101.                 memoryStream.ReadByte();
  102.                 try
  103.                 {
  104.                     deflateStream.CopyTo(fileStream);
  105.                     if (fileStream.Length != unpackedSize)
  106.                     {
  107.                         Console.WriteLine("WARNING: File size does not match. (item #{0})", record.ID);
  108.                         Program.WarningCount++;
  109.                     }
  110.                     Console.WriteLine("INFO: Unpacking item #{0} done.", record.ID);
  111.                     Program.InformationCount++;
  112.                 }
  113.                 catch (InvalidDataException)
  114.                 {
  115.                     Console.WriteLine("ERROR: Unpacking item #{0} failed.", record.ID);
  116.                     Program.ErrorCount++;
  117.                 }
  118.             }
  119.         }
  120.         public void MoveFiles(string directory, string temp)
  121.         {
  122.             var map = Path.Combine(temp, "3085189639");
  123.             if (!File.Exists(map))
  124.             {
  125.                 Console.WriteLine("ERROR: Maps not found!");
  126.                 Program.ErrorCount++;
  127.                 return;
  128.             }
  129.             using (var fileStream = new FileStream(map, FileMode.Open, FileAccess.Read, FileShare.Read))
  130.             {
  131.                 if (!fileStream.CanRead || !fileStream.CanSeek) throw new NotSupportedException("The file stream is terrible!");
  132.                 using (var mapReader = new BinaryReader(fileStream))
  133.                 {
  134.                     BinaryHeaderPointer maps = new BinaryHeaderPointer(mapReader), stringTableBytes = new BinaryHeaderPointer(mapReader);
  135.                     fileStream.Seek(maps.Offset, SeekOrigin.Begin);
  136.                     var dic = new Dictionary<uint, int>(maps.Count);
  137.                     for (var i = 0; i < maps.Count; i++) dic.Add(mapReader.ReadUInt32(), mapReader.ReadInt32());
  138.                     fileStream.Seek(stringTableBytes.Offset, SeekOrigin.Begin);
  139.                     int numStrings = mapReader.ReadInt32(), numPointers = mapReader.ReadInt32();
  140.                     var stringPointers = new List<StringPointer>(numStrings);
  141.                     for (var i = 0; i < numStrings; i++) stringPointers.Add(new StringPointer(mapReader));
  142.                     var pointerPointers = new List<LanguagePointer>(numPointers);
  143.                     for (var i = 0; i < numPointers; i++) pointerPointers.Add(new LanguagePointer(mapReader));
  144.                     var baseOffset = fileStream.Position;
  145.                     // Console.WriteLine(pointerPointers.Min(p => p.Offset));   // for debugging purpose
  146.  
  147.                     foreach (var file in new DirectoryInfo(temp).EnumerateFiles())
  148.                     {
  149.                         try
  150.                         {
  151.                             var id = uint.Parse(file.Name);
  152.                             var stringPointer = stringPointers[dic[id]];
  153.                             var pointer = default(LanguagePointer);
  154.                             for (var i = 0; i < stringPointer.Count; i++)
  155.                             {
  156.                                 pointer = pointerPointers[stringPointer.Index + i];
  157.                                 if (pointer.LanguageID == 25966) break; // ne
  158.                             }
  159.                             if (pointer.LanguageID != 25966) throw new Exception("Language ne not found!");
  160.                             fileStream.Seek(baseOffset + pointer.Offset, SeekOrigin.Begin);
  161.                             string realPath = ReadString(mapReader), absolutePath = Path.Combine(directory, realPath);
  162.                             Directory.CreateDirectory(Path.GetDirectoryName(absolutePath));
  163.                             file.MoveTo(absolutePath);
  164.                             Console.WriteLine("INFO: File moved successfully: {0}", realPath);
  165.                             Program.InformationCount++;
  166.                         }
  167.                         catch (Exception exc)
  168.                         {
  169.                             Console.WriteLine("ERROR: ({0}) {1}", exc.GetType(), exc.Message);
  170.                             Program.ErrorCount++;
  171.                         }
  172.                     }
  173.                 }
  174.             }
  175.         }
  176.  
  177.         public void Dispose()
  178.         {
  179.             reader.Close();
  180.             stream.Close();
  181.         }
  182.  
  183.         private readonly FileStream stream;
  184.         private readonly BinaryReader reader;
  185.         private readonly string path;
  186.         public int PackageVersion;
  187.         public List<FileRecord> Records;
  188.     }
  189.  
  190.     public struct FileRecord
  191.     {
  192.         public uint ID, Flags;
  193.         public int Offset, Size;
  194.  
  195.         public FileRecord(BinaryReader reader)
  196.         {
  197.             ID = reader.ReadUInt32();
  198.             Flags = reader.ReadUInt32();
  199.             if (Flags > 1)
  200.             {
  201.                 //throw new NotSupportedException("Unsupported file record flags: " + Flags);
  202.                 Console.WriteLine("WARNING: Unsupported file record flags value {0}. (item #{1})", Flags, ID);
  203.                 Program.WarningCount++;
  204.             }
  205.             Offset = reader.ReadInt32();
  206.             Size = reader.ReadInt32();
  207.         }
  208.     }
  209.  
  210.     public struct BinaryHeaderPointer
  211.     {
  212.         public int Count, Offset;
  213.  
  214.         public BinaryHeaderPointer(BinaryReader reader)
  215.         {
  216.             Count = reader.ReadInt32();
  217.             Offset = reader.ReadInt32();
  218.         }
  219.     }
  220.  
  221.     public struct StringPointer
  222.     {
  223.         public int Index, Count;
  224.  
  225.         public StringPointer(BinaryReader reader)
  226.         {
  227.             Index = reader.ReadInt32();
  228.             Count = reader.ReadInt32();
  229.         }
  230.     }
  231.  
  232.     public struct LanguagePointer
  233.     {
  234.         public uint LanguageID;
  235.         public int Offset;
  236.  
  237.         public LanguagePointer(BinaryReader reader)
  238.         {
  239.             LanguageID = reader.ReadUInt32();
  240.             Offset = reader.ReadInt32();
  241.         }
  242.     }
  243. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement