示例#1
0
        static void Main(string[] args)
        {
            Settings.Default.Save();

            if (args.Length < 1)
            {
                Console.WriteLine(Resources.Description);
                Console.ReadLine();
                return;
            }

#if !DEBUG
            try
            {
#endif
            if (args[0].EndsWith(".csb", StringComparison.OrdinalIgnoreCase))
            {
                var extractor = new DataExtractor();
                extractor.ProgressChanged += OnProgressChanged;

                extractor.BufferSize      = Settings.Default.BufferSize;
                extractor.EnableThreading = Settings.Default.EnableThreading;
                extractor.MaxThreads      = Settings.Default.MaxThreads;

                string baseDirectory       = Path.GetDirectoryName(args[0]);
                string outputDirectoryName = Path.Combine(baseDirectory, Path.GetFileNameWithoutExtension(args[0]));

                CriCpkArchive cpkArchive = null;
                string        cpkPath    = outputDirectoryName + ".cpk";
                bool          found      = File.Exists(cpkPath);

                //This should fix "File not found" error in case-sensitive file systems.
                //Add new extensions when necessary.
                foreach (string extension in new string[] { "cpk", "CPK" })
                {
                    if (found)
                    {
                        break;
                    }

                    cpkPath = outputDirectoryName + "." + extension;
                    found   = File.Exists(cpkPath);
                }

                using (CriTableReader reader = CriTableReader.Create(args[0]))
                {
                    while (reader.Read())
                    {
                        if (reader.GetString("name") == "SOUND_ELEMENT")
                        {
                            long tablePosition = reader.GetPosition("utf");
                            using (CriTableReader sdlReader = CriTableReader.Create(reader.GetSubStream("utf")))
                            {
                                while (sdlReader.Read())
                                {
                                    if (sdlReader.GetByte("fmt") != 0)
                                    {
                                        throw new Exception("The given CSB file contains an audio file which is not an ADX. Only CSB files with ADXs are supported.");
                                    }

                                    bool streaming = sdlReader.GetBoolean("stmflg");
                                    if (streaming && !found)
                                    {
                                        throw new Exception("Cannot find the external .CPK file for this .CSB file. Please ensure that the external .CPK file is stored in the directory where the .CPK file is.");
                                    }

                                    else if (streaming && found && cpkArchive == null)
                                    {
                                        cpkArchive = new CriCpkArchive();
                                        cpkArchive.Load(cpkPath, Settings.Default.BufferSize);
                                    }

                                    string        sdlName         = sdlReader.GetString("name");
                                    DirectoryInfo destinationPath = new DirectoryInfo(Path.Combine(outputDirectoryName, sdlName));
                                    destinationPath.Create();

                                    CriAaxArchive aaxArchive = new CriAaxArchive();

                                    if (streaming)
                                    {
                                        CriCpkEntry cpkEntry = cpkArchive.GetByPath(sdlName);

                                        if (cpkEntry != null)
                                        {
                                            using (Stream cpkSource = File.OpenRead(cpkPath))
                                                using (Stream aaxSource = cpkEntry.Open(cpkSource))
                                                {
                                                    aaxArchive.Read(aaxSource);

                                                    foreach (CriAaxEntry entry in aaxArchive)
                                                    {
                                                        extractor.Add(cpkPath,
                                                                      Path.Combine(destinationPath.FullName,
                                                                                   entry.Flag == CriAaxEntryFlag.Intro ? "Intro.adx" : "Loop.adx"),
                                                                      cpkEntry.Position + entry.Position, entry.Length);
                                                    }
                                                }
                                        }
                                    }

                                    else
                                    {
                                        long aaxPosition = sdlReader.GetPosition("data");
                                        using (Stream aaxSource = sdlReader.GetSubStream("data"))
                                        {
                                            aaxArchive.Read(aaxSource);

                                            foreach (CriAaxEntry entry in aaxArchive)
                                            {
                                                extractor.Add(args[0],
                                                              Path.Combine(destinationPath.FullName,
                                                                           entry.Flag == CriAaxEntryFlag.Intro ? "Intro.adx" : "Loop.adx"),
                                                              tablePosition + aaxPosition + entry.Position, entry.Length);
                                            }
                                        }
                                    }
                                }
                            }

                            break;
                        }
                    }
                }

                extractor.Run();
            }

            else if (File.GetAttributes(args[0]).HasFlag(FileAttributes.Directory))
            {
                string baseDirectory = Path.GetDirectoryName(args[0]);
                string csbPath       = args[0] + ".csb";

                foreach (string extension in new string[] { "csb", "CSB" })
                {
                    if (File.Exists(csbPath))
                    {
                        break;
                    }
                    csbPath = args[0] + "." + extension;
                }

                if (!File.Exists(csbPath))
                {
                    throw new Exception("Cannot find the .CSB file for this directory. Please ensure that the .CSB file is stored in the directory where this directory is.");
                }

                CriCpkArchive cpkArchive = new CriCpkArchive();
                cpkArchive.ProgressChanged += OnProgressChanged;

                CriTable csbFile = new CriTable();
                csbFile.Load(csbPath, Settings.Default.BufferSize);

                CriRow soundElementRow = csbFile.Rows.First(row => (string)row["name"] == "SOUND_ELEMENT");

                CriTable soundElementTable = new CriTable();
                soundElementTable.Load((byte[])soundElementRow["utf"]);

                List <FileInfo> junks = new List <FileInfo>();

                foreach (CriRow sdlRow in soundElementTable.Rows)
                {
                    string sdlName = (string)sdlRow["name"];

                    DirectoryInfo sdlDirectory = new DirectoryInfo(Path.Combine(args[0], sdlName));

                    if (!sdlDirectory.Exists)
                    {
                        throw new Exception($"Cannot find sound element directory for replacement.\nPath attempt: {sdlDirectory.FullName}");
                    }

                    bool streaming      = (byte)sdlRow["stmflg"] != 0;
                    uint sampleRate     = (uint)sdlRow["sfreq"];
                    byte numberChannels = (byte)sdlRow["nch"];

                    CriAaxArchive aaxArchive = new CriAaxArchive();
                    foreach (FileInfo file in sdlDirectory.GetFiles("*.adx"))
                    {
                        CriAaxEntry entry = new CriAaxEntry();
                        if (file.Name.ToLower(CultureInfo.GetCultureInfo("en-US")) == "intro.adx")
                        {
                            entry.Flag     = CriAaxEntryFlag.Intro;
                            entry.FilePath = file;
                            aaxArchive.Add(entry);

                            ReadAdx(file, out sampleRate, out numberChannels);
                        }

                        else if (file.Name.ToLower(CultureInfo.GetCultureInfo("en-US")) == "loop.adx")
                        {
                            entry.Flag     = CriAaxEntryFlag.Loop;
                            entry.FilePath = file;
                            aaxArchive.Add(entry);

                            ReadAdx(file, out sampleRate, out numberChannels);
                        }
                    }

                    if (streaming)
                    {
                        CriCpkEntry entry = new CriCpkEntry();
                        entry.Name          = Path.GetFileName(sdlName);
                        entry.DirectoryName = Path.GetDirectoryName(sdlName);
                        entry.Id            = (uint)cpkArchive.Count;
                        entry.FilePath      = new FileInfo(Path.GetTempFileName());
                        junks.Add(entry.FilePath);

                        cpkArchive.Add(entry);
                        aaxArchive.Save(entry.FilePath.FullName, Settings.Default.BufferSize);
                    }

                    else
                    {
                        sdlRow["data"] = aaxArchive.Save();
                    }

                    sdlRow["sfreq"] = sampleRate;
                    sdlRow["nch"]   = numberChannels;
                }

                soundElementTable.WriterSettings = CriTableWriterSettings.AdxSettings;
                soundElementRow["utf"]           = soundElementTable.Save();

                csbFile.WriterSettings = CriTableWriterSettings.AdxSettings;
                csbFile.Save(csbPath, Settings.Default.BufferSize);

                if (cpkArchive.Count > 0)
                {
                    string cpkPath = args[0] + ".cpk";
                    foreach (string extension in new string[] { "cpk", "CPK" })
                    {
                        if (File.Exists(args[0] + "." + extension))
                        {
                            cpkPath = args[0] + "." + extension;
                            break;
                        }
                    }

                    cpkArchive.Save(cpkPath, Settings.Default.BufferSize);
                }

                foreach (FileInfo junk in junks)
                {
                    junk.Delete();
                }
            }
#if !DEBUG
        }

        catch (Exception exception)
        {
            MessageBox.Show($"{exception.Message}", "CSB Editor", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
#endif
        }
        public static async Task CSBRepack(string csbDirectory)
        {
            string baseDirectory = Path.GetDirectoryName(csbDirectory);
            string csbPath       = csbDirectory + ".csb";

            foreach (string extension in new string[] { "csb", "CSB" })
            {
                if (File.Exists(csbPath))
                {
                    break;
                }
                csbPath = csbDirectory + "." + extension;
            }

            if (!File.Exists(csbPath))
            {
                throw new Exception("Cannot find the .CSB file for this directory. Please ensure that the .CSB file is stored in the directory where this directory is.");
            }

            CriCpkArchive cpkArchive = new CriCpkArchive();

            CriTable csbFile = new CriTable();

            csbFile.Load(csbPath, 4096);

            CriRow soundElementRow = csbFile.Rows.First(row => (string)row["name"] == "SOUND_ELEMENT");

            CriTable soundElementTable = new CriTable();

            soundElementTable.Load((byte[])soundElementRow["utf"]);

            List <FileInfo> junks = new List <FileInfo>();

            foreach (CriRow sdlRow in soundElementTable.Rows)
            {
                string sdlName = (string)sdlRow["name"];

                DirectoryInfo sdlDirectory = new DirectoryInfo(Path.Combine(csbDirectory, sdlName));

                if (!sdlDirectory.Exists)
                {
                    throw new Exception($"Cannot find sound element directory for replacement.\nPath attempt: {sdlDirectory.FullName}");
                }

                bool streaming      = (byte)sdlRow["stmflg"] != 0;
                uint sampleRate     = (uint)sdlRow["sfreq"];
                byte numberChannels = (byte)sdlRow["nch"];

                CriAaxArchive aaxArchive = new CriAaxArchive();
                foreach (FileInfo file in sdlDirectory.GetFiles("*.adx"))
                {
                    CriAaxEntry entry = new CriAaxEntry();
                    if (file.Name.ToLower(CultureInfo.GetCultureInfo("en-US")) == "intro.adx")
                    {
                        entry.Flag     = CriAaxEntryFlag.Intro;
                        entry.FilePath = file;
                        aaxArchive.Add(entry);

                        ReadAdx(file, out sampleRate, out numberChannels);
                    }

                    else if (file.Name.ToLower(CultureInfo.GetCultureInfo("en-US")) == "loop.adx")
                    {
                        entry.Flag     = CriAaxEntryFlag.Loop;
                        entry.FilePath = file;
                        aaxArchive.Add(entry);

                        ReadAdx(file, out sampleRate, out numberChannels);
                    }
                }

                if (streaming)
                {
                    CriCpkEntry entry = new CriCpkEntry();
                    entry.Name          = Path.GetFileName(sdlName);
                    entry.DirectoryName = Path.GetDirectoryName(sdlName);
                    entry.Id            = (uint)cpkArchive.Count;
                    entry.FilePath      = new FileInfo(Path.GetTempFileName());
                    junks.Add(entry.FilePath);

                    cpkArchive.Add(entry);
                    aaxArchive.Save(entry.FilePath.FullName, 4096);
                }

                else
                {
                    sdlRow["data"] = aaxArchive.Save();
                }

                sdlRow["sfreq"] = sampleRate;
                sdlRow["nch"]   = numberChannels;
            }

            soundElementTable.WriterSettings = CriTableWriterSettings.AdxSettings;
            soundElementRow["utf"]           = soundElementTable.Save();

            csbFile.WriterSettings = CriTableWriterSettings.AdxSettings;
            csbFile.Save(csbPath, 4096);

            if (cpkArchive.Count > 0)
            {
                string cpkPath = csbDirectory + ".cpk";
                foreach (string extension in new string[] { "cpk", "CPK" })
                {
                    if (File.Exists(csbDirectory + "." + extension))
                    {
                        cpkPath = csbDirectory + "." + extension;
                        break;
                    }
                }

                cpkArchive.Save(cpkPath, 4096);
            }

            foreach (FileInfo junk in junks)
            {
                junk.Delete();
            }
        }