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 }); } }
/// <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); }
/// <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!"); } _mliStruct = new MLIStruct(); // 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(); } // first block int flag = FileTools.ByteArrayToInt32(fileBytes, ref offset); int count = FileTools.ByteArrayToInt32(fileBytes, ref offset); if (flag == 1) { _mliStruct.UnknownStruct1Array = FileTools.ByteArrayToArray <UnknownStruct1>(fileBytes, ref offset, count); } if (flag == 1 && _mliStruct.UnknownStruct1Array[0].UnknownInt321 == 0x0A) { // shorts block int shortCount = FileTools.ByteArrayToInt32(fileBytes, ref offset); if (shortCount > 0) { _mliStruct.UnknownShortArray = FileTools.ByteArrayToShortArray(fileBytes, ref offset, shortCount); } // floats block int floatTripletCount = FileTools.ByteArrayToInt32(fileBytes, ref offset); if (floatTripletCount > 0) { _mliStruct.UnknownStruct2Array = FileTools.ByteArrayToArray <UnknownStruct2>(fileBytes, ref offset, floatTripletCount); } } // last two unknown blocks int count1 = FileTools.ByteArrayToInt32(fileBytes, fileBytes.Length - 8); int count2 = FileTools.ByteArrayToInt32(fileBytes, fileBytes.Length - 4); if (count1 > 0) { _mliStruct.UnknownStruct3Array1 = FileTools.ByteArrayToArray <UnknownStruct3>(fileBytes, ref offset, count1); } if (count2 > 0) { _mliStruct.UnknownStruct3Array2 = FileTools.ByteArrayToArray <UnknownStruct3>(fileBytes, ref offset, count2); } offset += 8; // for 2x count fields // final debug check Debug.Assert(offset == fileBytes.Length); }
/// <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); }
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; }