Advertisement
Dr_Asik

MTFExtractor

Mar 3rd, 2012
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.02 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4.  
  5. namespace MTFExtractor {
  6.     struct DataEntry {
  7.         public string Path;
  8.         public int Offset;
  9.         public int Size;
  10.     }
  11.  
  12.  
  13.     class MtfExtractor {
  14.         List<string> filesToExtract;
  15.         List<DataEntry> dataEntries;
  16.         public MtfExtractor(List<string> mtfFiles) {
  17.             filesToExtract = mtfFiles;
  18.         }
  19.  
  20.         public void Execute() {
  21.             foreach (var f in filesToExtract) {
  22.                 try {
  23.                     using (var fileStream = new FileStream(f, FileMode.Open))
  24.                     using (var binaryReader = new BinaryReader(fileStream)) {
  25.                         ProcessFile(binaryReader);
  26.                     }
  27.                 }
  28.                 catch (Exception e) {
  29.                     var errorMessage = string.Format("Error processing file {0} : {1}\n", f, e.Message);
  30.                     File.AppendAllText("log.txt", errorMessage);
  31.                     Console.WriteLine(errorMessage);
  32.                 }
  33.             }
  34.         }
  35.  
  36.         void ProcessFile(BinaryReader binaryReader) {
  37.             dataEntries = new List<DataEntry>();
  38.             int numEntries = binaryReader.ReadInt32();
  39.             for (int i = 0; i < numEntries; ++i) {
  40.                 CreateEntry(binaryReader);
  41.             }
  42.             dataEntries.Sort((a, b) => a.Offset.CompareTo(b.Offset));
  43.  
  44.             for (int i = 0; i < numEntries; ++i) {
  45.                 ProcessEntry(dataEntries[i], binaryReader, i);
  46.             }
  47.         }
  48.  
  49.         void ProcessEntry(DataEntry dataEntry, BinaryReader binaryReader, int index) {
  50.             // Darkstone's DATA.MTF has a number of invalid sizes, this makes this entire program much
  51.             // more complex than it could be. Basically this is why we have to create
  52.             // all DataEntries in advance and sort them by offset, otherwise we could just
  53.             // process one entry at a time as we read them.
  54.             if (dataEntry.Offset + dataEntry.Size > binaryReader.BaseStream.Length) {
  55.                 // If the size is invalid (it would go outside the file), stop reading at the next entry's offset instead
  56.                 var nextOffset = dataEntries.Count > index + 1 ? dataEntries[index + 1].Offset : binaryReader.BaseStream.Length;
  57.                 dataEntry.Size = (int)nextOffset - dataEntry.Offset;
  58.             }
  59.             var fileInfo = new FileInfo(dataEntry.Path);
  60.             fileInfo.Directory.Create();
  61.             using (var file = File.Create(dataEntry.Path)) {
  62.                 binaryReader.BaseStream.Seek(dataEntry.Offset, SeekOrigin.Begin);
  63.                 file.Write(binaryReader.ReadBytes(dataEntry.Size), 0, dataEntry.Size);
  64.             }
  65.         }
  66.  
  67.         void CreateEntry(BinaryReader binaryReader) {
  68.             int stringLength = binaryReader.ReadInt32();
  69.             var entry = new DataEntry {
  70.                 Path = UnsafeAsciiBytesToString(binaryReader.ReadBytes(stringLength)),
  71.                 Offset = binaryReader.ReadInt32(),
  72.                 Size = binaryReader.ReadInt32()
  73.             };
  74.             dataEntries.Add(entry);
  75.         }
  76.  
  77.         string UnsafeAsciiBytesToString(byte[] buffer) {
  78.             unsafe {
  79.                 fixed (byte* pAscii = buffer) {
  80.                     return new string((sbyte*)pAscii);
  81.                 }
  82.             }
  83.         }
  84.  
  85.  
  86.         static void Main(string[] args) {
  87.             var mtfFiles = new List<string>();
  88.  
  89.             // If file specified, extract that file, otherwise extract all mtf files in current working directory
  90.             if (args.Length == 1) {
  91.                 mtfFiles.Add(args[0]);
  92.             }
  93.             else {
  94.                 foreach (var f in Directory.EnumerateFiles(Environment.CurrentDirectory)) {
  95.                     if (f.EndsWith(".MTF", StringComparison.CurrentCultureIgnoreCase)) {
  96.                         mtfFiles.Add(f);
  97.                     }
  98.                 }
  99.             }
  100.             new MtfExtractor(mtfFiles).Execute();
  101.         }
  102.     }
  103. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement