Exemplo n.º 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
        }
Exemplo n.º 2
0
        public static void Build(CsbProject project, string outputFileName)
        {
            CriCpkArchive cpkArchive = new CriCpkArchive();

            DirectoryInfo outputDirectory = new DirectoryInfo(Path.GetDirectoryName(outputFileName));

            List <SerializationCueSheetTable> cueSheetTables = new List <SerializationCueSheetTable>();

            SerializationVersionInfoTable versionInfoTable = new SerializationVersionInfoTable();

            cueSheetTables.Add(new SerializationCueSheetTable
            {
                TableData = CriTableSerializer.Serialize(new List <SerializationVersionInfoTable>()
                {
                    versionInfoTable
                }, CriTableWriterSettings.AdxSettings),
                Name      = "INFO",
                TableType = 7,
            });

            // Serialize cues.
            List <SerializationCueTable> cueTables = new List <SerializationCueTable>();

            foreach (BuilderCueNode cueNode in project.CueNodes)
            {
                cueTables.Add(new SerializationCueTable
                {
                    Name      = cueNode.Name,
                    Id        = cueNode.Identifier,
                    UserData  = cueNode.UserComment,
                    Flags     = cueNode.Flags,
                    SynthPath = cueNode.SynthReference,
                });
            }

            cueSheetTables.Add(new SerializationCueSheetTable
            {
                TableData = CriTableSerializer.Serialize(cueTables, CriTableWriterSettings.AdxSettings),
                Name      = "CUE",
                TableType = 1,
            });

            // Serialize synth tables.
            List <SerializationSynthTable> synthTables = new List <SerializationSynthTable>();

            foreach (BuilderSynthNode synthNode in project.SynthNodes)
            {
                SerializationSynthTable synthTable = new SerializationSynthTable
                {
                    SynthName           = synthNode.Name,
                    SynthType           = (byte)synthNode.Type,
                    ComplexType         = (byte)synthNode.PlaybackType,
                    Volume              = synthNode.Volume,
                    Pitch               = synthNode.Pitch,
                    DelayTime           = synthNode.DelayTime,
                    SControl            = synthNode.SControl,
                    EgDelay             = synthNode.EgDelay,
                    EgAttack            = synthNode.EgAttack,
                    EgHold              = synthNode.EgHold,
                    EgDecay             = synthNode.EgDecay,
                    EgRelease           = synthNode.EgRelease,
                    EgSustain           = synthNode.EgSustain,
                    FType               = synthNode.FilterType,
                    FCof1               = synthNode.FilterCutoff1,
                    FCof2               = synthNode.FilterCutoff2,
                    FReso               = synthNode.FilterReso,
                    FReleaseOffset      = synthNode.FilterReleaseOffset,
                    DryOName            = synthNode.DryOName,
                    Mtxrtr              = synthNode.Mtxrtr,
                    Dry0                = synthNode.Dry0,
                    Dry1                = synthNode.Dry1,
                    Dry2                = synthNode.Dry2,
                    Dry3                = synthNode.Dry3,
                    Dry4                = synthNode.Dry4,
                    Dry5                = synthNode.Dry5,
                    Dry6                = synthNode.Dry6,
                    Dry7                = synthNode.Dry7,
                    WetOName            = synthNode.WetOName,
                    Wet0                = synthNode.Wet0,
                    Wet1                = synthNode.Wet1,
                    Wet2                = synthNode.Wet2,
                    Wet3                = synthNode.Wet3,
                    Wet4                = synthNode.Wet4,
                    Wet5                = synthNode.Wet5,
                    Wet6                = synthNode.Wet6,
                    Wet7                = synthNode.Wet7,
                    Wcnct0              = synthNode.Wcnct0,
                    Wcnct1              = synthNode.Wcnct1,
                    Wcnct2              = synthNode.Wcnct2,
                    Wcnct3              = synthNode.Wcnct3,
                    Wcnct4              = synthNode.Wcnct4,
                    Wcnct5              = synthNode.Wcnct5,
                    Wcnct6              = synthNode.Wcnct6,
                    Wcnct7              = synthNode.Wcnct7,
                    VoiceLimitGroupName = synthNode.VoiceLimitGroupReference,
                    VoiceLimitType      = synthNode.VoiceLimitType,
                    VoiceLimitPriority  = synthNode.VoiceLimitPriority,
                    VoiceLimitPhTime    = synthNode.VoiceLimitProhibitionTime,
                    VoiceLimitPcdlt     = synthNode.VoiceLimitPcdlt,
                    Pan3dVolumeOffset   = synthNode.Pan3dVolumeOffset,
                    Pan3dVolumeGain     = synthNode.Pan3dVolumeGain,
                    Pan3dAngleOffset    = synthNode.Pan3dAngleOffset,
                    Pan3dAngleGain      = synthNode.Pan3dAngleGain,
                    Pan3dDistanceOffset = synthNode.Pan3dDistanceOffset,
                    Pan3dDistanceGain   = synthNode.Pan3dDistanceGain,
                    Dry0g               = synthNode.Dry0g,
                    Dry1g               = synthNode.Dry1g,
                    Dry2g               = synthNode.Dry2g,
                    Dry3g               = synthNode.Dry3g,
                    Dry4g               = synthNode.Dry4g,
                    Dry5g               = synthNode.Dry5g,
                    Dry6g               = synthNode.Dry6g,
                    Dry7g               = synthNode.Dry7g,
                    Wet0g               = synthNode.Wet0g,
                    Wet1g               = synthNode.Wet1g,
                    Wet2g               = synthNode.Wet2g,
                    Wet3g               = synthNode.Wet3g,
                    Wet4g               = synthNode.Wet4g,
                    Wet5g               = synthNode.Wet5g,
                    Wet6g               = synthNode.Wet6g,
                    Wet7g               = synthNode.Wet7g,
                    F1Type              = synthNode.Filter1Type,
                    F1CofOffset         = synthNode.Filter1CutoffOffset,
                    F1CofGain           = synthNode.Filter1CutoffGain,
                    F1ResoOffset        = synthNode.Filter1ResoOffset,
                    F1ResoGain          = synthNode.Filter1ResoGain,
                    F2Type              = synthNode.Filter2Type,
                    F2CofLowOffset      = synthNode.Filter2CutoffLowerOffset,
                    F2CofLowGain        = synthNode.Filter2CutoffLowerGain,
                    F2CofHighOffset     = synthNode.Filter2CutoffHigherOffset,
                    F2CofHighGain       = synthNode.Filter2CutoffHigherGain,
                    Probability         = synthNode.PlaybackProbability,
                    NumberLmtChildren   = synthNode.NLmtChildren,
                    Repeat              = synthNode.Repeat,
                    ComboTime           = synthNode.ComboTime,
                    ComboLoopBack       = synthNode.ComboLoopBack,
                };

                if (synthNode.Type == BuilderSynthType.Single)
                {
                    synthTable.LinkName = synthNode.SoundElementReference;
                }

                else if (synthNode.Type == BuilderSynthType.WithChildren)
                {
                    foreach (string trackReference in synthNode.Children)
                    {
                        synthTable.LinkName += trackReference + (char)0x0A;
                    }
                }

                if (!string.IsNullOrEmpty(synthNode.AisacReference))
                {
                    BuilderAisacNode aisacNode = project.AisacNodes.First(aisac => aisac.Name == synthNode.AisacReference);
                    synthTable.AisacSetName = aisacNode.AisacName + "::" + aisacNode.Name + (char)0x0A;
                }

                synthTables.Add(synthTable);
            }

            cueSheetTables.Add(new SerializationCueSheetTable
            {
                TableData = CriTableSerializer.Serialize(synthTables, CriTableWriterSettings.AdxSettings),
                Name      = "SYNTH",
                TableType = 2,
            });

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

            // Serialize the sound elements.
            List <SerializationSoundElementTable> soundElementTables = new List <SerializationSoundElementTable>();

            foreach (BuilderSoundElementNode soundElementNode in project.SoundElementNodes)
            {
                CriAaxArchive aaxArchive = new CriAaxArchive();

                if (!string.IsNullOrEmpty(soundElementNode.Intro))
                {
                    aaxArchive.Add(new CriAaxEntry
                    {
                        Flag     = CriAaxEntryFlag.Intro,
                        FilePath = new FileInfo(Path.Combine(project.AudioDirectory.FullName, soundElementNode.Intro)),
                    });

                    aaxArchive.SetModeFromExtension(soundElementNode.Intro);
                }

                if (!string.IsNullOrEmpty(soundElementNode.Loop))
                {
                    aaxArchive.Add(new CriAaxEntry
                    {
                        Flag     = CriAaxEntryFlag.Loop,
                        FilePath = new FileInfo(Path.Combine(project.AudioDirectory.FullName, soundElementNode.Loop)),
                    });

                    aaxArchive.SetModeFromExtension(soundElementNode.Loop);
                }

                byte[] data = new byte[0];

                if (soundElementNode.Streaming)
                {
                    CriCpkEntry entry = new CriCpkEntry();
                    entry.Name           = Path.GetFileName(soundElementNode.Name);
                    entry.DirectoryName  = Path.GetDirectoryName(soundElementNode.Name);
                    entry.Id             = (uint)cpkArchive.Count;
                    entry.UpdateDateTime = DateTime.Now;
                    entry.FilePath       = new FileInfo(Path.GetTempFileName());
                    cpkArchive.Add(entry);

                    aaxArchive.Save(entry.FilePath.FullName);
                    junks.Add(entry.FilePath);
                }

                else
                {
                    data = aaxArchive.Save();
                }

                soundElementTables.Add(new SerializationSoundElementTable
                {
                    Name           = soundElementNode.Name,
                    Data           = data,
                    FormatType     = (byte)aaxArchive.Mode,
                    SoundFrequency = soundElementNode.SampleRate,
                    NumberChannels = soundElementNode.ChannelCount,
                    Streaming      = soundElementNode.Streaming,
                    NumberSamples  = soundElementNode.SampleCount,
                });
            }

            cueSheetTables.Add(new SerializationCueSheetTable
            {
                TableData = CriTableSerializer.Serialize(soundElementTables, CriTableWriterSettings.AdxSettings),
                Name      = "SOUND_ELEMENT",
                TableType = 4,
            });

            // Serialize the aisacs.
            List <SerializationAisacTable> aisacTables = new List <SerializationAisacTable>();

            foreach (BuilderAisacNode aisacNode in project.AisacNodes)
            {
                List <SerializationAisacGraphTable> graphTables = new List <SerializationAisacGraphTable>();
                foreach (BuilderAisacGraphNode graphNode in aisacNode.Graphs)
                {
                    List <SerializationAisacPointTable> pointTables = new List <SerializationAisacPointTable>();
                    foreach (BuilderAisacPointNode pointNode in graphNode.Points)
                    {
                        pointTables.Add(new SerializationAisacPointTable
                        {
                            In  = pointNode.X,
                            Out = pointNode.Y,
                        });
                    }

                    graphTables.Add(new SerializationAisacGraphTable
                    {
                        Points = CriTableSerializer.Serialize(pointTables, CriTableWriterSettings.AdxSettings),
                        Type   = graphNode.Type,
                        InMax  = graphNode.MaximumX,
                        InMin  = graphNode.MinimumX,
                        OutMax = graphNode.MaximumY,
                        OutMin = graphNode.MinimumY,
                    });
                }

                aisacTables.Add(new SerializationAisacTable
                {
                    Graph       = CriTableSerializer.Serialize(graphTables, CriTableWriterSettings.AdxSettings),
                    Name        = aisacNode.AisacName,
                    PathName    = aisacNode.Name,
                    Type        = aisacNode.Type,
                    RandomRange = aisacNode.RandomRange,
                });
            }

            cueSheetTables.Add(new SerializationCueSheetTable
            {
                TableData = CriTableSerializer.Serialize(aisacTables, CriTableWriterSettings.AdxSettings),
                Name      = "ISAAC",
                TableType = 5,
            });

            // Serialize the voice limit groups.
            List <SerializationVoiceLimitGroupTable> voiceLimitGroupTables = new List <SerializationVoiceLimitGroupTable>();

            foreach (BuilderVoiceLimitGroupNode voiceLimitGroupNode in project.VoiceLimitGroupNodes)
            {
                voiceLimitGroupTables.Add(new SerializationVoiceLimitGroupTable
                {
                    VoiceLimitGroupName = voiceLimitGroupNode.Name,
                    VoiceLimitGroupNum  = voiceLimitGroupNode.MaxAmountOfInstances,
                });
            }

            cueSheetTables.Add(new SerializationCueSheetTable
            {
                TableData = CriTableSerializer.Serialize(voiceLimitGroupTables, CriTableWriterSettings.AdxSettings),
                Name      = "VOICE_LIMIT_GROUP",
                TableType = 6,
            });

            // Finally, serialize the CSB file.
            CriTableSerializer.Serialize(outputFileName, cueSheetTables, CriTableWriterSettings.AdxSettings, MainForm.Settings.BufferSize);

            if (cpkArchive.Count > 0)
            {
                cpkArchive.Save(Path.ChangeExtension(outputFileName, "cpk"), MainForm.Settings.BufferSize);
            }

            foreach (FileInfo junk in junks)
            {
                junk.Delete();
            }
        }
        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();
            }
        }