Exemplo n.º 1
0
        private void CLI(StartupEventArgs e)
        {
            List<string> args = e.Args.ToList<string>();
            List<string>.Enumerator en = args.GetEnumerator();

            debug = false;
            bool list = false;
            quiet = false;
            string gameDir = "";
            string backupDir = "";
            string outDir = "";
            bool decode = true;
            bool all = false;
            bool all_hardcore = false;
            bool nolist = false;
            bool noassets = false;
            List<string> inputs = new List<string>();
            string location = System.Reflection.Assembly.GetEntryAssembly().Location;
            string infoFile = location.Remove(location.LastIndexOf("\\")) + "\\Resources\\info.txt";
            List<string> filters = new List<string>();
            bool PRINT_AND_EXIT = false;
            int MIN_FZ = 0;
            int MAX_FZ = int.MaxValue;
            bool pcm = false;
            string lookup = "";
            List<string> filter_id = new List<string>();

            while (en.MoveNext())
            {
                string arg = en.Current;
                string[] argp = arg.Split('=');
                switch (argp[0])
                {
                    case "-r":
                    case "--nolist":
                        nolist = true;
                        break;
                    case "-R":
                    case "--noassets":
                        noassets = true;
                        break;
                    case "--max":
                        if (argp.Length < 2)
                        {
                            Output("Format: --max=<int>");
                            return;
                        }
                        MAX_FZ = int.Parse(argp[1]);
                        break;
                    case "-X":
                        if (en.MoveNext())
                        {
                            MAX_FZ = int.Parse(en.Current);
                        }
                        break;
                    case "--lookup":
                        if (argp.Length < 2)
                        {
                            Output("Format: --lookup=<file>");
                        }
                        Output("!!WARNING!!");
                        Output("--lookup is an experimental module");
                        Output("results so far: everything is messed up");
                        Output("!!WARNING!!");
                        lookup = argp[1];
                        break;
                    case "--min":
                        if (argp.Length < 2)
                        {
                            Output("Format: --min=<int>");
                            return;
                        }
                        MIN_FZ = int.Parse(argp[1]);
                        break;
                    case "-x":
                        if (en.MoveNext())
                        {
                            MIN_FZ = int.Parse(en.Current);
                        }
                        break;
                    case "--id":
                        if (argp.Length < 2)
                        {
                            Output("Format: --id=<id>");
                            return;
                        }
                        if (argp[1].Length != 16)
                        {
                            Output("--id should be 16 characters");
                            return;
                        }
                        filter_id.Add(argp[1].ToUpper());
                        break;
                    case "-I":
                        if (en.MoveNext())
                        {
                            if (en.Current.Length != 16)
                            {
                                Output("-I should be 16 characters");
                                return;
                            }

                            filter_id.Add(en.Current.ToUpper());
                        }
                        break;
                    case "--list":
                    case "-l":
                        list = true;
                        break;
                    case "--verbose":
                    case "--debug":
                    case "-D":
                        debug = true;
                        break;
                    case "--quiet":
                    case "-q":
                        quiet = true;
                        break;
                    case "--decode":
                    case "-P":
                        decode = false;
                        break;
                    case "--game-dir":
                        if (argp.Length < 2)
                        {
                            Output("Format: --game-dir=<path>");
                            break;
                        }
                        gameDir = argp[1];
                        break;
                    case "-G":
                        if (en.MoveNext())
                        {
                            gameDir = en.Current;
                        }
                        break;
                    case "--backup-dir":
                        if (argp.Length < 2)
                        {
                            Output("Format: --backup-dir=<path>");
                            break;
                        }
                        backupDir = argp[1];
                        break;
                    case "-B":
                        if (en.MoveNext())
                        {
                            backupDir = en.Current;
                        }
                        break;
                    case "--out-dir":
                        if (argp.Length < 2)
                        {
                            Output("Format: --out-dir=<path>");
                            break;
                        }
                        outDir = argp[1];
                        break;
                    case "-O":
                        if (en.MoveNext())
                        {
                            outDir = en.Current;
                        }
                        break;
                    case "--all":
                    case "-a":
                        all = true;
                        break;
                    case "-A":
                        all = true;
                        all_hardcore = true;
                        break;
                    case "--ext":
                        if (argp.Length < 2)
                        {
                            Output("Format: --ext=<path>");
                            break;
                        }
                        infoFile = argp[1];
                        break;
                    case "-e":
                        if (en.MoveNext())
                        {
                            infoFile = en.Current;
                        }
                        break;
                    case "--pcm":
                        pcm = true;
                        break;
                    case "-f":
                        if (en.MoveNext())
                        {
                            string[] argf = en.Current.Split(',');
                            for (int i = 0; i < argf.Length; ++i)
                            {
                                filters.Add(argf[i].Trim());
                            }
                        }
                        break;
                    case "-i":
                        if (en.MoveNext())
                        {
                            inputs.Add(en.Current);
                        }
                        break;
                    case "-F":
                        PRINT_AND_EXIT = true;
                        break;
                    default:
                        if (arg.ToCharArray()[0] != '-')
                        {
                            inputs.Add(arg);
                        }
                        break;
                }
            }

            Output("Bundai CLI");

            Bandaid band = new Bandaid(Debug, Output);

            Debug("Checking if extension file exists");
            if (!File.Exists(infoFile))
            {
                Output("Error! extfile does not exist!");
                return;
            }
            Debug("Loading extension file", infoFile);
            Dictionary<string, string[]> exts = Bandaid.Exts(infoFile);

            if (PRINT_AND_EXIT)
            {
                List<string[]> extsL = exts.Values.ToList<string[]>();
                foreach (string[] ext in extsL)
                {
                    Console.Write(ext[0]);
                    if (ext[0] == "stream") Console.Write("; converts into IMA ADPCM (or PCM) .WAV file");
                    if (ext[0] == "strings") Console.Write("; converts into .CSV file");
                    Console.Write("\r\n");
                }
                return;
            }

            Debug("Checking if game-dir is specified and exists; game-dir =", gameDir);

            if (gameDir.Length == 0 || !Directory.Exists(gameDir))
            {
                Output("Error! Game-dir does not exist or is not specified");
                return;
            }

            Debug("Checking for /assets");
            if (!Directory.Exists(gameDir + "/assets"))
            {
                Output("Error! Could not find assets subdirectory");
                return;
            }

            Debug("Checking for all.blb");
            if (!File.Exists(gameDir + "/assets/all.blb"))
            {
                Output("Error! Could not find all.blb");
                return;
            }

            Debug("Checking if inputs or all; all =", all, "inputs = [" + string.Join(",", inputs.ToArray<string>()) + "]");

            if (!all && inputs.Count == 0)
            {
                Output("Error! All or inputs are not specified");
                return;
            }

            Debug("Backup directory specified; backup-dir =", backupDir);
            if (backupDir.Length > 0 && !list)
            {
                Debug("Checking if backup-dir", backupDir, "exists");
                if (File.Exists(backupDir))
                {
                    Output("Error!", backupDir, "exists but is a file!");
                }
                else if (!Directory.Exists(backupDir))
                {
                    Output(backupDir, "does not exist... Making.");
                    Directory.CreateDirectory(backupDir);
                }
                else Output("Backup directory", backupDir, "is valid");
            }

            Debug("Checking if list-only mode or out-dir; list =", list, "out-dir =", outDir);
            if (!list && outDir.Length > 0)
            {
                Debug("Checking if out-dir", outDir, "exists");
                if (File.Exists(outDir))
                {
                    Output("Error!", outDir, "exists but is a file!");
                }
                else if (!Directory.Exists(outDir))
                {
                    Output(outDir, "does not exist... Making.");
                    Directory.CreateDirectory(outDir);
                }
                else Output("Output directory", outDir, "is valid");
            }
            else if (!list)
            {
                Output("Error! out-dir or list are not specified");
                return;
            }
            else Debug("List-only mode");

            Debug("Loading asset filenames");
            List<string> assets = Directory.GetFiles(gameDir + "/assets/").ToList<string>();

            if (all || all_hardcore)
            {
                Debug("Populating inputs with", all_hardcore ? "all bundles" : "all_*.bundle");
                inputs.Clear();
                List<string>.Enumerator aen = assets.GetEnumerator();
                while (aen.MoveNext())
                {
                    string asset_file = aen.Current.Substring(aen.Current.LastIndexOf('/')+1);
                    if (asset_file.EndsWith("_h.bundle"))
                    {
                        if (!all_hardcore && !asset_file.StartsWith("all_")) continue;
                        asset_file = asset_file.Split('.')[0].Split(new string[] { "_h" }, StringSplitOptions.None)[0];
                        inputs.Add(asset_file);
                        Debug("Found", asset_file);
                    }
                }
            }
            else
            {
                Debug("Fixing inputs");
                List<string> inputsC = new List<string>();
                List<string>.Enumerator ienc = inputs.GetEnumerator();
                while (ienc.MoveNext())
                {
                    string ienC = ienc.Current.Split('.')[0].Split(new string[] { "_h" }, StringSplitOptions.None)[0];
                    List<string>.Enumerator aen = assets.GetEnumerator();
                    while (aen.MoveNext())
                    {
                        if (aen.Current.Contains(ienC + "_h.bundle"))
                        {
                            inputsC.Add(ienC);
                            Debug("Found", ienC);
                        }
                    }
                }
                inputs.Clear();
                inputs.AddRange(inputsC);
            }

            Debug("New inputs", "[" + string.Join(",", inputs) + "]");

            string ROOT_DIR = gameDir + "/assets/";
            if (backupDir.Length > 0)
            {
                Output("Backing files up");

                Output("Backup: all.blb");
                if (!File.Exists(backupDir + "/all.blb") && File.Exists(ROOT_DIR + "/all.blb")) File.Copy(ROOT_DIR + "/all.blb", backupDir + "/all.blb");
                else Debug("Skipping all.blb");
                List<string>.Enumerator ben = inputs.GetEnumerator();

                while (ben.MoveNext())
                {
                    string src = ROOT_DIR + ben.Current;
                    string dst = backupDir + "/" + ben.Current;

                    Output("Backup:", ben.Current);
                    if (!File.Exists(dst + ".bundle") && File.Exists(src + ".bundle")) File.Copy(src + ".bundle", dst + ".bundle");
                    else Debug("Skipping", ben.Current + ".bundle");
                    if (!File.Exists(dst + "_h.bundle") && File.Exists(src + "_h.bundle")) File.Copy(src + "_h.bundle", dst + "_h.bundle");
                    else Debug("Skipping", ben.Current + "_h.bundle");
                }

                ROOT_DIR = backupDir + "/";
            }

            Output("Starting...");
            IndexCollection idxCol = new IndexCollection();
            if (lookup != null && lookup.Length > 0)
            {
                Binboy lbb = new Binboy(lookup);
                lbb.Open();
                idxCol.ParseLookup(lbb);
            }
            Binboy bb = new Binboy(ROOT_DIR + "all.blb");
            if (!bb.Open())
            {
                Output("Can't open all.blb");
                return;
            }

            for (int i = 0; i < 8; i++) bb.ReadBytes(4);
            int files = bb.ReadInt32();
            int target = bb.ReadInt32();
            bb.Position = (long)target;
            Debug("Reading file table");
            for (int i = 0; i < files; ++i)
            {
                idxCol.Add(bb.ReadBytes(8), bb.ReadBytes(8), bb.ReadInt32(), bb.ReadInt32(), bb.ReadInt32(), bb.ReadInt32());
            }

            bb.Dispose();
            List<string>.Enumerator ieun = inputs.GetEnumerator();
            bool hadFilters = filter_id.Count > 0;
            while (ieun.MoveNext())
            {
                if (list) outDir = System.IO.Path.GetTempPath();
                string dst = outDir + "/unknown/" + ieun.Current + "/";
                BundleDataCollection bdc = new BundleDataCollection();
                Binboy bbd = new Binboy(ROOT_DIR + ieun.Current + "_h.bundle");
                Debug("Opening", ROOT_DIR + ieun.Current + "_h.bundle");
                if (!bbd.Open()) continue;
                Debug("Reading headers");

                bbd.Position = 0;
                for (int i = 0; i < 5; ++i) bdc.AddHeader(bbd.ReadUInt32());
                bool flag = false;
                if ((uint)bdc.Header[4] == 24u)
                {
                    flag = true;
                    bdc.AddHeader(bbd.ReadUInt32());
                    bdc.AddHeader(bbd.ReadUInt32());
                }
                for (int i = 0; i < bdc.GetTotal(); i++)
                {
                    Debug(i+1, "/", bdc.GetTotal());
                    if (flag)
                    {
                        bdc.Add(new BundleData(bbd.ReadInt32(), bbd.ReadInt32(), bbd.ReadInt32()));
                    }
                    else
                    {
                        bdc.Add(new BundleData(bbd.ReadInt32(), bbd.ReadInt32(), 0));
                    }
                    if (i > 0 && !flag)
                    {
                        BundleData bhd1 = (BundleData)bdc[i];
                        BundleData bhd2 = (BundleData)bdc[i - 1];
                        bhd2.Length = bhd1.Address - bhd2.Address;
                    }
                }
                if (bdc.Count - 1 >= 0 && !flag)
                {
                    BundleData bhd3 = (BundleData)bdc[bdc.Count - 1];
                    bhd3.Length = -1;
                }

                string txt = "";

                bbd.Dispose();
                bbd = new Binboy(ROOT_DIR + ieun.Current + ".bundle");
                Output("Opening", ieun.Current);
                bbd.Open();
                if (bdc.Header.Count == 5)
                {
                    bbd.ReadBytes(((BundleData)bdc[0]).Address);
                }

                System.Collections.IEnumerator bbdc = bdc.GetEnumerator();
                bool hasDoneShit = false;

                if (hadFilters && filter_id.Count == 0) break;

                while(bbdc.MoveNext())
                {
                    if (hadFilters && filter_id.Count == 0) break;

                    BundleData bddd = (BundleData)bbdc.Current;
                    string xex = "bin";
                    bool lookedup = false;
                    string dstFrom = dst;
                    try
                    {
                        txt = idxCol.FindName(bddd.Index);
                        string[] tin = txt.Split('.');
                        Debug("tin", string.Join(",", tin));
                        if (hadFilters)
                        {
                            if (!filter_id.Contains(tin[0].ToUpper())) continue;
                            filter_id.Remove(tin[0].ToUpper());
                        }
                        xex = tin[2];
                        if (exts.ContainsKey(xex.ToUpper()))
                        {
                            string[] xx = exts[xex];
                            Debug("xx", string.Join(",", xx));
                            if (filters.Count > 0 && !filters.Contains(xx[0])) continue;
                            xex = xx.Length > 1 ? xx[1] : xx[0];
                            txt = txt.Substring(0, txt.LastIndexOf('.') + 1);
                        }
                        string lookupstr = idxCol.FindLookup(bddd.Index);
                        if (lookupstr != null && lookupstr.Trim().Length > 1)
                        {
                            txt = ".";
                            lookedup = true;
                            dstFrom = outDir + "/" + lookupstr.Trim();
                        }
                        else
                        {
                            dstFrom = dst;
                        }
                    }
                    catch (Exception epppppp)
                    {
                        if (filters.Count > 0) continue;
                        txt = "unknown_" + string.Format("{0:X8}", bddd.Index) + ".";
                        Debug(epppppp.Message, epppppp.StackTrace);
                    }

                    bbd.Position = (long)bddd.Address;
                    byte[] a;
                    if (bddd.Length == -1) a = bbd.ReadAllBytes();
                    else a = bbd.ReadBytes(bddd.Length);
                    if (a != null && a.LongLength > MIN_FZ && a.LongLength < MAX_FZ)
                    {
                        string dstFrm = dstFrom;
                        if (lookedup)
                        {
                            dstFrm = dstFrom.Substring(0, dstFrom.LastIndexOf('/') == 0 ? dstFrom.Length : dstFrom.LastIndexOf('/'));
                        }

                        Output(ieun.Current, dstFrom + txt + xex, Binboy.Format(a.LongLength));
                        if (!list)
                        {
                            byte[] a_cache = a;
                            if (decode)
                            {
                                switch (xex)
                                {
                                    case "strings":
                                        a = Parsers.Strings(a, out xex);
                                        break;

                                    case "wav":
                                    case "stream":
                                        a = Parsers.IMA_ADPCM(a, out xex, pcm);
                                        break;
                                }
                            }

                            if (!Directory.Exists(dstFrm)) Directory.CreateDirectory(dstFrm);
                            Bandaid.write(dstFrom + txt + xex, a);

                            if (!noassets)
                            {
                                using (StreamWriter sw = new StreamWriter(new FileStream(dst + "/assets.idx", FileMode.Append)))
                                {
                                    sw.WriteLine(txt + xex);
                                }
                            }
                            hasDoneShit = true;
                        }
                    }
                }
                if (!nolist && !list && hasDoneShit)
                {
                    using (StreamWriter sw = new StreamWriter(new FileStream(dst + "/list.csv", FileMode.Create)))
                    {
                        sw.WriteLine(string.Join(",", bdc.Header.ToArray()));
                    }
                }
            }
        }
Exemplo n.º 2
0
        //Coverted from C (ima_rejigger2)
        //https://bitbucket.org/anders/wwiseconv/wiki/WWise_format
        public static byte[] IMA_ADPCM(byte[] a, out string xex, bool pcm)
        {
            xex = "stream";
            Binboy bb = new Binboy(a);
            if(!bb.Open()) return a;

            if (bb.GetEncoding().GetString(bb.ReadBytes(4), 0, 4) != "RIFF") return a;
            int riffSize = bb.ReadInt32();
            if (bb.GetEncoding().GetString(bb.ReadBytes(4), 0, 4) != "WAVE") return a;

            int waveChunkStart = 12;
            int waveChunkEnd = 8 + riffSize;
            int chunkOffset = waveChunkStart;
            int channels = -1;
            int blockSize = -1;
            int samples = -1;
            int dataSize = -1;
            int dataPos = -1;

            bb.SetPosition(0);
            MemoryStream ms = new MemoryStream(bb.ReadAllBytes());
            BinaryWriter bw = new BinaryWriter(ms);

            while (chunkOffset < waveChunkEnd)
            {
                bb.SetPosition((int)chunkOffset);
                string chunkType = Encoding.ASCII.GetString(bb.ReadBytes(4), 0, 4);
                int chunkSize = bb.ReadInt32();

                if (chunkOffset + 8 + chunkSize < chunkOffset + 8 || chunkOffset + 8 + chunkSize > waveChunkEnd) return a;

                switch (chunkType)
                {
                    case "fmt ":
                        Bandaid.Debug("fmt");
                        if ((int)0xE > chunkSize) return a;
                        Bandaid.Debug("ChunkSize is correct");
                        ushort codec = bb.ReadUInt16(chunkOffset + 8);
                        if (codec == 0xFFFF)
                        {
                            xex = "stream";
                            return a;
                        }
                        if (0x2 != codec) return a;
                        Bandaid.Debug("Codec is correct");
                        channels = bb.ReadUInt16();
                        Bandaid.Debug("chunkOffset", chunkOffset);
                        samples = bb.ReadInt32();
                        bb.ReadUInt32();
                        ushort sblockSize = bb.ReadUInt16();
                        Bandaid.Debug("Channels", channels, "BlockSize", sblockSize);
                        blockSize = sblockSize;
                        bw.BaseStream.Position = chunkOffset + 8;
                        bw.Write((ushort)0x11);
                        break;
                    case "data":
                        Bandaid.Debug("Data");
                        if (channels < 1 || blockSize < 1) return a;
                        dataSize = chunkSize;
                        dataPos = chunkOffset + 8;
                        reinterleaveMS_IMA(bw, bb, dataPos, chunkSize, channels, blockSize);
                        break;
                }

                chunkOffset += 8 + chunkSize;
            }
            if (!pcm) return ms.ToArray();
            ms.Position = 0;
            IMA_ADPCM decode = new IMA_ADPCM(ms);
            xex = "wav";
            return decode.Decode();
        }