示例#1
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();
            }
        }
示例#3
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
        }
示例#4
0
        static void Main(string[] args)
        {
            if (!File.Exists(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile))
            {
                Settings.Default.Reset();
                Settings.Default.Save();
            }

            if (args.Length < 1)
            {
                Console.WriteLine(Resources.Description);
                Console.ReadLine();
                return;
            }
#if !DEBUG
            try
            {
#endif
            if (args[0].EndsWith(".acb", 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 outputDirectoryPath = Path.ChangeExtension(args[0], null);
                string extAfs2ArchivePath  = string.Empty;

                Directory.CreateDirectory(outputDirectoryPath);

                using (CriTableReader acbReader = CriTableReader.Create(args[0]))
                {
                    acbReader.Read();

                    CriAfs2Archive afs2Archive    = new CriAfs2Archive();
                    CriAfs2Archive extAfs2Archive = new CriAfs2Archive();

                    CriCpkArchive cpkArchive    = new CriCpkArchive();
                    CriCpkArchive extCpkArchive = null;

                    extAfs2ArchivePath = outputDirectoryPath + ".awb";
                    bool found = File.Exists(extAfs2ArchivePath);

                    if (!found)
                    {
                        extAfs2ArchivePath = outputDirectoryPath + "_streamfiles.awb";
                        found = File.Exists(extAfs2ArchivePath);
                    }

                    if (!found)
                    {
                        extAfs2ArchivePath = outputDirectoryPath + "_STR.awb";
                        found = File.Exists(extAfs2ArchivePath);
                    }

                    bool cpkMode = true;

                    long awbPosition = acbReader.GetPosition("AwbFile");
                    if (acbReader.GetLength("AwbFile") > 0)
                    {
                        using (SubStream afs2Stream = acbReader.GetSubStream("AwbFile"))
                        {
                            cpkMode = !CheckIfAfs2(afs2Stream);

                            if (cpkMode)
                            {
                                cpkArchive.Read(afs2Stream);
                            }

                            else
                            {
                                afs2Archive.Read(afs2Stream);
                            }
                        }
                    }

                    if (acbReader.GetLength("StreamAwbAfs2Header") > 0)
                    {
                        cpkMode = false;

                        using (SubStream extAfs2Stream = acbReader.GetSubStream("StreamAwbAfs2Header"))
                        {
                            bool utfMode = DataStream.ReadCString(extAfs2Stream, 4) == "@UTF";
                            extAfs2Stream.Seek(0, SeekOrigin.Begin);

                            if (utfMode)
                            {
                                using (CriTableReader utfAfs2HeaderReader = CriTableReader.Create(extAfs2Stream))
                                {
                                    utfAfs2HeaderReader.Read();

                                    using (SubStream extAfs2HeaderStream = utfAfs2HeaderReader.GetSubStream("Header"))
                                    {
                                        extAfs2Archive.Read(extAfs2HeaderStream);
                                    }
                                }
                            }

                            else
                            {
                                extAfs2Archive.Read(extAfs2Stream);
                            }
                        }

                        if (!found)
                        {
                            throw new FileNotFoundException("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
                        }
                    }

                    using (SubStream waveformTableStream = acbReader.GetSubStream("WaveformTable"))
                        using (CriTableReader waveformReader = CriTableReader.Create(waveformTableStream))
                        {
                            while (waveformReader.Read())
                            {
                                byte encodeType = waveformReader.GetByte("EncodeType");
                                bool streaming  = waveformReader.GetBoolean("Streaming");

                                ushort id =
                                    waveformReader.ContainsField("MemoryAwbId") ?
                                    streaming ? waveformReader.GetUInt16("StreamAwbId") : waveformReader.GetUInt16("MemoryAwbId") :
                                    waveformReader.GetUInt16("Id");

                                string outputName = id.ToString("D5");
                                if (streaming)
                                {
                                    outputName += "_streaming";
                                }

                                outputName += GetExtension(encodeType);
                                outputName  = Path.Combine(outputDirectoryPath, outputName);

                                if (streaming)
                                {
                                    if (!found)
                                    {
                                        throw new Exception("Cannot find the external .AWB file for this .ACB file. Please ensure that the external .AWB file is stored in the directory where the .ACB file is.");
                                    }

                                    else if (extCpkArchive == null && cpkMode)
                                    {
                                        extCpkArchive = new CriCpkArchive();
                                        extCpkArchive.Load(extAfs2ArchivePath, Settings.Default.BufferSize);
                                    }

                                    EntryBase afs2Entry = null;

                                    if (cpkMode)
                                    {
                                        afs2Entry = extCpkArchive.GetById(id);
                                    }

                                    else
                                    {
                                        afs2Entry = extAfs2Archive.GetById(id);
                                    }

                                    extractor.Add(extAfs2ArchivePath, outputName, afs2Entry.Position, afs2Entry.Length);
                                }

                                else
                                {
                                    EntryBase afs2Entry = null;

                                    if (cpkMode)
                                    {
                                        afs2Entry = cpkArchive.GetById(id);
                                    }

                                    else
                                    {
                                        afs2Entry = afs2Archive.GetById(id);
                                    }

                                    extractor.Add(args[0], outputName, awbPosition + afs2Entry.Position, afs2Entry.Length);
                                }
                            }
                        }
                }

                extractor.Run();
            }

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

                string awbPath = args[0] + "_streamfiles.awb";
                bool   found   = File.Exists(awbPath);

                if (!found)
                {
                    awbPath = args[0] + "_STR.awb";
                    found   = File.Exists(awbPath);
                }

                if (!found)
                {
                    awbPath = args[0] + ".awb";
                }

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

                CriTable acbFile = new CriTable();
                acbFile.Load(acbPath, Settings.Default.BufferSize);

                CriAfs2Archive afs2Archive    = new CriAfs2Archive();
                CriAfs2Archive extAfs2Archive = new CriAfs2Archive();

                CriCpkArchive cpkArchive    = new CriCpkArchive();
                CriCpkArchive extCpkArchive = new CriCpkArchive();
                cpkArchive.Mode = extCpkArchive.Mode = CriCpkMode.Id;

                afs2Archive.ProgressChanged    += OnProgressChanged;
                extAfs2Archive.ProgressChanged += OnProgressChanged;
                cpkArchive.ProgressChanged     += OnProgressChanged;
                extCpkArchive.ProgressChanged  += OnProgressChanged;

                bool cpkMode = true;

                byte[] awbFile             = (byte[])acbFile.Rows[0]["AwbFile"];
                byte[] streamAwbAfs2Header = (byte[])acbFile.Rows[0]["StreamAwbAfs2Header"];

                cpkMode = !(awbFile != null && awbFile.Length >= 4 && Encoding.ASCII.GetString(awbFile, 0, 4) == "AFS2") && (streamAwbAfs2Header == null || streamAwbAfs2Header.Length == 0);

                using (CriTableReader reader = CriTableReader.Create((byte[])acbFile.Rows[0]["WaveformTable"]))
                {
                    while (reader.Read())
                    {
                        byte encodeType = reader.GetByte("EncodeType");
                        bool streaming  = reader.GetBoolean("Streaming");

                        ushort id =
                            reader.ContainsField("MemoryAwbId") ?
                            streaming ? reader.GetUInt16("StreamAwbId") : reader.GetUInt16("MemoryAwbId") :
                            reader.GetUInt16("Id");

                        string inputName = id.ToString("D5");
                        if (streaming)
                        {
                            inputName += "_streaming";
                        }

                        inputName += GetExtension(encodeType);
                        inputName  = Path.Combine(args[0], inputName);

                        if (!File.Exists(inputName))
                        {
                            throw new FileNotFoundException($"Cannot find audio file with id {id} for replacement.\nPath attempt: {inputName}");
                        }

                        if (cpkMode)
                        {
                            CriCpkEntry entry = new CriCpkEntry();
                            entry.FilePath = new FileInfo(inputName);
                            entry.Id       = id;

                            if (streaming)
                            {
                                extCpkArchive.Add(entry);
                            }

                            else
                            {
                                cpkArchive.Add(entry);
                            }
                        }

                        else
                        {
                            CriAfs2Entry entry = new CriAfs2Entry();
                            entry.FilePath = new FileInfo(inputName);
                            entry.Id       = id;

                            if (streaming)
                            {
                                extAfs2Archive.Add(entry);
                            }

                            else
                            {
                                afs2Archive.Add(entry);
                            }
                        }
                    }
                }

                acbFile.Rows[0]["AwbFile"]             = null;
                acbFile.Rows[0]["StreamAwbAfs2Header"] = null;

                if (afs2Archive.Count > 0 || cpkArchive.Count > 0)
                {
                    Console.WriteLine("Saving internal AWB...");
                    acbFile.Rows[0]["AwbFile"] = cpkMode ? cpkArchive.Save() : afs2Archive.Save();
                    Console.WriteLine();
                }

                if (extAfs2Archive.Count > 0 || extCpkArchive.Count > 0)
                {
                    Console.WriteLine("Saving external AWB...");
                    if (cpkMode)
                    {
                        extCpkArchive.Save(awbPath, Settings.Default.BufferSize);
                    }

                    else
                    {
                        extAfs2Archive.Save(awbPath, Settings.Default.BufferSize);

                        if (Encoding.UTF8.GetString(streamAwbAfs2Header, 0, 4) == "@UTF")
                        {
                            CriTable headerTable = new CriTable();
                            headerTable.Load(streamAwbAfs2Header);

                            headerTable.Rows[0]["Header"]          = extAfs2Archive.Header;
                            headerTable.WriterSettings             = CriTableWriterSettings.Adx2Settings;
                            acbFile.Rows[0]["StreamAwbAfs2Header"] = headerTable.Save();
                        }

                        else
                        {
                            acbFile.Rows[0]["StreamAwbAfs2Header"] = extAfs2Archive.Header;
                        }
                    }
                }

                acbFile.WriterSettings = CriTableWriterSettings.Adx2Settings;
                acbFile.Save(acbPath, Settings.Default.BufferSize);
            }
#if !DEBUG
        }

        catch (Exception exception)
        {
            MessageBox.Show($"{exception.Message}", "ACB Editor", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
#endif
        }