Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- namespace unTenchu
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine("AFS Volume 200 Unpacker");
- if (args.Length == 0)
- {
- Console.WriteLine("usage: untenchu inFile.vol");
- return;
- }
- try
- {
- AFSvol200 volume = new AFSvol200(args[0]);
- foreach (string file in volume.FileList)
- {
- Console.WriteLine(file);
- EnsureDirectoryExists(new FileInfo(file).Directory);
- File.WriteAllBytes(file, volume.GetFile(file));
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
- }
- public static void EnsureDirectoryExists(DirectoryInfo di)
- {
- if (di.Exists)
- return;
- EnsureDirectoryExists(di.Parent);
- di.Create();
- }
- }
- class AFSvol200
- {
- BinaryReader br;
- IndexInfo[] IndexData;
- const ulong MagicA = 6866950764218238529; // "AFS_VOL_"
- const uint MagicB = 3158066; // "200\0"
- public AFSvol200(string fi)
- {
- br = new BinaryReader(File.OpenRead(fi));
- ulong firstRead = br.ReadUInt64();
- uint secondRead = br.ReadUInt32();
- if (firstRead != MagicA)
- throw new Exception("invalid magic number");
- if (secondRead != MagicB)
- throw new Exception("invalid magic number");
- uint indicies = read32bigEndian();
- uint toc_offset = read32bigEndian();
- IndexData = new IndexInfo[indicies];
- br.BaseStream.Position = toc_offset;
- for (int i = 0; i < indicies; i++)
- {
- br.ReadUInt16(); //This is always "IX", and we don't need to know that.
- IndexData[i] = new IndexInfo();
- IndexData[i].idxType = (IndexType)read16bigEndian();
- IndexData[i].offset = read32bigEndian();
- IndexData[i].size = read32bigEndian();
- IndexData[i].sizeBackup = read32bigEndian(); //I don't know why the size is stored twice. Did they want compression?
- IndexData[i].blob = readFixedString(20);
- while (IndexData[i].blob.EndsWith("\0"))
- IndexData[i].blob = IndexData[i].blob.Substring(0, IndexData[i].blob.Length - 1);
- if (IndexData[i].HasMother)
- IndexData[i].mother = IndexData[IndexData[i].MotherId];
- }
- }
- string readFixedString(int len)
- {
- return Encoding.ASCII.GetString(br.ReadBytes(len));
- }
- uint read32bigEndian()
- {
- byte[] v = br.ReadBytes(4);
- byteswap(v, 0, 3);
- byteswap(v, 1, 2);
- return BitConverter.ToUInt32(v, 0);
- }
- uint read16bigEndian()
- {
- byte[] v = br.ReadBytes(2);
- byteswap(v, 0,1);
- return BitConverter.ToUInt16(v, 0);
- }
- void byteswap(byte[] data, int left, int right) //I know this can be done a lot more elegant - but i'm laaaaazy :D
- {
- byte t = data[left];
- data[left] = data[right];
- data[right] = t;
- }
- public string[] FileList
- {
- get
- {
- List<string> result = new List<string>();
- for (int i = 0; i < IndexData.Length; i++)
- if (IndexData[i].idxType == IndexType.File)
- result.Add(IndexData[i].ToString());
- return result.ToArray();
- }
- }
- public byte[] GetFile(string filename)
- {
- for (int i = 0; i < IndexData.Length; i++)
- {
- if (IndexData[i].ToString() == filename)
- {
- br.BaseStream.Position = IndexData[i].offset;
- return br.ReadBytes((int)IndexData[i].size);
- }
- }
- throw new FileNotFoundException();
- }
- }
- enum IndexType : ushort
- {
- Directory = 2,
- File = 1,
- }
- class IndexInfo
- {
- public IndexType idxType;
- public uint offset, size, sizeBackup;
- public string blob;
- public IndexInfo mother;
- public bool HasMother
- {
- get { return blob.Split('_').Length >= 2; }
- }
- public int MotherId
- {
- get
- {
- if (!HasMother)
- return 0;
- string mString = blob.Split('_')[0];
- mString = mString.Substring(1, mString.Length - 1);
- return Convert.ToInt32(mString);
- }
- }
- public string BaseName
- {
- get
- {
- if (HasMother)
- return blob.Split(new char[] { '_' }, 2)[1];
- else
- return blob;
- }
- }
- public override string ToString()
- {
- string rValue;
- if (HasMother)
- rValue = mother.ToString() + "\\" + BaseName;
- else
- rValue = BaseName;
- return rValue.Replace(':', '_');
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement