public override void ParseFileBytes(byte[] fileBytes)
        {
            int      offset   = 0;
            FileInfo fileInfo = new FileInfo(Path);


            // read header
            _header = FileTools.ByteArrayToStructure <Header>(fileBytes, ref offset);
            if (_header.MagicWord != FileMagicWord)
            {
                return;                                     // todo add exception
            }
            // read file entries
            int bytesRemaining = (int)(fileInfo.Length - offset);
            int structSize     = Marshal.SizeOf(typeof(FileEntryStruct));

            if (bytesRemaining % structSize != 0)
            {
                // todo: add fail/warning?
            }
            int fileEntryCount = bytesRemaining / structSize;

            _fileEntryStructs = FileTools.ByteArrayToArray <FileEntryStruct>(fileBytes, ref offset, fileEntryCount);


            // process file entries
            foreach (FileEntryStruct fileEntryStruct in _fileEntryStructs)
            {
                Files.Add(new FileEntry(fileEntryStruct)
                {
                    Pack = this
                });
            }
        }
Beispiel #2
0
        public void ParseFileBytes(byte[] fileBytes, bool debugOutputLoadingProgress)
        {
            // sanity check
            if (fileBytes == null)
            {
                throw new ArgumentNullException("fileBytes", "File bytes cannot be null!");
            }

            Character = new UnitObject(debugOutputLoadingProgress);
            int byteOffset = 0;

            // main file header
            FileHeader fileHeader = FileTools.ByteArrayToStructure <FileHeader>(fileBytes, ref byteOffset);

            // file header checks
            if (fileHeader.MagicWord != FileMagicWord)
            {
                throw new Exceptions.UnexpectedMagicWordException();
            }
            if (fileHeader.Version != RequiredVersion)
            {
                throw new Exceptions.NotSupportedFileVersionException();
            }

            byteOffset = UnitObjectOffset;
            Character.ParseUnitObject(fileBytes, byteOffset, fileBytes.Length - byteOffset);
        }
Beispiel #3
0
        /// <summary>
        /// Parses a level rules file bytes.
        /// </summary>
        /// <param name="fileBytes">The bytes of the level rules to parse.</param>
        public override void ParseFileBytes(byte[] fileBytes)
        {
            // sanity check
            if (fileBytes == null)
            {
                throw new ArgumentNullException("fileBytes", "File bytes cannot be null!");
            }
            _xmlLevelRules = new XmlLevelRules();
            int offset = 0;


            // file header checks
            UInt32 fileMagicWord = FileTools.ByteArrayToUInt32(fileBytes, ref offset);

            if (fileMagicWord != FileMagicWord)
            {
                throw new Exceptions.UnexpectedMagicWordException();
            }

            UInt32 fileVersion = FileTools.ByteArrayToUInt32(fileBytes, ref offset);

            if (fileVersion != RequiredVersion)
            {
                throw new Exceptions.NotSupportedFileVersionException();
            }


            // main file header
            _xmlLevelRules.FileHeader = FileTools.ByteArrayToStructure <LevelRulesHeader>(fileBytes, ref offset);
            LevelRulesHeader header = _xmlLevelRules.FileHeader;


            // static rules
            if (header.StaticRulesCount != 0 && header.StaticRulesFooterOffset != 0)
            {
                _xmlLevelRules.LevelRules = new LevelRule[header.StaticRulesCount];
                int staticRulesFooterOffset = (int)header.StaticRulesFooterOffset;
                for (int i = 0; i < header.StaticRulesCount; i++)
                {
                    int roomsCount = FileTools.ByteArrayToInt32(fileBytes, staticRulesFooterOffset);
                    staticRulesFooterOffset += 8;
                    int roomsOffset = FileTools.ByteArrayToInt32(fileBytes, staticRulesFooterOffset);
                    staticRulesFooterOffset += 8;

                    _xmlLevelRules.LevelRules[i] = new LevelRule
                    {
                        StaticRooms = FileTools.ByteArrayToArray <Room>(fileBytes, roomsOffset, roomsCount)
                    };
                    offset += Marshal.SizeOf(typeof(Room)) * roomsCount + 16;
                    _UpdateRoomsDesc(_xmlLevelRules.LevelRules[i].StaticRooms);
                }
            }
            else if (header.RandomRulesCount != 0 && header.RandomRulesFooterOffset != 0)
            {
                _xmlLevelRules.LevelRules = new LevelRule[header.RandomRulesCount]; // checked all files an no files have both static and random, so no chance of overwriting static above
                LevelRulesRandomFooter[] levelRulesFooters = FileTools.ByteArrayToArray <LevelRulesRandomFooter>(fileBytes, (int)header.RandomRulesFooterOffset, (int)header.RandomRulesCount);
                offset += Marshal.SizeOf(typeof(LevelRulesRandomFooter)) * (int)header.RandomRulesCount;

                for (int i = 0; i < header.RandomRulesCount; i++)
                {
                    _xmlLevelRules.LevelRules[i] = new LevelRule
                    {
                        // get rule connector rooms
                        ConnectorRooms = FileTools.ByteArrayToArray <Room>(fileBytes, (Int32)levelRulesFooters[i].ConnectorRuleOffset, (Int32)levelRulesFooters[i].ConnectorRoomCount),

                        // then the actual level rules
                        Rules = new Room[levelRulesFooters[i].RuleCount][]
                    };
                    offset += Marshal.SizeOf(typeof(Room)) * (int)levelRulesFooters[i].ConnectorRoomCount;
                    _UpdateRoomsDesc(_xmlLevelRules.LevelRules[i].ConnectorRooms);

                    for (int j = 0; j < levelRulesFooters[i].RuleCount; j++)
                    {
                        _xmlLevelRules.LevelRules[i].Rules[j] = FileTools.ByteArrayToArray <Room>(fileBytes, (Int32)levelRulesFooters[i].RuleOffsets[j], levelRulesFooters[i].RoomCounts[j]);
                        offset += Marshal.SizeOf(typeof(Room)) * levelRulesFooters[i].RoomCounts[j];
                        _UpdateRoomsDesc(_xmlLevelRules.LevelRules[i].Rules[j]);
                    }
                }
            }


            // final debug check CT_Rule100 is corrupt or something - has extra bytes at end of it
            //Debug.Assert(offset == fileBytes.Length);
        }
Beispiel #4
0
        /// <summary>
        /// Parses a level rules file bytes.
        /// </summary>
        /// <param name="fileBytes">The bytes of the level rules to parse.</param>
        public override void ParseFileBytes(byte[] fileBytes)
        {
            // sanity check
            if (fileBytes == null)
            {
                throw new ArgumentNullException("fileBytes", "File bytes cannot be null!");
            }
            RoomDefinition = new RoomDefinitionStruct();

            // file header checks
            int    offset        = 0;
            UInt32 fileMagicWord = FileTools.ByteArrayToUInt32(fileBytes, ref offset);

            if (fileMagicWord != FileMagicWord)
            {
                throw new Exceptions.UnexpectedMagicWordException();
            }

            UInt32 fileVersion = FileTools.ByteArrayToUInt32(fileBytes, ref offset);

            if (fileVersion != RequiredVersion)
            {
                throw new Exceptions.NotSupportedFileVersionException();
            }

            // main file header
            RoomDefinition.FileHeader = FileTools.ByteArrayToStructure <RoomDefinitionHeader>(fileBytes, ref offset);
            RoomDefinitionHeader header = RoomDefinition.FileHeader;

            // read UnknownStruct1 array
            offset = (int)header.Offset110;
            int count10C = header.Count10C;

            if (offset > 0 && count10C > 0)
            {
                RoomDefinition.UnknownStruct1Array = _ReadUnknownStruct1Array(fileBytes, ref offset, count10C); // FileTools.ByteArrayToArray<UnknownStruct1>(fileBytes, ref offset, count10C);
            }

            // read UnknownStruct2 array
            offset = (int)header.Offset120;
            int count118 = header.Count118;

            if (offset > 0 && count118 > 0)
            {
                RoomDefinition.UnknownStruct2Array = _ReadUnknownStruct2Array(fileBytes, ref offset, count118); // FileTools.ByteArrayToArray<UnknownStruct2>(fileBytes, ref offset, count118);
            }

            // read UnknownStruct3 arrays
            offset = (int)header.Offset288;
            int count29C = header.Count29C;
            int count298 = header.Count298;

            if (offset > 0 && count29C > 0 && count298 > 0)
            {
                RoomDefinition.UnknownStruct3Arrays = new UnknownStruct3[count29C][];
                for (int i = 0; i < count29C; i++)
                {
                    RoomDefinition.UnknownStruct3Arrays[i] = _ReadUnknownStruct3Array(fileBytes, ref offset, count298); // FileTools.ByteArrayToArray<UnknownStruct3>(fileBytes, ref offset, count298);
                }
            }
            // read UnknownStruct3 Int32 array
            offset = (int)header.Offset2A0;
            int count2A8 = header.Count2A8;

            if (offset > 0 && count2A8 > 0)
            {
                RoomDefinition.UnknownStruct3Int32Array = FileTools.ByteArrayToInt32Array(fileBytes, ref offset, count2A8);
            }

            // read room vertices array
            offset = (int)header.VerticesOffset;
            int vertexCount = header.VertexCount;

            if (offset > 0 && vertexCount > 0)
            {
                RoomDefinition.Vertices = _ReadVector3Array(fileBytes, ref offset, vertexCount); // FileTools.ByteArrayToArray<Vector3>(fileBytes, ref offset, vertexCount);
            }

            // read UnknownStruct5 array
            offset = (int)header.Offset278;
            int count280 = header.Count280;

            if (offset > 0 && count280 > 0)
            {
                RoomDefinition.UnknownStruct5Array = FileTools.ByteArrayToArray <UnknownStruct5>(fileBytes, ref offset, count280);
            }

            // read UnknownStruct6 array
            offset = (int)header.Offset130;
            int count12C = header.Count12C;

            if (offset > 0 && count12C > 0)
            {
                RoomDefinition.UnknownStruct6Array = FileTools.ByteArrayToArray <UnknownStruct6>(fileBytes, ref offset, count12C);
            }

            // read UnknownStruct7 array (not seen read like this - but it works) - has same structure (3xfloat) as UnknownStruct4
            offset = (int)header.Offset178;
            int count174 = header.Count174;

            if (offset > 0 && count174 > 0)
            {
                RoomDefinition.UnknownStruct7Array = _ReadUnknownStruct7Vector3Array(fileBytes, ref offset, count174); // FileTools.ByteArrayToArray<Vector3>(fileBytes, ref offset, count174);
            }

            // read UnknownStruct8 array (not seen read like this - but it works)
            offset = (int)header.Offset188;
            int count184 = header.Count184;

            if (offset > 0 && count184 > 0)
            {
                RoomDefinition.UnknownStruct8Array = _ReadUnknownStruct7Array(fileBytes, ref offset, count184); // FileTools.ByteArrayToArray<UnknownStruct7>(fileBytes, ref offset, count184);
            }

            // read UnknownStruct9 array
            offset = (int)header.Offset168;
            int countUnknown7 = header.Count160;

            if (offset > 0 && countUnknown7 > 0)
            {
                RoomDefinition.UnknownStructFooter = FileTools.ByteArrayToArray <UnknownStruct5>(fileBytes, ref offset, countUnknown7);
            }

            // final debug check
            Debug.Assert(offset == fileBytes.Length);
        }
Beispiel #5
0
        private void _ParseDataType(byte[] buffer)
        {
            int offset = 0;

            // header
            FileHeader fileHeader = FileTools.ByteArrayToStructure <FileHeader>(buffer, ref offset);

            if (fileHeader.FileToken != Token.Head)
            {
                throw new Exceptions.UnexpectedTokenException("Expected Head token but got 0x" + fileHeader.FileToken.ToString("X8"));
            }
            if (fileHeader.FileVersion != RequiredVersion)
            {
                throw new Exceptions.NotSupportedFileVersionException(RequiredVersion, fileHeader.FileVersion);
            }

            // Read the strings section
            StringsHeader stringsHeader = FileTools.ByteArrayToStructure <StringsHeader>(buffer, ref offset);

            if (stringsHeader.StringsToken != Token.Sect)
            {
                throw new Exceptions.UnexpectedTokenException(Token.Sect, stringsHeader.StringsToken);
            }
            List <String> strings = new List <String>();

            for (int i = 0; i < stringsHeader.StringsCount; i++)
            {
                strings.Add(FileTools.ByteArrayToStringASCII(buffer, offset));
                offset += strings[i].Length + 1; // +1 for \0
            }

            // String Details
            UInt32 stringsDetailsToken = FileTools.ByteArrayToUInt32(buffer, ref offset);

            if (stringsDetailsToken != Token.Sect)
            {
                throw new Exceptions.UnexpectedTokenException(Token.Sect, stringsDetailsToken);
            }
            // Skip over the details struct because we don't need it.
            offset += stringsHeader.StringsCount * Marshal.SizeOf(typeof(StringDetailsStruct));

            // Files Structure details
            UInt32 filesToken = FileTools.ByteArrayToUInt32(buffer, ref offset);

            if (filesToken != Token.Sect)
            {
                throw new Exceptions.UnexpectedTokenException(Token.Sect, stringsDetailsToken);
            }
            FileDetails.AddRange(FileTools.ByteArrayToArray <FileEntryStruct>(buffer, ref offset, fileHeader.FileCount));

            // The Files list is the public interface
            for (int i = 0; i < fileHeader.FileCount; i++)
            {
                PackFileEntry fileEntry = new FileEntry(FileDetails[i])
                {
                    Pack = this,
                    Path = System.IO.Path.Combine(strings[FileDetails[i].DirectoryIndex], strings[FileDetails[i].NameIndex]),
                };

                Files.Add(fileEntry);
            }

            HasIntegrity = true;
        }
Beispiel #6
0
        private void _ParsePatchType(byte[] buffer)
        {
            int offset = 0;

            /* This reading/parsing stores all date merely to make it clear of the file structure.
             * Given we're not going to be using this much at all, this will do for now until we know
             * what all the unknown fields are.
             */

            // header
            PatchFileHeader fileHeader = FileTools.ByteArrayToStructure <PatchFileHeader>(buffer, ref offset);

            if (fileHeader.EndToken != Token.PatchSect)
            {
                throw new Exceptions.UnexpectedTokenException("Expected PatchSect token but got 0x" + fileHeader.EndToken.ToString("X8"));
            }

            // file searches?
            List <PatchSearch> searchSegments = new List <PatchSearch>();

            while (true)
            {
                bool isPresent = (StreamTools.ReadInt32(buffer, ref offset) != 0);
                if (!isPresent)
                {
                    break;
                }

                int characterCount = StreamTools.ReadInt32(buffer, ref offset);

                PatchSearch searchSegment = new PatchSearch
                {
                    IsPresent      = true,
                    CharacterCount = characterCount,
                    FileSearch     = StreamTools.ReadStringUnicode(buffer, ref offset, characterCount, false)
                };

                searchSegments.Add(searchSegment);
            }

            // files
            List <PatchEntryStruct> entries = new List <PatchEntryStruct>();

            while (true)
            {
                int characterCount = StreamTools.ReadInt32(buffer, ref offset);

                PatchEntryStruct entrySegment = new PatchEntryStruct
                {
                    CharacterCount = characterCount,
                    FileName       = StreamTools.ReadStringUnicode(buffer, ref offset, characterCount, false),
                    UsedInX86      = (StreamTools.ReadInt32(buffer, ref offset) != 0),
                    UsedInX64      = (StreamTools.ReadInt32(buffer, ref offset) != 0),
                    Localization   = StreamTools.ReadInt16(buffer, ref offset),
                    FileSize       = StreamTools.ReadInt64(buffer, ref offset),
                    DatOffset      = StreamTools.ReadInt64(buffer, ref offset),
                    Hash           = StreamTools.ReadInt32(buffer, ref offset),
                    HasMoreEntries = StreamTools.ReadInt32(buffer, ref offset),
                };

                entries.Add(entrySegment);

                if (entrySegment.HasMoreEntries == -1)
                {
                    break;
                }
            }

            // add files to file list (could be done in above loop, but as mentioned earlier, this parsing method is almost enitrely out of random interest
            foreach (PatchEntryStruct entry in entries)
            {
                PackFileEntry fileEntry = new PatchFileEntry(entry)
                {
                    Pack = this
                };

                Files.Add(fileEntry);
            }

            HasIntegrity = (offset == buffer.Length);
        }
Beispiel #7
0
        public override sealed bool ParseData(byte[] buffer)
        {
            if ((buffer == null))
            {
                return(false);
            }
            int offset = 0;

            StringsHeader stringsHeader = FileTools.ByteArrayToStructure <StringsHeader>(buffer, ref offset);

            for (int i = 0; i < stringsHeader.Count; i++)
            {
                StringBlock stringBlock = new StringBlock
                {
                    ReferenceId = FileTools.ByteArrayToInt32(buffer, ref offset),
                    Unknown     = FileTools.ByteArrayToInt32(buffer, ref offset)
                };

                int count = FileTools.ByteArrayToInt32(buffer, ref offset);
                stringBlock.StringId = FileTools.ByteArrayToStringASCII(buffer, offset);
                offset += count + 1;

                stringBlock.Reserved = FileTools.ByteArrayToInt32(buffer, ref offset);

                count = FileTools.ByteArrayToInt32(buffer, ref offset);
                stringBlock.String = FileTools.ByteArrayToStringUnicode(buffer, offset, count);
                offset            += count;

                int attributeCount = FileTools.ByteArrayToInt32(buffer, ref offset);

                for (int j = 0; j < attributeCount; j++)
                {
                    count = FileTools.ByteArrayToInt32(buffer, ref offset);
                    int byteCount = (count + 1) * 2;

                    switch (j)
                    {
                    case 0:
                        stringBlock.Attribute1 = FileTools.ByteArrayToStringUnicode(buffer, offset, byteCount);
                        break;

                    case 1:
                        stringBlock.Attribute2 = FileTools.ByteArrayToStringUnicode(buffer, offset, byteCount);
                        break;

                    case 2:
                        stringBlock.Attribute3 = FileTools.ByteArrayToStringUnicode(buffer, offset, byteCount);
                        break;

                    case 3:
                        stringBlock.Attribute4 = FileTools.ByteArrayToStringUnicode(buffer, offset, byteCount);
                        break;
                    }

                    offset += byteCount;
                }

                Rows.Add(stringBlock);
            }

            return(HasIntegrity = ((offset == buffer.Length)) ? true : false);
        }