Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.IO;
- using System.IO.Compression;
- using System.Linq;
- using System.Text;
- namespace Mygod.LittleInferno.Resource.Unpacker
- {
- public static class Program
- {
- private static void Main(string[] args)
- {
- if (args == null || args.Length == 0)
- {
- DoubleWriter.WriteLine("Drag files onto the program to start unpacking!");
- Console.ReadKey();
- return;
- }
- DoubleWriter.Output = new StreamWriter(File.Create("output.txt")) {AutoFlush = true};
- 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))
- {
- DoubleWriter.WriteLine("INFO: Unpacking file: {0}", arg);
- ErrorCount = WarningCount = 0;
- InformationCount = 1;
- try
- {
- (lastPackage = new Package(arg)).ExtractAll(temp);
- }
- catch (Exception exc)
- {
- DoubleWriter.WriteLine("ERROR: {0}", exc.Message);
- ErrorCount++;
- }
- DoubleWriter.WriteLine("Unpacking done. {0} error(s), {1} warning(s), {2} info(s).", ErrorCount, WarningCount, InformationCount);
- DoubleWriter.WriteLine();
- }
- if (lastPackage != null)
- {
- DoubleWriter.WriteLine("INFO: Moving files into the correct path.");
- ErrorCount = WarningCount = 0;
- InformationCount = 1;
- var decodePosition = lastPackage.MoveFiles(directory, temp) ? directory : temp;
- DoubleWriter.WriteLine("Moving done. {0} error(s), {1} warning(s), {2} info(s).", ErrorCount, WarningCount, InformationCount);
- DoubleWriter.WriteLine();
- DoubleWriter.WriteLine("INFO: Trying to decode images.");
- ErrorCount = WarningCount = 0;
- InformationCount = 1;
- TryDecodeFiles(decodePosition);
- DoubleWriter.WriteLine("Decoding done. {0} error(s), {1} warning(s), {2} info(s).", ErrorCount, WarningCount, InformationCount);
- DoubleWriter.WriteLine();
- }
- DoubleWriter.Output.Close();
- }
- public static void TryDecodeFiles(string directoryPath)
- {
- var queue = new Queue<DirectoryInfo>();
- queue.Enqueue(new DirectoryInfo(directoryPath));
- while (queue.Count > 0)
- {
- var dir = queue.Dequeue();
- foreach (var info in dir.EnumerateFileSystemInfos())
- {
- var dirInfo = info as DirectoryInfo;
- if (dirInfo != null)
- {
- queue.Enqueue(dirInfo);
- continue;
- }
- var fileInfo = info as FileInfo;
- if (fileInfo == null) continue;
- TryDecodeImage(fileInfo);
- }
- }
- }
- private static void TryDecodeImage(FileInfo fileInfo)
- {
- RawImage image = null;
- var path = fileInfo.FullName;
- try
- {
- if (path.ToLower().EndsWith(".raw")) return;
- using (var stream = fileInfo.OpenRead()) image = new RawImage(stream);
- fileInfo.MoveTo(path + ".raw");
- image.SaveToFile(path);
- }
- catch (Exception exc)
- {
- DoubleWriter.WriteLine("WARNING: {0} is not an image. ({1})", path, exc.Message);
- WarningCount++;
- }
- finally
- {
- if (image != null) image.Dispose();
- }
- }
- 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);
- DoubleWriter.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)
- {
- DoubleWriter.WriteLine("WARNING: File size does not match. (item #{0})", record.ID);
- Program.WarningCount++;
- }
- DoubleWriter.WriteLine("INFO: Unpacking item #{0} done.", record.ID);
- Program.InformationCount++;
- }
- catch (InvalidDataException)
- {
- DoubleWriter.WriteLine("ERROR: Unpacking item #{0} failed.", record.ID);
- Program.ErrorCount++;
- }
- }
- }
- public bool MoveFiles(string directory, string temp)
- {
- var map = Path.Combine(temp, "3085189639");
- if (!File.Exists(map))
- {
- DoubleWriter.WriteLine("ERROR: Maps not found!");
- Program.ErrorCount++;
- return false;
- }
- 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;
- // DoubleWriter.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);
- // ReSharper disable AssignNullToNotNullAttribute
- Directory.CreateDirectory(Path.GetDirectoryName(absolutePath));
- // ReSharper restore AssignNullToNotNullAttribute
- try
- {
- file.MoveTo(absolutePath);
- }
- catch (IOException)
- {
- file.CopyTo(absolutePath); // copy it at least
- file.Delete();
- }
- DoubleWriter.WriteLine("INFO: File moved successfully: {0}", realPath);
- Program.InformationCount++;
- }
- catch (Exception exc)
- {
- DoubleWriter.WriteLine("ERROR: ({0}) {1}", exc.GetType(), exc.Message);
- Program.ErrorCount++;
- }
- }
- }
- }
- return true;
- }
- 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);
- DoubleWriter.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();
- }
- }
- public class RawImage : IDisposable
- {
- public RawImage(Stream stream)
- {
- using (var reader = new BinaryReader(stream))
- {
- Width = reader.ReadInt32();
- Height = reader.ReadInt32();
- if (Width * Height * 4 + 12 != stream.Length) throw new Exception("Length incorrect.");
- Bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
- Type = (ImageType) reader.ReadInt32();
- switch (Type)
- {
- case ImageType.RGBA:
- for (var y = 0; y < Height; y++) for (var x = 0; x < Width; x++)
- {
- byte b = reader.ReadByte(), g = reader.ReadByte(), r = reader.ReadByte(), a = reader.ReadByte();
- Bitmap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
- }
- break;
- case ImageType.Greyscale:
- for (var y = 0; y < Height; y++) for (var x = 0; x < Width; x++)
- {
- byte ca = reader.ReadByte(), cc = reader.ReadByte(), ac = reader.ReadByte(), aa = reader.ReadByte();
- Bitmap.SetPixel(x, y, Color.FromArgb((byte) (ca * aa * ac / 16581375.0), cc, cc, cc));
- }
- break;
- }
- }
- }
- public int Width, Height;
- public ImageType Type;
- public Bitmap Bitmap;
- public void SaveToFile(string filePath, ImageFormat format = null)
- {
- if (format == null) format = ImageFormat.Png;
- var extension = '.' + format.ToString().ToLower();
- if (!filePath.EndsWith(extension)) filePath += extension;
- Bitmap.Save(filePath, format);
- }
- public void Dispose()
- {
- Bitmap.Dispose();
- }
- }
- public enum ImageType
- {
- RGBA = 1, Greyscale = 8
- }
- public static class DoubleWriter
- {
- public static StreamWriter Output;
- public static void WriteLine(string value, params object[] arg)
- {
- Console.WriteLine(value, arg);
- if (Output != null) Output.WriteLine(value, arg);
- }
- public static void WriteLine()
- {
- Console.WriteLine();
- if (Output != null) Output.WriteLine();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement