/// <summary> /// Appends a file to the index and accompanying data file. /// </summary> /// <param name="directory">The directory that will be stored in the index.</param> /// <param name="fileName">The filename that will be stored in the index.</param> /// <param name="bytesToWrite">Byte array of the file to add.</param> /// <param name="fileTime">File time to set to the file.</param> /// <returns>Returns true if the operation was successful.</returns> public override bool AddFile(String directory, String fileName, byte[] bytesToWrite, DateTime?fileTime = null) { if (bytesToWrite == null || bytesToWrite.Length == 0) { throw new ArgumentNullException("bytesToWrite", "Bytes to write cannot be empty!"); } bool doCompress = NoCompressionExt.All(extentsion => !fileName.EndsWith(extentsion)); if (fileTime == null) { fileTime = DateTime.Now; } FileEntryStruct fileStruct = new FileEntryStruct { StartToken = Token.Info, SizeUncompressed = bytesToWrite.Length, SizeCompressed = doCompress ? 1 : 0, FileTime = fileTime.Value.ToFileTime(), NameHash = Crypt.GetStringSHA1UInt32(fileName), DirectoryHash = Crypt.GetStringSHA1UInt32(directory), First4BytesOfFile = FileTools.ByteArrayToInt32(bytesToWrite, 0), Second4BytesOfFile = FileTools.ByteArrayToInt32(bytesToWrite, 4), EndToken = Token.Info, }; PackFileEntry fileEntry = new FileEntry(fileStruct); fileEntry.Directory = directory; fileEntry.Name = fileName; Files.Add(fileEntry); _AddFileToDat(bytesToWrite, fileEntry); // todo: create new applicable file entry object as well? // todo: remove existing file bytes if applicable... return(true); }
public int[] ReadScriptTable(int offset) { if (offset == 0) { return(null); } int position = offset; int value = FileTools.ByteArrayToInt32(_scriptBuffer, position); while (value != 0) { if (ScriptOpCodeSizes.Case01.Contains(value)) { position += (3 * sizeof(int)); } else if (ScriptOpCodeSizes.Case02.Contains(value)) { position += (2 * sizeof(int)); } else if (ScriptOpCodeSizes.Case03.Contains(value)) { position += (1 * sizeof(int)); } else if (ScriptOpCodeSizes.BitField.Contains(value)) { position += (2 * sizeof(int)); } else { return(null); } value = FileTools.ByteArrayToInt32(_scriptBuffer, position); } int length = (position + sizeof(int) - offset) / sizeof(int); return(FileTools.ByteArrayToInt32Array(_scriptBuffer, ref offset, length)); }
public StringsFile(byte[] buffer, String filePath) { IsStringsFile = true; FilePath = filePath; StringId = _GetStringId(filePath); if (StringId == null) { throw new Exceptions.DataFileStringIdNotFound(filePath); } Attributes = DataFileMap[StringId]; // create field delegators FieldInfo[] dataFileFields = Attributes.RowType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); dataFileFields = dataFileFields.OrderBy(f => f.MetadataToken).ToArray(); // order by defined order - GetFields does not guarantee ordering Delegator = new ObjectDelegator(dataFileFields); Rows = new List <Object>(); int peek = FileTools.ByteArrayToInt32(buffer, 0); bool isCSV = (peek != Token.Header); HasIntegrity = ((isCSV)) ? ParseCSV(buffer) : ParseData(buffer); }
/// <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); }
private static bool _ParsePropertiesScript(byte[] data, ref int offset, ref ExcelFunction excelScript) { ExcelFunction.Parameter parameter = new ExcelFunction.Parameter(); // token and version checks if (!_CheckToken(data, ref offset, Token.mysh)) { return(false); } UInt32 version = FileTools.ByteArrayToUInt32(data, ref offset); if (version != Token.MyshVersion) { return(false); } // general parameter values int charCount = FileTools.ByteArrayToInt32(data, ref offset); if (charCount >= 0x1000) { return(false); } parameter.Name = FileTools.ByteArrayToStringASCII(data, ref offset, charCount); parameter.Unknown = FileTools.ByteArrayToUInt32(data, ref offset); // what kind of parameter is it parameter.TypeId = FileTools.ByteArrayToUInt32(data, ref offset); int paramLength; switch (parameter.TypeId) { case 0x38: // 56 // "nPowerChange" from TCv4 Skills paramLength = 4; break; case 0x39: // 57 // oldstats, x, sel, dmgtype, ? paramLength = 4; break; case 0x3C: // 60 // dam, ? paramLength = 5; break; case 0x41: // 65 // dmg_elec, dmg_fire, etc paramLength = 8; break; default: Debug.Assert(false, "Unknown MYSH TypeId = " + parameter.TypeId); return(false); } parameter.TypeValues = FileTools.ByteArrayToInt32Array(data, ref offset, paramLength); excelScript.Parameters.Add(parameter); if (parameter.TypeId != 0x41) { return(true); // only 0x41 has paramaters and a script values block following it } // get remaining parameters int paramCount = parameter.TypeValues[5]; for (int i = 0; i < paramCount; i++) { if (!_ParsePropertiesScript(data, ref offset, ref excelScript)) { return(false); } } // the actual script values int valuesByteCount = FileTools.ByteArrayToInt32(data, ref offset); if (valuesByteCount <= 0) { return(false); } excelScript.ScriptByteCode = new byte[valuesByteCount]; Buffer.BlockCopy(data, offset, excelScript.ScriptByteCode, 0, valuesByteCount); offset += valuesByteCount; return(true); }
private static bool _CheckToken(byte[] buffer, ref int offset, int token) { return(token == FileTools.ByteArrayToInt32(buffer, ref offset)); }
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); }