Example #1
0
        /// <summary>
        /// Initializes arc from binary reader
        /// </summary>
        /// <param name="reader"></param>
        private bool Init(ExtBinaryReader reader)
        {
            if (!HashDict.Initialized)
            {
                HashDict.Init();
            }

            if (reader.BaseStream.Length < Marshal.SizeOf <_sArcHeader>())
            {
                return(false);
            }

            header = reader.ReadType <_sArcHeader>();

            if (header.Magic != Magic)
            {
                throw new InvalidDataException("ARC magic does not match");
            }

            reader.BaseStream.Seek(header.FileSystemOffset, SeekOrigin.Begin);
            if (header.FileDataOffset < 0x8824AF68)
            {
                Version = 0x00010000;
                ReadFileSystemV1(ReadCompressedTable(reader));
            }
            else
            {
                ReadFileSystem(ReadCompressedTable(reader));
            }

            //reader.BaseStream.Seek(header.FileSystemSearchOffset, SeekOrigin.Begin);
            //ReadSearchTable(ReadCompressedTable(reader));

            return(true);
        }
Example #2
0
        /// <summary>
        /// Parses filesystem from the 1.0.0 arc
        /// </summary>
        /// <param name="fileSystemTable"></param>
        private void ReadFileSystemV1(byte[] fileSystemTable)
        {
            using (ExtBinaryReader reader = new ExtBinaryReader(new MemoryStream(fileSystemTable)))
            {
                reader.BaseStream.Position = 0;
                var nodeHeader = reader.ReadType <_sFileSystemHeaderV1>();

                reader.BaseStream.Seek(0x68, SeekOrigin.Begin);

                // Hash Table
                reader.BaseStream.Seek(0x8 * nodeHeader.Part1Count, SeekOrigin.Current);

                // Hash Table 2
                System.Diagnostics.Debug.WriteLine("stream " + reader.BaseStream.Position.ToString("X"));
                streamNameToHash = reader.ReadType <_sStreamNameToHash>(nodeHeader.Part1Count);

                // Hash Table 3
                System.Diagnostics.Debug.WriteLine("stream " + reader.BaseStream.Position.ToString("X"));
                streamIndexToFile = reader.ReadType <_sStreamIndexToOffset>(nodeHeader.Part2Count);

                // stream offsets
                System.Diagnostics.Debug.WriteLine("stream " + reader.BaseStream.Position.ToString("X"));
                streamOffsets = reader.ReadType <_sStreamOffset>(nodeHeader.MusicFileCount);

                // Another Hash Table
                System.Diagnostics.Debug.WriteLine("RegionalHashList " + reader.BaseStream.Position.ToString("X"));
                reader.BaseStream.Seek(0xC * 0xE, SeekOrigin.Current);

                //folders

                System.Diagnostics.Debug.WriteLine("FolderHashes " + reader.BaseStream.Position.ToString("X"));
                directoryList = reader.ReadType <_sDirectoryList>(nodeHeader.FolderCount);

                //file offsets

                System.Diagnostics.Debug.WriteLine("fileoffsets " + reader.BaseStream.Position.ToString("X"));
                directoryOffsets = reader.ReadType <_sDirectoryOffset>(nodeHeader.FileCount1 + nodeHeader.FileCount2);
                //DirectoryOffsets_2 = reader.ReadType<_sDirectoryOffsets>(R, NodeHeader.FileCount2);

                System.Diagnostics.Debug.WriteLine("subfileoffset " + reader.BaseStream.Position.ToString("X"));
                directoryChildHashGroup = reader.ReadType <_sHashIndexGroup>(nodeHeader.HashFolderCount);

                System.Diagnostics.Debug.WriteLine("subfileoffset " + reader.BaseStream.Position.ToString("X"));
                fileInfoV1 = reader.ReadType <_sFileInformationV1>(nodeHeader.FileInformationCount);

                System.Diagnostics.Debug.WriteLine("subfileoffset " + reader.BaseStream.Position.ToString("X"));
                subFiles = reader.ReadType <_sSubFileInfo>(nodeHeader.SubFileCount + nodeHeader.SubFileCount2);
            }
        }
Example #3
0
        /// <summary>
        /// Reads the search table information for V2 Arc
        /// </summary>
        /// <param name="searchTable"></param>
        private void ReadSearchTable(byte[] searchTable)
        {
            using (ExtBinaryReader r = new ExtBinaryReader(new MemoryStream(searchTable)))
            {
                var header = r.ReadType <_sSearchHashHeader>();

                // paths
                var ActualPathHashSection = r.ReadType <_sHashIndexGroup>(header.FolderLengthHashCount);

                int MaxFolderIndex = 0;
                foreach (var section in ActualPathHashSection)
                {
                    MaxFolderIndex = Math.Max(MaxFolderIndex, section.index >> 8);
                }
                Console.WriteLine("Max FolderIndex " + MaxFolderIndex.ToString("X"));

                // path lookup group
                var UnkHashGroup = r.ReadType <_sHashGroup>(header.FolderLengthHashCount);
                Console.WriteLine("End at: " + r.BaseStream.Position.ToString("X"));

                // file paths
                var ActualFullPath = r.ReadType <_sHashIndexGroup>(header.SomeCount3);
                Console.WriteLine("End at: " + r.BaseStream.Position.ToString("X"));

                // index to look up pathgroup? why they needed a separate index who knows...
                var IndexTable = r.ReadType <int>(header.SomeCount3);
                Console.WriteLine("End at: " + r.BaseStream.Position.ToString("X"));

                // file path lookup group
                var PathNameHashGroupLookup = r.ReadType <_sHashGroup>(header.SomeCount4);
                Console.WriteLine("End at: " + r.BaseStream.Position.ToString("X"));

                int MaxIntTableValue = 0;
                foreach (var g in UnkHashGroup)
                {
                    MaxIntTableValue = Math.Max((int)g.ExtensionHash, MaxIntTableValue);
                    //Console.WriteLine(HashDict.GetString(g.Hash));
                }
                Console.WriteLine("Max table value: " + MaxIntTableValue.ToString("X"));


                /*using (StreamWriter writer = new StreamWriter(new FileStream("print.txt", FileMode.Create)))
                 *  foreach (var g in ActualFullPath)
                 *  {
                 *      writer.WriteLine(HashDict.GetString(g.Hash));
                 *  }*/
            }
        }
Example #4
0
        /// <summary>
        /// Arc versions other than 1.0 have compressed tables
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        private byte[] ReadCompressedTable(ExtBinaryReader reader)
        {
            var compHeader = reader.ReadType <_sCompressedTableHeader>();

            if (compHeader.DataOffset > 0x10)
            {
                var tableStart = reader.BaseStream.Position - 0x10;
                reader.BaseStream.Seek(tableStart, SeekOrigin.Begin);
                var size = reader.ReadInt32();
                reader.BaseStream.Seek(tableStart, SeekOrigin.Begin);
                return(reader.ReadBytes(size));
            }
            else
            if (compHeader.DataOffset == 0x10)
            {
                return(reader.ReadZstdCompressed(compHeader.CompressedSize));
            }
            else
            {
                return(reader.ReadBytes(compHeader.CompressedSize));
            }
        }
Example #5
0
        /// <summary>
        /// Parses filesystem from the 1.0.0 arc
        /// </summary>
        /// <param name="fileSystemTable"></param>
        private void ReadFileSystemV1(byte[] fileSystemTable)
        {
            using (ExtBinaryReader reader = new ExtBinaryReader(new MemoryStream(fileSystemTable)))
            {
                reader.BaseStream.Position = 0;
                var NodeHeader = reader.ReadType <_sFileSystemHeaderV1>();

                reader.BaseStream.Seek(0x68, SeekOrigin.Begin);

                // Hash Table
                reader.BaseStream.Seek(0x8 * NodeHeader.Part1Count, SeekOrigin.Current);

                // Hash Table 2
                System.Diagnostics.Debug.WriteLine("stream " + reader.BaseStream.Position.ToString("X"));
                streamNameToHash = reader.ReadType <_sStreamNameToHash>(NodeHeader.Part1Count);

                // Hash Table 3
                System.Diagnostics.Debug.WriteLine("stream " + reader.BaseStream.Position.ToString("X"));
                streamIndexToFile = reader.ReadType <_sStreamIndexToOffset>(NodeHeader.Part2Count);

                // stream offsets
                System.Diagnostics.Debug.WriteLine("stream " + reader.BaseStream.Position.ToString("X"));
                streamOffsets = reader.ReadType <_sStreamOffset>(NodeHeader.MusicFileCount);

                // Another Hash Table
                System.Diagnostics.Debug.WriteLine("RegionalHashList " + reader.BaseStream.Position.ToString("X"));
                reader.BaseStream.Seek(0xC * 0xE, SeekOrigin.Current);

                //folders

                System.Diagnostics.Debug.WriteLine("FolderHashes " + reader.BaseStream.Position.ToString("X"));
                directoryList = reader.ReadType <_sDirectoryList>(NodeHeader.FolderCount);

                //file offsets

                System.Diagnostics.Debug.WriteLine("fileoffsets " + reader.BaseStream.Position.ToString("X"));
                directoryOffsets = reader.ReadType <_sDirectoryOffset>(NodeHeader.FileCount1 + NodeHeader.FileCount2);
                //DirectoryOffsets_2 = reader.ReadType<_sDirectoryOffsets>(R, NodeHeader.FileCount2);

                System.Diagnostics.Debug.WriteLine("subfileoffset " + reader.BaseStream.Position.ToString("X"));
                directoryChildHashGroup = reader.ReadType <_sHashIndexGroup>(NodeHeader.HashFolderCount);

                System.Diagnostics.Debug.WriteLine("subfileoffset " + reader.BaseStream.Position.ToString("X"));
                fileInfoV1 = reader.ReadType <_sFileInformationV1>(NodeHeader.FileInformationCount);

                System.Diagnostics.Debug.WriteLine("subfileoffset " + reader.BaseStream.Position.ToString("X"));
                subFiles = reader.ReadType <_sSubFileInfo>(NodeHeader.SubFileCount + NodeHeader.SubFileCount2);

                /*SubFileInformationStart = R.BaseStream.Position;
                 * SubFileInformation_1 = reader.ReadType<_SubFileInfo>(R, NodeHeader.SubFileCount);
                 * SubFileInformationStart2 = R.BaseStream.Position;
                 * SubFileInformation_2 = reader.ReadType<_SubFileInfo>(R, NodeHeader.SubFileCount2);*/

                //_sHashInt[] HashInts = reader.ReadType<_sHashInt>(R, NodeHeader.FolderCount);

                // okay some more file information
                //uint FileHashCount = reader.ReadUInt32();
                //uint UnknownTableCount = reader.ReadUInt32();

                //_sExtraFITable[] Extra1 = reader.ReadType<_sExtraFITable>(R, UnknownTableCount);
                //_sExtraFITable2[] Extra2 = reader.ReadType<_sExtraFITable2>(R, FileHashCount);

                /*reader.BaseStream.Position += 8 * NodeHeader.FileInformationCount;
                 *
                 * FolderHashDict = new Dictionary<uint, _sDirectoryList>();
                 * foreach (_sDirectoryList fh in DirectoryLists)
                 * {
                 *  FolderHashDict.Add(fh.HashID, fh);
                 * }
                 *
                 * foreach (_sDirectoryOffsets chunk in DirectoryOffsets_1)
                 * {
                 *  for (int i = 0; i < chunk.SubDataCount; i++)
                 *      if (!ChunkHash1.ContainsKey((int)chunk.SubDataStartIndex + i))
                 *          ChunkHash1.Add((int)chunk.SubDataStartIndex + i, chunk);
                 * }
                 * foreach (_sDirectoryOffsets chunk in DirectoryOffsets_2)
                 * {
                 *  for (int i = 0; i < chunk.SubDataCount; i++)
                 *      if (!ChunkHash2.ContainsKey((int)chunk.SubDataStartIndex + i))
                 *          ChunkHash2.Add((int)chunk.SubDataStartIndex + i, chunk);
                 * }*/
            }
        }
Example #6
0
        /// <summary>
        /// Reads file system table from Arc
        /// </summary>
        /// <param name="fileSystemTable"></param>
        private void ReadFileSystem(byte[] fileSystemTable)
        {
            using (ExtBinaryReader reader = new ExtBinaryReader(new MemoryStream(fileSystemTable)))
            {
                FSHeader = reader.ReadType <_sFileSystemHeader>();

                uint ExtraFolder = 0;
                uint ExtraCount  = 0;

                if (fileSystemTable.Length >= 0x2992DD4)
                {
                    // Version 3+
                    Version = reader.ReadInt32();

                    ExtraFolder = reader.ReadUInt32();
                    ExtraCount  = reader.ReadUInt32();

                    reader.ReadBytes(0x10);  // some extra thing :thinking
                }
                else
                {
                    Version = 0x00020000;
                    reader.BaseStream.Seek(0x3C, SeekOrigin.Begin);
                }

                // skip this for now
                regionalbytes = reader.ReadBytes(0xE * 12);

                // Streams
                StreamHeader = reader.ReadType <_sStreamHeader>();

                streamUnk = reader.ReadType <_sStreamUnk>(StreamHeader.UnkCount);

                streamHashToName = reader.ReadType <_sStreamHashToName>(StreamHeader.StreamHashCount);

                streamNameToHash = reader.ReadType <_sStreamNameToHash>(StreamHeader.StreamHashCount);

                streamIndexToFile = reader.ReadType <_sStreamIndexToOffset>(StreamHeader.StreamIndexToOffsetCount);

                streamOffsets = reader.ReadType <_sStreamOffset>(StreamHeader.StreamOffsetCount);

                Console.WriteLine(reader.BaseStream.Position.ToString("X"));

                // Unknown
                uint UnkCount1 = reader.ReadUInt32();
                uint UnkCount2 = reader.ReadUInt32();
                fileInfoUnknownTable     = reader.ReadType <_sFileInformationUnknownTable>(UnkCount2);
                filePathToIndexHashGroup = reader.ReadType <_sHashIndexGroup>(UnkCount1);

                // FileTables

                fileInfoPath = reader.ReadType <_sFileInformationPath>(FSHeader.FileInformationPathCount);

                fileInfoIndex = reader.ReadType <_sFileInformationIndex>(FSHeader.FileInformationIndexCount);

                // directory tables

                // directory hashes by length and index to directory probably 0x6000 something
                Console.WriteLine(reader.BaseStream.Position.ToString("X"));
                directoryHashGroup = reader.ReadType <_sHashIndexGroup>(FSHeader.DirectoryCount);

                directoryList = reader.ReadType <_sDirectoryList>(FSHeader.DirectoryCount);

                directoryOffsets = reader.ReadType <_sDirectoryOffset>(FSHeader.DirectoryOffsetCount1 + FSHeader.DirectoryOffsetCount2 + ExtraFolder);

                directoryChildHashGroup = reader.ReadType <_sHashIndexGroup>(FSHeader.DirectoryHashSearchCount);

                // file information tables
                Console.WriteLine(reader.BaseStream.Position.ToString("X"));
                fileInfoV2 = reader.ReadType <_sFileInformationV2>(FSHeader.FileInformationCount + FSHeader.SubFileCount2 + ExtraCount);

                fileInfoSubIndex = reader.ReadType <_sFileInformationSubIndex>(FSHeader.FileInformationSubIndexCount + FSHeader.SubFileCount2 + ExtraCount);

                subFiles = reader.ReadType <_sSubFileInfo>(FSHeader.SubFileCount + FSHeader.SubFileCount2);

                Console.WriteLine(reader.BaseStream.Position.ToString("X"));
                //uint max = 0;

                /*using (StreamWriter writer = new StreamWriter(new FileStream("FS1.txt", FileMode.Create)))
                 *  for (int i = 0; i < (int)FSHeader.FileInformationCount; i++)
                 *  {
                 *      var fileinfo = fileInfoV2[i];
                 *      var path = fileInfoPath[fileinfo.PathIndex];
                 *      var subindex = fileInfoSubIndex[fileinfo.SubIndexIndex];
                 *      writer.WriteLine(fileinfo.Flags.ToString("X") + " " + fileinfo.PathIndex.ToString("X") + " " + subindex.SubFileIndex.ToString("X") + " " + HashDict.GetString(path.Path) + " " + HashDict.GetString(path.FileName));
                 *      //max = Math.Max(max, fp.SomeIndex2);
                 *  }
                 * using (StreamWriter writer = new StreamWriter(new FileStream("FS2.txt", FileMode.Create)))
                 * for (int i = (int)FSHeader.FileInformationCount ;i < fileInfoV2.Length; i++)
                 *  {
                 *      var fileinfo = fileInfoV2[i];
                 *      var path = fileInfoPath[fileinfo.PathIndex];
                 *      var subindex = fileInfoSubIndex[fileinfo.SubIndexIndex];
                 *      writer.WriteLine(fileinfo.Flags.ToString("X") + " " + fileinfo.PathIndex.ToString("X") + " " + subindex.SubFileIndex.ToString("X") + " " + HashDict.GetString(path.Path) + " " + HashDict.GetString(path.FileName));
                 *      //max = Math.Max(max, fp.SomeIndex2);
                 *  }*/
                //Console.WriteLine("Max: " + max.ToString("X"));

                /*int MaxIntTableValue = 0;
                 * foreach (var g in fileInfoIndex)
                 * {
                 *  MaxIntTableValue = Math.Max((int)g.FileInformationIndex, MaxIntTableValue);
                 *  //Console.WriteLine(HashDict.GetString(g.Hash));
                 * }
                 * Console.WriteLine("Max table value: " + MaxIntTableValue.ToString("X"));*/

                /*var flags = new System.Collections.Generic.List<uint>();
                 * foreach (var g in fileInfoV2)
                 * {
                 *  if (!flags.Contains(g.Flags))
                 *      flags.Add(g.Flags);
                 * }*/
                /*using (StreamWriter writer = new StreamWriter(new FileStream("print.txt", FileMode.Create)))
                 *  foreach (var g in PathNameHashLengthLookup)
                 *  {
                 *      writer.WriteLine(HashDict.GetString(g.FilePathHash) + " " + HashDict.GetString(PathNameHashGroupLookup[IndexTable[g.ExtensionHash]].FileNameHash));
                 *  }*/
            }
        }
Example #7
0
        /// <summary>
        /// Reads file system table from Arc
        /// </summary>
        /// <param name="fileSystemTable"></param>
        private void ReadFileSystem(byte[] fileSystemTable)
        {
            using (ExtBinaryReader reader = new ExtBinaryReader(new MemoryStream(fileSystemTable)))
            {
                fsHeader = reader.ReadType <_sFileSystemHeader>();

                uint extraFolder   = 0;
                uint extraCount    = 0;
                uint extraCount2   = 0;
                uint extraSubCount = 0;

                if (fileSystemTable.Length >= 0x2992DD4)
                {
                    // Version 3+
                    Version = reader.ReadInt32();

                    extraFolder = reader.ReadUInt32();
                    extraCount  = reader.ReadUInt32();

                    reader.ReadBytes(8);  // some extra thing :thinking
                    extraCount2   = reader.ReadUInt32();
                    extraSubCount = reader.ReadUInt32();
                }
                else
                {
                    Version = 0x00020000;
                    reader.BaseStream.Seek(0x3C, SeekOrigin.Begin);
                }

                // skip this for now
                regionalBytes = reader.ReadBytes(0xE * 12);

                // Streams
                streamHeader = reader.ReadType <_sStreamHeader>();

                streamUnk = reader.ReadType <_sStreamUnk>(streamHeader.UnkCount);

                streamHashToName = reader.ReadType <_sStreamHashToName>(streamHeader.StreamHashCount);

                streamNameToHash = reader.ReadType <_sStreamNameToHash>(streamHeader.StreamHashCount);

                streamIndexToFile = reader.ReadType <_sStreamIndexToOffset>(streamHeader.StreamIndexToOffsetCount);

                streamOffsets = reader.ReadType <_sStreamOffset>(streamHeader.StreamOffsetCount);

                Console.WriteLine(reader.BaseStream.Position.ToString("X"));

                // Unknown
                uint unkCount1 = reader.ReadUInt32();
                uint unkCount2 = reader.ReadUInt32();
                fileInfoUnknownTable     = reader.ReadType <_sFileInformationUnknownTable>(unkCount2);
                filePathToIndexHashGroup = reader.ReadType <_sHashIndexGroup>(unkCount1);

                // FileTables

                fileInfoPath = reader.ReadType <_sFileInformationPath>(fsHeader.FileInformationPathCount);

                fileInfoIndex = reader.ReadType <_sFileInformationIndex>(fsHeader.FileInformationIndexCount);

                // directory tables

                // directory hashes by length and index to directory probably 0x6000 something
                Console.WriteLine(reader.BaseStream.Position.ToString("X"));
                directoryHashGroup = reader.ReadType <_sHashIndexGroup>(fsHeader.DirectoryCount);

                directoryList = reader.ReadType <_sDirectoryList>(fsHeader.DirectoryCount);

                directoryOffsets = reader.ReadType <_sDirectoryOffset>(fsHeader.DirectoryOffsetCount1 + fsHeader.DirectoryOffsetCount2 + extraFolder);

                directoryChildHashGroup = reader.ReadType <_sHashIndexGroup>(fsHeader.DirectoryHashSearchCount);

                // file information tables
                Console.WriteLine(reader.BaseStream.Position.ToString("X"));
                fileInfoV2 = reader.ReadType <_sFileInformationV2>(fsHeader.FileInformationCount + fsHeader.SubFileCount2 + extraCount);

                fileInfoSubIndex = reader.ReadType <_sFileInformationSubIndex>(fsHeader.FileInformationSubIndexCount + fsHeader.SubFileCount2 + extraCount2);

                subFiles = reader.ReadType <_sSubFileInfo>(fsHeader.SubFileCount + fsHeader.SubFileCount2 + extraSubCount);
                Console.WriteLine("End:" + reader.BaseStream.Position.ToString("X"));
            }
        }