byte[] _Read(uint count) { byte[] data = Reader.ReadBytes((int)count); for (int i = 0; i < data.Length; i++) { Key = CryptedDtbStream.XorKey(Key); data[i] ^= (byte)Key; } Offset += (uint)data.Length; return(data); }
void _Write(byte[] buffer, uint offset, uint count) { byte[] buf = new byte[count]; for (int i = 0; i < count; i++) { Key = CryptedDtbStream.XorKey(Key); buf[i] = (byte)(buffer[i + offset] ^ Key); } Stream.Write(buf, 0, (int)count); Offset += count; }
public ChunkedDtbStream(EndianReader reader) { Mode = ChunkedMode.Chunk; Stream = reader.Base; Reader = reader; uint i, j; Stream.Position = 4; Key = Reader.ReadInt32(); ChunkMap = new int[Chunks + 1]; Seeds = new int[SeedIndexCount]; ChunkMap[0] = -8; for (i = 1; i <= Chunks; i++) { int pos; Stream.Position = (i - 1) * ChunkSize; byte[] buffer = Reader.ReadBytes(ChunkSize); for (pos = ChunkSize; pos > 0; pos--) { if (buffer[pos - 1] != 0) { break; } } ChunkMap[i] = ChunkMap[i - 1] + pos; } length = (uint)ChunkMap[ChunkMap.Length - 1]; //Length = ChunkMap[(sizeof(ChunkMap)/sizeof(ChunkMap[0]))-1]; // calculate seeds for faster seeking for (i = 0; i < length; i += SeedLength) { Seeds[i / SeedLength] = Key; for (j = 0; j < SeedLength; j++) { Key = CryptedDtbStream.XorKey(Key); } } Offset = 0; Key = Seeds[0]; Stream.Position = 8; }
public Ark(EndianReader hdrstream, params Stream[] arkstreams) : this() { HdrStream = hdrstream; ArkStreams = arkstreams; HdrStream.Position = 0; Version = HdrStream.ReadUInt32(); uint numArks; uint numArks2; long[] arkSizes; int stringSize; Stream stringTable; int numOffsets; int[] offsetTable; int numEntries; if (Version == ArkMagic || Version == ArkMagicLE) // FreQuency { Version = HdrStream.ReadUInt32(); // == 2 int fileoffset = HdrStream.ReadInt32(); numEntries = HdrStream.ReadInt32(); int diroffset = HdrStream.ReadInt32(); numOffsets = HdrStream.ReadInt32(); int stringoffset = HdrStream.ReadInt32(); int numStrings = HdrStream.ReadInt32(); HdrStream.ReadInt32(); int sectorSize = HdrStream.ReadInt32(); HdrStream.Position = diroffset; offsetTable = new int[numOffsets]; for (int i = 0; i < numOffsets; i++) { HdrStream.ReadInt32(); // Hash + 0x0000 offsetTable[i] = HdrStream.ReadInt32(); } HdrStream.Position = stringoffset; stringTable = new MemoryStream(); EndianReader writer = new EndianReader(stringTable, Endianness.BigEndian); for (int i = 0; i < numStrings; i++) { writer.Write(Util.ReadCString(HdrStream)); writer.Write((byte)0); } HdrStream.Position = fileoffset; for (int i = 0; i < numEntries; i++) { HdrStream.ReadInt16(); // Hash HdrStream.ReadInt16(); // Flags int nameoffset = HdrStream.ReadInt32(); // Filename int directory = HdrStream.ReadInt16(); int sectoroffset = HdrStream.ReadInt16(); int sector = HdrStream.ReadInt32(); uint size = HdrStream.ReadUInt32(); HdrStream.ReadInt32(); // Extracted length stringTable.Position = offsetTable[directory] - stringoffset; string pathname = Util.ReadCString(stringTable); stringTable.Position = nameoffset - stringoffset; string filename = Util.ReadCString(stringTable); DirectoryNode dir = Root.Navigate(pathname, true) as DirectoryNode; dir.AddChild(new FileNode(filename, size, new Substream(HdrStream, sector * sectorSize + sectoroffset, (long)size))); } } else { if (Version > 5) // Invalid version number, encrypted { Stream stream = new CryptedDtbStream(HdrStream); HdrStream = new EndianReader(stream, HdrStream.Endian); HdrStream.Position = 0; Version = HdrStream.ReadUInt32(); } if (Version <= 2) { numArks = 1; numArks2 = 1; arkSizes = new long[1] { HdrStream.Base.Length }; ArkStreams = new Stream[1] { HdrStream.Base }; numEntries = HdrStream.ReadInt32(); HdrStream.Position += numEntries * (4 * 4 + 4); } else if (Version <= 5) { numArks = HdrStream.ReadUInt32(); numArks2 = HdrStream.ReadUInt32(); arkSizes = new long[numArks]; for (int i = 0; i < numArks; i++) { if (Version == 4) { arkSizes[i] = HdrStream.ReadInt64(); } else { arkSizes[i] = (long)HdrStream.ReadUInt32(); } } if (Version == 5) // ark file string list { numArks = HdrStream.ReadUInt32(); for (int i = 0; i < numArks; i++) { int strsize = HdrStream.ReadInt32(); HdrStream.PadRead(strsize); // I'm not using them >.> } } } else { throw new FormatException(); } stringSize = HdrStream.ReadInt32(); stringTable = new MemoryStream(HdrStream.ReadBytes(stringSize), false); numOffsets = HdrStream.ReadInt32(); offsetTable = new int[numOffsets]; for (int i = 0; i < numOffsets; i++) { offsetTable[i] = HdrStream.ReadInt32(); } if (Version <= 2) { HdrStream.Position = 0x04; } numEntries = HdrStream.ReadInt32(); for (int i = 0; i < numEntries; i++) { long offset; if (Version <= 3) { offset = (long)HdrStream.ReadUInt32(); } else { offset = HdrStream.ReadInt64(); } uint filenameStringIndex = HdrStream.ReadUInt32(); uint dirnameStringIndex = HdrStream.ReadUInt32(); ulong size = 0; if (Version <= 2) { size = HdrStream.ReadUInt32(); HdrStream.ReadInt32(); // unknown, flags? } else { size = HdrStream.ReadUInt64(); } string pathname; if (dirnameStringIndex == 0xFFFFFFFF) { pathname = string.Empty; } else { stringTable.Position = offsetTable[dirnameStringIndex]; pathname = Util.ReadCString(stringTable); } stringTable.Position = offsetTable[filenameStringIndex]; string filename = Util.ReadCString(stringTable); DirectoryNode dir = Root.Navigate(pathname, true) as DirectoryNode; int ark; for (ark = 0; offset >= arkSizes[ark]; offset -= arkSizes[ark++]) { ; } if (dir != null) // Arks sometimes have paths like "../../etc", so we're just going to ignore them { dir.AddChild(new FileNode(filename, size, new Substream(ArkStreams[ark], offset, (long)size))); } } } }