/// <summary> /// Takes regular image data and returns it in a compressed form ready for archiving /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] CompressTex(byte[] data) { int chunkSize = 131072; //Set at this stage. Easy to change later int noChunks = (data.Length + chunkSize - 1) / chunkSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; int pos = 0; for (int i = 0; i < noChunks; i++) { if (data.Length - (pos + chunkSize) < 0) { chunks[i].uncSize = data.Length - pos; chunks[i].rawData = new byte[chunks[i].uncSize]; Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunks[i].uncSize); pos += chunks[i].uncSize; } else { chunks[i].uncSize = chunkSize; chunks[i].rawData = new byte[chunkSize]; Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunkSize); pos += chunks[i].uncSize; } } pos = 0; CompressedChunkBlock[] newChunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { newChunks[i].rawData = LZO1X.Compress(chunks[i].rawData); newChunks[i].cprSize = newChunks[i].rawData.Length; newChunks[i].uncSize = chunks[i].uncSize; pos += newChunks[i].cprSize; } byte[] result; using (MemoryStream stream = new MemoryStream()) { byte[] magic = new byte[] { 0xC1, 0x83, 0x2A, 0x9E, 0x00, 0x00, 0x02, 0x00 }; pos = Gibbed.IO.NumberHelpers.LittleEndian(pos); BinaryWriter bin = new BinaryWriter(stream); bin.Write(magic); bin.Write(pos); pos = Gibbed.IO.NumberHelpers.LittleEndian(data.Length); //unc size bin.Write(pos); for (int i = 0; i < noChunks; i++) { int uncSize = newChunks[i].uncSize; int cprSize = newChunks[i].cprSize; uncSize = Gibbed.IO.NumberHelpers.LittleEndian(uncSize); cprSize = Gibbed.IO.NumberHelpers.LittleEndian(cprSize); bin.Write(cprSize); bin.Write(uncSize); } for (int i = 0; i < noChunks; i++) { bin.Write(newChunks[i].rawData); } result = stream.ToArray(); } return result; }
private void ReadChunks(Stream s) { try { DebugLog.PrintLn("Reading Chunks..."); for (int i = 0; i < Header.Chunks.Count; i++) { if (verbose) { DebugLog.PrintLn("Reading Chunk(" + i + ") Header..."); } CompressedChunk c = Header.Chunks[i]; s.Seek(c.CompOffset, 0); c.Magic = ReadUInt(s); if (c.Magic != 0x9E2A83C1) { throw new Exception("Not a valid Chunkheader, wrong magic!(#" + i + ")"); } c.BlockSize = ReadUInt(s); ReadUInt(s); ReadUInt(s); uint count = (c.UnCompSize + c.BlockSize - 1) / c.BlockSize; c.Blocks = new List <CompressedChunkBlock>(); if (verbose) { DebugLog.PrintLn("Reading Chunk(" + i + ") Blocks..."); } for (int j = 0; j < count; j++) { CompressedChunkBlock b = new CompressedChunkBlock(); b.CompSize = ReadUInt(s); b.UnCompSize = ReadUInt(s); b.loaded = false; c.Blocks.Add(b); } Header.Chunks[i] = c; } if (Header.Chunks.Count != 0) { uint FullSize = Header.Chunks[Header.Chunks.Count - 1].UnCompOffset + Header.Chunks[Header.Chunks.Count - 1].UnCompSize; Header.DeCompBuffer = new MemoryStream(new byte[FullSize]); Header.DeCompBuffer.Seek(0, 0); Source.Seek(0, 0); byte[] buff = new byte[Header._offsetCompFlagEnd]; Source.Read(buff, 0, (int)Header._offsetCompFlagEnd); Header.DeCompBuffer.Write(buff, 0, (int)Header._offsetCompFlagEnd); Header.DeCompBuffer.Write(BitConverter.GetBytes(0), 0, 4); Header.DeCompBuffer.Write(BitConverter.GetBytes(Header.unk7), 0, 4); Header.DeCompBuffer.Write(BitConverter.GetBytes(Header.unk8), 0, 4); Header.DeCompBuffer.Seek(Header._offsetFlag, 0); uint newFlags = (Header.Flags ^ 0x02000000); Header.DeCompBuffer.Write(BitConverter.GetBytes(newFlags), 0, 4); } } catch (Exception ex) { DebugLog.PrintLn("PCCPACKAGE::READCHUNKS ERROR:\n" + ex.Message); } }
private void UncompressRange(uint offset, uint size) { try { int startchunk = 0; int endchunk = -1; for (int i = 0; i < Header.Chunks.Count; i++) { if (Header.Chunks[i].UnCompOffset > offset) { break; } startchunk = i; } for (int i = 0; i < Header.Chunks.Count; i++) { if (Header.Chunks[i].UnCompOffset >= offset + size) { break; } endchunk = i; } if (startchunk == -1 || endchunk == -1) { return; } for (int i = startchunk; i <= endchunk; i++) { CompressedChunk c = Header.Chunks[i]; Header.DeCompBuffer.Seek(c.UnCompOffset, 0); for (int j = 0; j < c.Blocks.Count; j++) { CompressedChunkBlock b = c.Blocks[j]; uint startblock = (uint)Header.DeCompBuffer.Position; uint endblock = (uint)Header.DeCompBuffer.Position + b.UnCompSize; if (((startblock >= offset && startblock < offset + size) || (endblock >= offset && endblock < offset + size) || (offset >= startblock && offset < endblock) || (offset + size > startblock && offset + size <= endblock)) && !b.loaded) { Header.DeCompBuffer.Write(UncompressBlock(i, j), 0, (int)b.UnCompSize); b.loaded = true; c.Blocks[j] = b; Header.Chunks[i] = c; } else { Header.DeCompBuffer.Seek(b.UnCompSize, SeekOrigin.Current); } } } } catch (Exception ex) { DebugLog.PrintLn("PCCPACKAGE::UNCOMPRESSRANGE ERROR:\n" + ex.Message); } }
/// <summary> /// Takes compressed archived image data and returns the raw image data /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] DecompressTex(Stream archiveStream, int offset, int uncSize, int cprSize) { int pos = 0; archiveStream.Seek(offset, SeekOrigin.Begin); int magicNumber = archiveStream.ReadValueS32(); pos += 4; if (magicNumber != -1641380927) { throw new FormatException("Magic Number is not correct. Invalid archive data"); } int blockSize = archiveStream.ReadValueS32(); pos += 4; int readCprSize = archiveStream.ReadValueS32(); //Archive cprSize doesn't include header size pos += 4; int uncReadSize = archiveStream.ReadValueS32(); if (uncReadSize != uncSize) { throw new FormatException("Uncompressed data sizes don't match. Read: " + uncReadSize + ", expected: " + uncSize); } pos += 4; int noChunks = (uncSize + blockSize - 1) / blockSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = new CompressedChunkBlock(); chunk.cprSize = archiveStream.ReadValueS32(); chunk.uncSize = archiveStream.ReadValueS32(); chunk.rawData = new byte[chunk.cprSize]; pos += 8; chunks[i] = chunk; } if (readCprSize + pos != cprSize) { throw new FormatException("Compressed data sizes don't match. Invalid archive data"); } byte[] rawData = new byte[readCprSize]; rawData = archiveStream.ReadBytes(readCprSize); archiveStream.Close(); using (MemoryStream data = new MemoryStream(rawData)) { for (int i = 0; i < noChunks; i++) { chunks[i].rawData = data.ReadBytes(chunks[i].cprSize); } } byte[] imgBuffer = new byte[uncSize]; int resultPos = 0; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = chunks[i]; byte[] tempResult = new byte[chunk.uncSize]; try { LZO1X.Decompress(chunk.rawData, tempResult); } catch { throw new Exception("LZO decompression failed!"); } Buffer.BlockCopy(tempResult, 0, imgBuffer, resultPos, chunk.uncSize); resultPos += chunk.uncSize; } return imgBuffer; }
/// <summary> /// Takes regular image data and returns it in a compressed form ready for archiving /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] CompressTex(byte[] data) { int chunkSize = 131072; //Set at this stage. Easy to change later int noChunks = (data.Length + chunkSize - 1) / chunkSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; int pos = 0; for (int i = 0; i < noChunks; i++) { if (data.Length - (pos + chunkSize) < 0) { chunks[i].uncSize = data.Length - pos; chunks[i].rawData = new byte[chunks[i].uncSize]; Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunks[i].uncSize); pos += chunks[i].uncSize; } else { chunks[i].uncSize = chunkSize; chunks[i].rawData = new byte[chunkSize]; Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunkSize); pos += chunks[i].uncSize; } } pos = 0; CompressedChunkBlock[] newChunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { newChunks[i].rawData = LZO1X.Compress(chunks[i].rawData); if (newChunks[i].rawData.Length == 0) { throw new Exception("LZO compression failed!"); } newChunks[i].cprSize = newChunks[i].rawData.Length; newChunks[i].uncSize = chunks[i].uncSize; pos += newChunks[i].cprSize; } byte[] result; using (MemoryStream stream = new MemoryStream()) { byte[] magic = new byte[] { 0xC1, 0x83, 0x2A, 0x9E, 0x00, 0x00, 0x02, 0x00 }; pos = Gibbed.IO.NumberHelpers.LittleEndian(pos); BinaryWriter bin = new BinaryWriter(stream); bin.Write(magic); bin.Write(pos); pos = Gibbed.IO.NumberHelpers.LittleEndian(data.Length); //unc size bin.Write(pos); for (int i = 0; i < noChunks; i++) { int uncSize = newChunks[i].uncSize; int cprSize = newChunks[i].cprSize; uncSize = Gibbed.IO.NumberHelpers.LittleEndian(uncSize); cprSize = Gibbed.IO.NumberHelpers.LittleEndian(cprSize); bin.Write(cprSize); bin.Write(uncSize); } for (int i = 0; i < noChunks; i++) { bin.Write(newChunks[i].rawData); } result = stream.ToArray(); } return(result); }
/// <summary> /// Takes compressed archived image data and returns the raw image data /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] DecompressTex(Stream archiveStream, int offset, int uncSize, int cprSize) { int pos = 0; archiveStream.Seek(offset, SeekOrigin.Begin); int magicNumber = archiveStream.ReadValueS32(); pos += 4; if (magicNumber != -1641380927) { throw new FormatException("Magic Number is not correct. Invalid archive data"); } int blockSize = archiveStream.ReadValueS32(); pos += 4; int readCprSize = archiveStream.ReadValueS32(); //Archive cprSize doesn't include header size pos += 4; int uncReadSize = archiveStream.ReadValueS32(); if (uncReadSize != uncSize) { throw new FormatException("Uncompressed data sizes don't match. Read: " + uncReadSize + ", expected: " + uncSize); } pos += 4; int noChunks = (uncSize + blockSize - 1) / blockSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = new CompressedChunkBlock(); chunk.cprSize = archiveStream.ReadValueS32(); chunk.uncSize = archiveStream.ReadValueS32(); chunk.rawData = new byte[chunk.cprSize]; pos += 8; chunks[i] = chunk; } if (readCprSize + pos != cprSize) { throw new FormatException("Compressed data sizes don't match. Invalid archive data"); } byte[] rawData = new byte[readCprSize]; rawData = archiveStream.ReadBytes(readCprSize); archiveStream.Close(); using (MemoryStream data = new MemoryStream(rawData)) { for (int i = 0; i < noChunks; i++) { chunks[i].rawData = data.ReadBytes(chunks[i].cprSize); } } byte[] imgBuffer = new byte[uncSize]; int resultPos = 0; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = chunks[i]; byte[] tempResult = new byte[chunk.uncSize]; try { LZO1X.Decompress(chunk.rawData, tempResult); } catch { throw new Exception("LZO decompression failed!"); } Buffer.BlockCopy(tempResult, 0, imgBuffer, resultPos, chunk.uncSize); resultPos += chunk.uncSize; } return(imgBuffer); }
/// <summary> /// Takes regular image data and returns it in a compressed form ready for archiving /// </summary> /// <param name="data">Data to compress</param> /// <returns>Compressed texture</returns> public static byte[] CompressTex(byte[] data) { int chunkSize = 131072; //Set at this stage. Easy to change later int noChunks = (data.Length + chunkSize - 1) / chunkSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; int pos = 0; for (int i = 0; i < noChunks; i++) { if (data.Length - (pos + chunkSize) < 0) { chunks[i].uncSize = data.Length - pos; chunks[i].rawData = new byte[chunks[i].uncSize]; Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunks[i].uncSize); pos += chunks[i].uncSize; } else { chunks[i].uncSize = chunkSize; chunks[i].rawData = new byte[chunkSize]; Buffer.BlockCopy(data, pos, chunks[i].rawData, 0, chunkSize); pos += chunks[i].uncSize; } } pos = 0; CompressedChunkBlock[] newChunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { newChunks[i].rawData = LZOCompress(chunks[i].rawData); //MiniLZO.Compress(chunks[i].rawData, out newChunks[i].rawData); if (newChunks[i].rawData.Length == 0) throw new Exception("LZO compression failed!"); newChunks[i].cprSize = newChunks[i].rawData.Length; newChunks[i].uncSize = chunks[i].uncSize; pos += newChunks[i].cprSize; } byte[] result; using (MemoryStream stream = new MemoryStream()) { byte[] magic = new byte[] { 0xC1, 0x83, 0x2A, 0x9E, 0x00, 0x00, 0x02, 0x00 }; BinaryWriter bin = new BinaryWriter(stream); bin.Write(magic); bin.Write(pos); pos = data.Length; //unc size bin.Write(pos); for (int i = 0; i < noChunks; i++) { int uncSize = newChunks[i].uncSize; int cprSize = newChunks[i].cprSize; bin.Write(cprSize); bin.Write(uncSize); } for (int i = 0; i < noChunks; i++) { bin.Write(newChunks[i].rawData); } result = stream.ToArray(); } return result; }
private void ReadChunks(Stream s) { try { DebugLog.PrintLn("Reading Chunks..."); for (int i = 0; i < Header.Chunks.Count; i++) { if(verbose) DebugLog.PrintLn("Reading Chunk(" + i + ") Header..."); CompressedChunk c = Header.Chunks[i]; s.Seek(c.CompOffset, 0); c.Magic = ReadUInt(s); if (c.Magic != 0x9E2A83C1) throw new Exception("Not a valid Chunkheader, wrong magic!(#" + i + ")"); c.BlockSize = ReadUInt(s); ReadUInt(s); ReadUInt(s); uint count = (c.UnCompSize + c.BlockSize - 1) / c.BlockSize; c.Blocks = new List<CompressedChunkBlock>(); if (verbose) DebugLog.PrintLn("Reading Chunk(" + i + ") Blocks..."); for (int j = 0; j < count; j++) { CompressedChunkBlock b = new CompressedChunkBlock(); b.CompSize = ReadUInt(s); b.UnCompSize = ReadUInt(s); b.loaded = false; c.Blocks.Add(b); } Header.Chunks[i] = c; } if (Header.Chunks.Count != 0) { uint FullSize = Header.Chunks[Header.Chunks.Count - 1].UnCompOffset + Header.Chunks[Header.Chunks.Count - 1].UnCompSize; Header.DeCompBuffer = new MemoryStream(new byte[FullSize]); Header.DeCompBuffer.Seek(0, 0); Source.Seek(0, 0); byte[]buff = new byte[Header._offsetCompFlagEnd]; Source.Read(buff, 0, (int)Header._offsetCompFlagEnd); Header.DeCompBuffer.Write(buff, 0, (int)Header._offsetCompFlagEnd); Header.DeCompBuffer.Write(BitConverter.GetBytes(0), 0, 4); Header.DeCompBuffer.Write(BitConverter.GetBytes(Header.unk7), 0, 4); Header.DeCompBuffer.Write(BitConverter.GetBytes(Header.unk8), 0, 4); Header.DeCompBuffer.Seek(Header._offsetFlag, 0); uint newFlags = (Header.Flags ^ 0x02000000); Header.DeCompBuffer.Write(BitConverter.GetBytes(newFlags), 0, 4); } } catch (Exception ex) { DebugLog.PrintLn("PCCPACKAGE::READCHUNKS ERROR:\n" + ex.Message); } }