public static ChunkyCollection ReadChunkyChunks(byte[] chunkBytes) { MemoryStream ms = new MemoryStream(chunkBytes, false); RelicBinaryReader br = new RelicBinaryReader(ms); remaining = new byte[0]; int pos = 0; int fileLength = chunkBytes.Length; ChunkyCollection col = new ChunkyCollection(); while (pos<fileLength && (fileLength-pos)>20) //check that there's a reasonable amount remaining so that the app doesn't choke on the extra bytes //added to the end of files like Relic's Chunky Viewer does on SpookyRAT extracted files { string type = br.ReadString(4); if (type == "FOLD" || type=="DATA") { string id = br.ReadString(4); int version = br.ReadInt32(); int dataLength = br.ReadInt32(); int nameLength = br.ReadInt32(); string name = br.ReadString(nameLength); byte[] innerData = br.ReadBytes(dataLength); if (type == "FOLD") { col.Add(new ChunkyFolder(id, version, name, innerData)); } else { col.Add(CreateChunkyChunk(id, "", version, name, innerData)); } pos+= dataLength+nameLength+20; } else if (type == "Reli") { br.BaseStream.Seek(-4, SeekOrigin.Current); remaining = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position)); //we've hit another chunk, so stop the reading break; } else if (type=="") { //HACK: drop out with REC files rather than exceptioning, as the trailing info doesn't seem to be Chunkified remaining = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position)); break; } else { throw new InvalidChunkException("Chunk was not of type FOLD or DATA"); } } return col; }
public RelicChunkyStructure(ChunkyFolder chunkyRoot, int unknown1, int unknown2, int unknown3) { chunkCol = new ChunkyCollection(); chunkCol.Add(chunkyRoot); unknownInt1 = unknown1; unknownInt2 = unknown2; unknownInt3 = unknown3; }
public ChunkyFolder(string ID_in, int version_in, string name_in, byte[] innerData) : base(ChunkyChunkType.Folder, ID_in, version_in, name_in) { children = new ChunkyCollection(this); MemoryStream ms = new MemoryStream(innerData, false); BinaryReader br = new BinaryReader(ms); ChunkyChunk chunk = null; ChunkyDataATTR attr = null; ChunkyDataINFOTPAT info = null; int pos = 0; while (pos < innerData.Length) { br.BaseStream.Seek(pos, SeekOrigin.Begin); chunk = RelicChunkReader.ReadChunkyChunk(br.ReadBytes(innerData.Length - pos), ID_in); children.Add(chunk); if (chunk is ChunkyDataATTR) { attr = (ChunkyDataATTR)chunk; } else if (chunk is ChunkyDataINFOTPAT) { info = (ChunkyDataINFOTPAT)chunk; } else if (attr != null && chunk is ChunkyDataDATA) { ((ChunkyDataDATA)chunk).Attributes = attr; } else if (info != null && chunk is ChunkyDataLayer) { ((ChunkyDataLayer)chunk).Info = info; } pos += chunk.Length; } }
private static ChunkyStructureCollection ReadChunkyStructure(BinaryReader br, long fileLength) { //long end = fileLength - 20; ChunkyStructureCollection structCol = new ChunkyStructureCollection(); int unknown1 = br.ReadInt32(); int unknown2 = br.ReadInt32(); int unknown3 = br.ReadInt32(); byte[] bytes = br.ReadBytes((int)(fileLength - br.BaseStream.Position)); structCol.Add(new RelicChunkyStructure(RelicChunkReader.ReadChunkyChunks(bytes), unknown1, unknown2, unknown3)); if (RelicChunkReader.HasRemainingBytes()) { byte[] remainingData = RelicChunkReader.GetRemainingBytes(); if (remainingData[0] == 0x52 && remainingData[1] == 0x65 && remainingData[2] == 0x6C && remainingData[3] == 0x69) { MemoryStream ms = new MemoryStream(remainingData); BinaryReader br2 = new BinaryReader(ms); ChunkyStructureCollection col = ReadChunkyFileStructure(br2); foreach (RelicChunkyStructure strct in col) { structCol.Add(strct); } } else { ChunkyCollection col = new ChunkyCollection(); col.Add(new ChunkyRawData(remainingData)); structCol.Add(new RelicChunkyStructure(col)); } } return(structCol); }