Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace MTFExtractor {
- struct DataEntry {
- public string Path;
- public int Offset;
- public int Size;
- }
- class MtfExtractor {
- List<string> filesToExtract;
- List<DataEntry> dataEntries;
- public MtfExtractor(List<string> mtfFiles) {
- filesToExtract = mtfFiles;
- }
- public void Execute() {
- foreach (var f in filesToExtract) {
- try {
- using (var fileStream = new FileStream(f, FileMode.Open))
- using (var binaryReader = new BinaryReader(fileStream)) {
- ProcessFile(binaryReader);
- }
- }
- catch (Exception e) {
- var errorMessage = string.Format("Error processing file {0} : {1}\n", f, e.Message);
- File.AppendAllText("log.txt", errorMessage);
- Console.WriteLine(errorMessage);
- }
- }
- }
- void ProcessFile(BinaryReader binaryReader) {
- dataEntries = new List<DataEntry>();
- int numEntries = binaryReader.ReadInt32();
- for (int i = 0; i < numEntries; ++i) {
- CreateEntry(binaryReader);
- }
- dataEntries.Sort((a, b) => a.Offset.CompareTo(b.Offset));
- for (int i = 0; i < numEntries; ++i) {
- ProcessEntry(dataEntries[i], binaryReader, i);
- }
- }
- void ProcessEntry(DataEntry dataEntry, BinaryReader binaryReader, int index) {
- // Darkstone's DATA.MTF has a number of invalid sizes, this makes this entire program much
- // more complex than it could be. Basically this is why we have to create
- // all DataEntries in advance and sort them by offset, otherwise we could just
- // process one entry at a time as we read them.
- if (dataEntry.Offset + dataEntry.Size > binaryReader.BaseStream.Length) {
- // If the size is invalid (it would go outside the file), stop reading at the next entry's offset instead
- var nextOffset = dataEntries.Count > index + 1 ? dataEntries[index + 1].Offset : binaryReader.BaseStream.Length;
- dataEntry.Size = (int)nextOffset - dataEntry.Offset;
- }
- var fileInfo = new FileInfo(dataEntry.Path);
- fileInfo.Directory.Create();
- using (var file = File.Create(dataEntry.Path)) {
- binaryReader.BaseStream.Seek(dataEntry.Offset, SeekOrigin.Begin);
- file.Write(binaryReader.ReadBytes(dataEntry.Size), 0, dataEntry.Size);
- }
- }
- void CreateEntry(BinaryReader binaryReader) {
- int stringLength = binaryReader.ReadInt32();
- var entry = new DataEntry {
- Path = UnsafeAsciiBytesToString(binaryReader.ReadBytes(stringLength)),
- Offset = binaryReader.ReadInt32(),
- Size = binaryReader.ReadInt32()
- };
- dataEntries.Add(entry);
- }
- string UnsafeAsciiBytesToString(byte[] buffer) {
- unsafe {
- fixed (byte* pAscii = buffer) {
- return new string((sbyte*)pAscii);
- }
- }
- }
- static void Main(string[] args) {
- var mtfFiles = new List<string>();
- // If file specified, extract that file, otherwise extract all mtf files in current working directory
- if (args.Length == 1) {
- mtfFiles.Add(args[0]);
- }
- else {
- foreach (var f in Directory.EnumerateFiles(Environment.CurrentDirectory)) {
- if (f.EndsWith(".MTF", StringComparison.CurrentCultureIgnoreCase)) {
- mtfFiles.Add(f);
- }
- }
- }
- new MtfExtractor(mtfFiles).Execute();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement