Exemple #1
0
            public static CriTableReader Open(Stream source, long position, string expectedSignature)
            {
                source.Seek(position, SeekOrigin.Begin);

                if (DataStream.ReadCString(source, 4) != expectedSignature)
                {
                    throw new InvalidDataException($"'{expectedSignature}' signature could not be found.");
                }

                uint flag        = DataStream.ReadUInt32(source);
                uint tableLength = DataStream.ReadUInt32(source);
                uint unknown     = DataStream.ReadUInt32(source);

                return(CriTableReader.Create(new SubStream(source, source.Position, tableLength)));
            }
        public static ArrayList Deserialize(Stream source, Type type)
        {
            ArrayList arrayList = new ArrayList();

            using (CriTableReader tableReader = CriTableReader.Create(source, true))
            {
                IEnumerable <PropertyInfo> propertyInfos = type.GetProperties().Where(property =>
                {
                    if (property.GetCustomAttribute <CriIgnoreAttribute>() == null)
                    {
                        string fieldName = property.Name;

                        if (property.GetCustomAttribute <CriFieldAttribute>() != null)
                        {
                            fieldName = property.GetCustomAttribute <CriFieldAttribute>().FieldName;
                        }

                        return(tableReader.ContainsField(fieldName));
                    }

                    return(false);
                });

                while (tableReader.Read())
                {
                    object obj = Activator.CreateInstance(type);

                    // I hope this is faster than the old method lol
                    foreach (PropertyInfo propertyInfo in propertyInfos)
                    {
                        string fieldName = propertyInfo.Name;

                        if (propertyInfo.GetCustomAttribute <CriFieldAttribute>() != null)
                        {
                            fieldName = propertyInfo.GetCustomAttribute <CriFieldAttribute>().FieldName;
                        }

                        object value = tableReader.GetValue(fieldName);

                        if (value is SubStream substream)
                        {
                            value = substream.ToArray();
                        }

                        else if (value is byte boolean && propertyInfo.PropertyType == typeof(bool))
                        {
                            value = boolean == 1;
                        }
        public override void Read(Stream source)
        {
            using (CriTableReader reader = CriTableReader.Create(source))
            {
                switch (reader.TableName)
                {
                // ADX wrapper
                case "AAX":
                    Mode = CriAaxArchiveMode.Adx;
                    break;

                // DSP wrapper
                case "ADPCM_WII":
                    Mode = CriAaxArchiveMode.Dsp;
                    break;

                // WAV wrapper
                case "SWLPCM":
                    Mode = CriAaxArchiveMode.Wav;
                    break;

                // Unknown
                default:
                    throw new InvalidDataException($"Unknown AAX type '{reader.TableName}'. Please report the error with the file(s).");
                }

                if (Mode == CriAaxArchiveMode.Dsp)
                {
                    // TODO
                    throw new NotImplementedException("DSP files aren't supported yet.");
                }

                else
                {
                    while (reader.Read())
                    {
                        CriAaxEntry entry = new CriAaxEntry();
                        entry.Flag     = (CriAaxEntryFlag)reader.GetByte("lpflg");
                        entry.Position = reader.GetPosition("data");
                        entry.Length   = reader.GetLength("data");
                        entries.Add(entry);
                    }
                }
            }
        }
Exemple #4
0
        public static void Main(string[] args)
        {
            var awbsByHeaderHash    = new Dictionary <string, string>();
            var acbsByAwbHeaderHash = new Dictionary <string, string>();
            var lines = new List <string>();

            string DirectoryForWork = "";
            string outputDirectory  = "";

            if (args.Count() < 1)
            {
                DirectoryForWork = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                outputDirectory  = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "output");
            }
            else
            {
                DirectoryForWork = args[0];
                outputDirectory  = Path.Combine(args[0], "output");
            }

            StreamWriter LogFile = new StreamWriter(Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "ACB_FinderLog.txt")));

            Directory.CreateDirectory(outputDirectory);

            var md5 = MD5.Create();

            var buffer = new byte[4];
            var di     = Directory.GetFiles(DirectoryForWork, "*", SearchOption.AllDirectories);

            Console.WriteLine("=== ACB Finder (" + DateTime.Now + ") ===");
            LogFile.WriteLine("=== ACB Finder (" + DateTime.Now + ") ===");

            Console.WriteLine("Found " + di.Length + " files in " + DirectoryForWork + "...");
            LogFile.WriteLine("Found " + di.Length + " files in " + DirectoryForWork + "...");
            int AWBsFound = 0;

            foreach (var filePath in di)
            {
                if (filePath.Contains("ACBFinder.exe") || filePath.Contains("SonicAudioLib.dll") || filePath.Contains("ACB_FinderLog.txt"))
                {
                    continue;
                }
                using (var stream = File.OpenRead(filePath))
                {
                    stream.Read(buffer, 0, 4);

                    var signature = Encoding.ASCII.GetString(buffer);
                    if (signature == "AFS2")
                    {
                        Console.WriteLine("Found an AWB file: " + filePath.Replace(DirectoryForWork, "").Replace("\\", ""));
                        LogFile.WriteLine("Found an AWB file: " + filePath.Replace(DirectoryForWork, "").Replace("\\", ""));
                        AWBsFound++;

                        stream.Read(buffer, 0, 4);
                        int entryCount = DataStream.ReadInt32(stream);

                        stream.Seek(4 + (entryCount * buffer[2]), SeekOrigin.Current);
                        int length = (buffer[1] == 2 ? DataStream.ReadInt16(stream) : DataStream.ReadInt32(stream)) + 2;

                        stream.Seek(0, SeekOrigin.Begin);
                        var header = new byte[length];
                        stream.Read(header, 0, length);

                        string hash = Convert.ToBase64String(md5.ComputeHash(header));
                        awbsByHeaderHash[hash] = filePath;
                    }
                    else if (signature == "@UTF")
                    {
                        stream.Seek(0, SeekOrigin.Begin);

                        try
                        {
                            using (var reader = CriTableReader.Create(stream))
                            {
                                reader.Read();

                                string name = (((FileStream)reader.SourceStream).Name).Replace(DirectoryForWork, "").Replace("\\", ""); //Properly get the filename using the stream and remove the directory from it
                                name = name.Remove(name.Length - 4, 4);                                                                 //Remove the extension too, just in case?
                                File.Copy(filePath, Path.Combine(outputDirectory, name + ".acb"), true);

                                Console.WriteLine("Found and copied ACB: {0}", name);
                                LogFile.WriteLine("Found and copied ACB: {0}", name);

                                lines.Add($"{Path.GetFileName(filePath)}={name}.acb");

                                if (reader.GetLength("StreamAwbAfs2Header") != 0)
                                {
                                    //using ( var reader2 = reader.GetTableReader( "StreamAwbAfs2Header" ) )
                                    //{
                                    //    reader2.Read();

                                    var header = reader.GetData("StreamAwbAfs2Header");
                                    var hash   = Convert.ToBase64String(md5.ComputeHash(header));

                                    acbsByAwbHeaderHash[hash] = name;
                                    //}
                                }
                            }
                        }
                        catch
                        {
                            Console.WriteLine("File could not be read correctly as an ACB: " + filePath.Replace(DirectoryForWork, "").Replace("\\", ""));
                            LogFile.WriteLine("File could not be read correctly as an ACB: " + filePath.Replace(DirectoryForWork, "").Replace("\\", ""));
                            continue;
                        }
                    }
                }
            }

            foreach (var pair in awbsByHeaderHash)
            {
                if (!acbsByAwbHeaderHash.TryGetValue(pair.Key, out string name))
                {
                    Console.WriteLine("AWB (" + pair.Key + ") with no ACB found.");
                    LogFile.WriteLine("AWB (" + pair.Key + ") with no ACB found.");
                    continue;
                }

                lines.Add($"{Path.GetFileName(pair.Value)}={name}.awb");

                File.Copy(pair.Value, Path.Combine(outputDirectory, name + ".awb"), true);
                Console.WriteLine("Copied awb {0}", name);
                LogFile.WriteLine("Copied awb {0}", name);
            }

            foreach (var pair in acbsByAwbHeaderHash.Where(x => !awbsByHeaderHash.ContainsKey(x.Key)))
            {
                File.AppendAllText(Path.Combine(outputDirectory, "missing_awb.txt"), string.Format("{0}\n", pair.Value));
            }
            File.WriteAllLines(Path.Combine(outputDirectory, "file_list.txt"), lines);

            Console.WriteLine("Process completed - Found " + AWBsFound + " AWB file(s).  Press any key to exit.");
            LogFile.WriteLine("== Process completed (" + DateTime.Now + ") - Found " + AWBsFound + " AWB file(s).  Press any key to exit. ===");
            LogFile.Close();
            Console.ReadKey();
        }
Exemple #5
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
        }
        // All taken from the code for CsbEditor: https://github.com/blueskythlikesclouds/SonicAudioTools/blob/master/Source/CsbEditor/Program.cs
        public static async Task CSBUnpack(string csbFile)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            DataExtractor?extractor = new()
            {
                EnableThreading = false
            };

            string baseDirectory       = Path.GetDirectoryName(csbFile);
            string outputDirectoryName = Path.Combine(baseDirectory, Path.GetFileNameWithoutExtension(csbFile));

            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(csbFile))
            {
                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, 4096);
                                }

                                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(csbFile,
                                                          Path.Combine(destinationPath.FullName,
                                                                       entry.Flag == CriAaxEntryFlag.Intro ? "Intro.adx" : "Loop.adx"),
                                                          tablePosition + aaxPosition + entry.Position, entry.Length);
                                        }
                                    }
                                }
                            }
                        }

                        break;
                    }
                }
            }

            extractor.Run();
        }
Exemple #7
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
        }
Exemple #8
0
        public override void Read(Stream source)
        {
            using (CriTableReader reader = CriCpkSection.Open(source, source.Position, "CPK "))
            {
                reader.Read();

                bool isLatestVersion = reader.ContainsField("CpkMode");

                if (isLatestVersion)
                {
                    mode = (CriCpkMode)reader.GetUInt32("CpkMode");
                }

                else
                {
                    bool tocEnabled  = reader.GetUInt64("TocOffset") > 0;
                    bool itocEnabled = reader.GetUInt64("ItocOffset") > 0;

                    if (tocEnabled && !itocEnabled)
                    {
                        mode = CriCpkMode.FileName;
                    }

                    else if (!tocEnabled && itocEnabled)
                    {
                        mode = CriCpkMode.Id;
                    }

                    else if (tocEnabled && itocEnabled)
                    {
                        mode = CriCpkMode.FileNameAndId;
                    }

                    else
                    {
                        mode = CriCpkMode.None;
                    }
                }

                // No need to waste time, stop right there.
                if (mode == CriCpkMode.None)
                {
                    return;
                }

                long tocPosition     = (long)reader.GetUInt64("TocOffset");
                long itocPosition    = (long)reader.GetUInt64("ItocOffset");
                long etocPosition    = (long)reader.GetUInt64("EtocOffset");
                long contentPosition = (long)reader.GetUInt64("ContentOffset");

                align = reader.GetUInt16("Align");

                if (mode == CriCpkMode.FileName || mode == CriCpkMode.FileNameAndId)
                {
                    using (CriTableReader tocReader = CriCpkSection.Open(source, tocPosition, "TOC "))
                        using (CriTableReader etocReader = CriCpkSection.Open(source, etocPosition, "ETOC"))
                        {
                            while (tocReader.Read())
                            {
                                CriCpkEntry entry = new CriCpkEntry();
                                entry.DirectoryName      = tocReader.GetString("DirName");
                                entry.Name               = tocReader.GetString("FileName");
                                entry.Length             = tocReader.GetUInt32("FileSize");
                                entry.Position           = (long)tocReader.GetUInt64("FileOffset");
                                entry.Id                 = isLatestVersion ? tocReader.GetUInt32("ID") : tocReader.GetUInt32("Info");
                                entry.Comment            = tocReader.GetString("UserString");
                                entry.UncompressedLength = tocReader.GetUInt32("ExtractSize");
                                entry.IsCompressed       = entry.Length != entry.UncompressedLength;

                                if (contentPosition < tocPosition)
                                {
                                    entry.Position += contentPosition;
                                }

                                else
                                {
                                    entry.Position += tocPosition;
                                }

                                entry.Position = Helpers.Align(entry.Position, align);

                                etocReader.MoveToRow(tocReader.CurrentRow);
                                entry.UpdateDateTime = DateTimeFromCpkDateTime(etocReader.GetUInt64("UpdateDateTime"));

                                entries.Add(entry);
                            }
                        }

                    if (mode == CriCpkMode.FileNameAndId && isLatestVersion)
                    {
                        using (CriTableReader itocReader = CriCpkSection.Open(source, itocPosition, "ITOC"))
                        {
                            while (itocReader.Read())
                            {
                                entries[itocReader.GetInt32("TocIndex")].Id = (uint)itocReader.GetInt32("ID");
                            }
                        }
                    }
                }

                else if (mode == CriCpkMode.Id)
                {
                    using (CriTableReader itocReader = CriCpkSection.Open(source, itocPosition, "ITOC"))
                    {
                        while (itocReader.Read())
                        {
                            if (itocReader.GetUInt32("FilesL") > 0)
                            {
                                using (CriTableReader dataReader = itocReader.GetTableReader("DataL"))
                                {
                                    while (dataReader.Read())
                                    {
                                        CriCpkEntry entry = new CriCpkEntry();
                                        entry.Id                 = dataReader.GetUInt16("ID");
                                        entry.Length             = dataReader.GetUInt16("FileSize");
                                        entry.UncompressedLength = dataReader.GetUInt16("ExtractSize");
                                        entry.IsCompressed       = entry.Length != entry.UncompressedLength;

                                        entries.Add(entry);
                                    }
                                }
                            }

                            if (itocReader.GetUInt32("FilesH") > 0)
                            {
                                using (CriTableReader dataReader = itocReader.GetTableReader("DataH"))
                                {
                                    while (dataReader.Read())
                                    {
                                        CriCpkEntry entry = new CriCpkEntry();
                                        entry.Id                 = dataReader.GetUInt16("ID");
                                        entry.Length             = dataReader.GetUInt32("FileSize");
                                        entry.UncompressedLength = dataReader.GetUInt32("ExtractSize");
                                        entry.IsCompressed       = entry.Length != entry.UncompressedLength;

                                        entries.Add(entry);
                                    }
                                }
                            }
                        }
                    }

                    long entryPosition = contentPosition;
                    foreach (CriCpkEntry entry in entries.OrderBy(entry => entry.Id))
                    {
                        entryPosition = Helpers.Align(entryPosition, align);

                        entry.Position = entryPosition;
                        entryPosition += entry.Length;
                    }
                }

                else
                {
                    throw new NotImplementedException($"Unimplemented CPK mode ({mode})");
                }

                Comment = reader.GetString("Comment");
            }
        }