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;
                        }
Esempio n. 2
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
        }
Esempio n. 3
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");
            }
        }