private byte[] DecompressCommon(SymbianDecompressor aDecompressor, int aSeekOffset, int aAmountToRead, int aMaximumOutputSize, out int aNumberOfInputBytesRead) { System.Diagnostics.Debug.WriteLine("[SIContentE32Image] DecompressCommon - START - " + base.Image.Name + " # " + System.Threading.Thread.CurrentThread.Name); // uint imageContentSize = iFileSize; uint orighdrsz = ImageHeader.TotalSize; uint remainder = imageContentSize - orighdrsz; // using (SymbianStreamReaderLE reader = base.ImageStream.CreateReader(SymbianStreamReaderLE.TCloseOperation.EResetPosition)) { long codePos = Image.ContentOffsetWithinDataStream + orighdrsz + aSeekOffset; reader.Seek(codePos); // byte[] input = reader.ReadBytes(aAmountToRead); byte[] output = new byte[aMaximumOutputSize]; // The decompressor tells us how many bytes of output it really created. int numberOfBytesCreated = aDecompressor.DecompressImage(input, output, out aNumberOfInputBytesRead); // We can then return that to the callee. byte[] ret = new byte[numberOfBytesCreated > 0 ? numberOfBytesCreated : 0]; if (numberOfBytesCreated > 0) { Array.Copy(output, ret, numberOfBytesCreated); } // System.Diagnostics.Debug.WriteLine("[SIContentE32Image] DecompressCommon - END - " + base.Image.Name + " # " + System.Threading.Thread.CurrentThread.Name); // return(ret); } }
private void DecompressBytePair(SymbianDecompressor aDecompressor) { int inputBytesRead = 0; // uint imageContentSize = iFileSize; uint orighdrsz = ImageHeader.TotalSize; uint uncompressedSize = ImageHeader.UncompressedSize; // First decompress the code byte[] code = DecompressCommon(aDecompressor, 0, (int)(imageContentSize - orighdrsz), (int)uncompressedSize, out inputBytesRead); if (code.Length < ImageHeader.CodeSize) { throw new Exception("E32Image bytepair decompression did not provide enough code"); } // Now get the data int remainder = (int)(uncompressedSize - inputBytesRead); byte[] data = DecompressCommon(aDecompressor, inputBytesRead, remainder, (int)uncompressedSize, out inputBytesRead); // We should have read all the decompressed data int totalAmountOfDecompressedDataSupplied = data.Length + code.Length; if (totalAmountOfDecompressedDataSupplied != uncompressedSize) { throw new Exception("E32Image bytepair decompression did not supply enough decompressed output"); } lock ( iCodeSyncRoot ) { iCode = new byte[uncompressedSize]; Array.Copy(code, iCode, code.Length); Array.Copy(data, 0, iCode, code.Length, data.Length); } }
protected override void DoDecompress() { lock ( iCodeSyncRoot ) { if (iCode == null) { TSymbianCompressionType type = this.CompressionType; switch (type) { default: case TSymbianCompressionType.ENone: // NB: This has not yet been observed in reality DecompressNone(); break; case TSymbianCompressionType.EDeflate: case TSymbianCompressionType.EBytePair: { using (SymbianDecompressor decompressor = SymbianDecompressor.NewByType(type)) { // switch (type) { case TSymbianCompressionType.EBytePair: DecompressBytePair(decompressor); break; case TSymbianCompressionType.EDeflate: DecompressDeflate(decompressor); break; } } break; } } if (iCode != null) { if (iStream != null) { iStream.Dispose(); iStream = null; } // iStream = new MemoryStream(iCode); } } } }
private void DecompressDeflate(SymbianDecompressor aDecompressor) { int inputBytesRead = 0; // uint imageContentSize = iFileSize; uint orighdrsz = ImageHeader.TotalSize; uint uncompressedSize = ImageHeader.UncompressedSize; byte[] combinedDataAndCode = DecompressCommon(aDecompressor, 0, (int)(imageContentSize - orighdrsz), (int)uncompressedSize, out inputBytesRead); if (combinedDataAndCode.Length != uncompressedSize) { throw new Exception("E32Image inflate decompression did not supply enough decompressed output"); } lock ( iCodeSyncRoot ) { iCode = combinedDataAndCode; } }
private void DoDecompressBytePair() { if (iContentIsPrepared == false) { SIHeaderROM imageHeader = ImageHeader; base.Trace("[SymbianImageROM] DoDecompressBytePair() - START - header uncompressed rom size: {0}", imageHeader.UncompressedRomSize); // Create new buffer and copy over rom image header SIMemoryStream resultantDataStream = new SIMemoryStream(imageHeader.UncompressedRomSize); int numPages = imageHeader.NumberOfPages; uint pageTableOffset = imageHeader.RomPageIndexOffset; uint romDataOffset = imageHeader.HeaderSizeLoader; base.Trace("[SymbianImageROM] DoDecompressBytePair() - numPages: {0}, pageTableOffset: {1}, romDataOffset: {2}", numPages, pageTableOffset, romDataOffset); // SymbianDecompressor decompressor = SymbianDecompressor.NewByType(TSymbianCompressionType.EBytePair); // List <SRomPageInfo> pages = new List <SRomPageInfo>(numPages + 1); for (int i = 0; i < numPages; i++) { // Read a page table entry long pageOffsetWithinFile = pageTableOffset + (i * SRomPageInfo.Size); //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - pageOffsetWithinFile: {1}", i, pageOffsetWithinFile ); base.ImageStream.Seek(pageOffsetWithinFile, SeekOrigin.Begin); SRomPageInfo pageInfo = SRomPageInfo.New((Stream)base.ImageStream, romDataOffset); // Process the entry based upon the compression type //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - pageInfo.DataSize: {1}, pageInfo.DataStart: {2}, pageInfo.CompressionType: {3}", i, pageInfo.DataSize, pageInfo.DataStart, pageInfo.CompressionType ); base.ImageStream.Seek(pageInfo.DataStart, SeekOrigin.Begin); if (pageInfo.CompressionType == SRomPageInfo.TSymbianCompressionType.ENoCompression) { // Read data - no decompression needed //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - PAGE NOT COMPRESSED", i ); resultantDataStream.Write(base.ImageStream, (int)pageInfo.DataSize); } else if (pageInfo.CompressionType == SRomPageInfo.TSymbianCompressionType.EBytePair) { //base.Trace( "[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - BYTE PAIR PAGE", i ); // Read data - need to decompress it byte[] compressedData = new byte[pageInfo.DataSize]; base.ImageStream.Read(compressedData, 0, compressedData.Length); // Make destination buffer - which is a page big byte[] uncompressedData = new byte[SRomPageInfo.KPageSize]; // Decompress to buffer - we're handling the page management, so we want raw decompression int error = decompressor.DecompressRaw(compressedData, uncompressedData); // Save it if (error < 0) { base.Trace("[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - Exception - bytepair decompression error", i); throw new Exception("BytePair decompression error: " + error.ToString()); } else if (error != SRomPageInfo.KPageSize) { base.Trace("[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - Exception - bytepair underflow error", i); throw new Exception("Decompressor underflow - only created " + error.ToString() + " bytes"); } else { resultantDataStream.Write(uncompressedData); } } else { base.Trace("[SymbianImageROM] DoDecompressBytePair() - page[{0:d5}] - UNSUPPORTED COMPRESSION TYPE - Exception!", i); throw new NotSupportedException("Unsupported page compression type"); } // Report progress base.ReportDecompressionEvent(TDecompressionEvent.EEventDecompressionProgress, ((float)i / (float)numPages) * 100); } // Now we can replace the base class stream (which is just the raw compressed file data) with the new uncompressed version base.ImageStream = resultantDataStream; iContentIsPrepared = true; base.Trace("[SymbianImageROM] DoDecompressBytePair() - END"); } }