/// <summary> /// Returns the file data, decompressed if needed /// </summary> /// <param name="item">The grf file</param> /// <param name="decompress">Should the data decompressed?</param> /// <returns></returns> public byte[] GetFileData(RoGrfFileItem item, bool decompress) { byte[] buf = null; bool isUpdated = item.IsAdded || item.IsUpdated; if (isUpdated) { // Load data from file buf = File.ReadAllBytes(item.NewFilepath); } else if (item.FileData == null || item.FileData.Length != item.LengthCompressedAlign) { // Cache data CacheFileData(item); buf = item.FileData; } if (isUpdated == false && buf != null && buf.Length > 0) { // deocde, if needed if (item.Cycle >= 0 && Deflate.IsMagicHead(buf) == false) { RoGrfHelper.DecryptFileData(buf, item.Cycle == 0, item.Cycle); } // Decompress data if (decompress) { buf = Deflate.Decompress(buf); } } return(buf); }
/// <summary> /// Reads the uncompressed body of versions between 0x100 and 0x103. /// No compression of the body but a mess on filenames. /// </summary> /// <param name="binReader"></param> /// <param name="fileCount"></param> /// <param name="skipFiles"></param> /// <returns></returns> private bool ReadFilesVersion1(BinaryReader binReader, int fileCount, bool skipFiles) { mFileTableLength = (ulong)(binReader.BaseStream.Length - binReader.BaseStream.Position); mFiletableUncompressed = binReader.ReadBytes((int)mFileTableLength); // Read only body? if (skipFiles == false) { for (int i = 0, offset = 0; i < fileCount; i++) { var itemTableOffset = (uint)offset; var entryType = mFiletableUncompressed[offset + 12]; var offset2 = offset + BitConverter.ToInt32(mFiletableUncompressed, offset) + 4; if (entryType == 0) { offset = offset2 + 17; continue; } var nameLen = mFiletableUncompressed[offset] - 6; // These are client limits if (nameLen >= GrfMaxFilenameLength) { throw new Exception("Filename on index " + i + " is " + nameLen + " bytes long, max length is " + GrfMaxFilenameLength + "."); } var nameBuf = new byte[nameLen]; Buffer.BlockCopy(mFiletableUncompressed, offset + 6, nameBuf, 0, nameLen); var name = RoGrfHelper.DecodeFileName(nameBuf); // Check and fix the filename if (name.Contains('\0')) { name = name.Substring(0, name.IndexOf('\0')); } var compressedLenAligned = (uint)(BitConverter.ToInt32(mFiletableUncompressed, offset2 + 4) - 37579); var realLen = (uint)BitConverter.ToInt32(mFiletableUncompressed, offset2 + 8); var pos = (uint)BitConverter.ToInt32(mFiletableUncompressed, offset2 + 13); var cycle = 0; var compressedLen = 0; if (name.Contains(".")) { var ext = "." + name.Split('.').Last().ToLower(); compressedLen = BitConverter.ToInt32(mFiletableUncompressed, offset2) - BitConverter.ToInt32(mFiletableUncompressed, offset2 + 8) - 715; if (ext != ".gnd" && ext != ".gat" && ext != ".act" && ext != ".str") { cycle = 1; for (int j = 10; compressedLen >= j; j *= 10) { cycle++; } } } name = Tools.UnifyPath(name); var item = new RoGrfFileItem { TableOffset = itemTableOffset, Index = Files.Count, Filepath = name, LengthCompressed = (uint)compressedLen, LengthCompressedAlign = compressedLenAligned, LengthUnCompressed = realLen, Flags = entryType, // base offset + header length DataOffset = pos + GrfHeaderLen }; Files.Add(item.NameHash, item); mStringlist.Add(item.NameHash); mFileDataLength += item.LengthCompressedAlign; offset += (int)GrfFileLen; #if !DISABLE_GRF_EVENTS OnItemAdded(item, i, fileCount); #endif } } return(true); }