/// <param name="type">0 is YAZ0, 1 is YAY0, anything else is CompressionHeader</param> public int Compress(VoidPtr srcAddr, int srcLen, Stream outStream, IProgressTracker progress, int type) { _pSrc = (byte *)srcAddr; _sourceLen = srcLen; int chunkCount = (int)Math.Ceiling((double)srcLen / _threadChunk); if (progress != null) { progress.Begin(0, srcLen, 0); } _contractions = new List <Contraction> [chunkCount]; bool YAY0Comp = type == 1; if (type == 0) { YAZ0 header = new YAZ0(); header._tag = YAZ0.Tag; header._unCompDataLen = (uint)_sourceLen; outStream.Write(&header, YAZ0.Size); } else if (type == 1) { //Don't write YAY0 header yet. //Collect all compression data first } else { CompressionHeader header = new CompressionHeader(); header.Algorithm = CompressionType.RunLength; header.ExpandedSize = (uint)_sourceLen; outStream.Write(&header, 4 + (header.LargeSize ? 4 : 0)); } ParallelLoopResult result = Parallel.For(0, chunkCount, FindContractions); while (!result.IsCompleted) { Thread.Sleep(100); } List <Contraction> fullContractions; int codeBits, current; byte codeByte; //byte[] temp; int lastUpdate = srcLen; fullContractions = new List <Contraction>(); for (int i = 0; i < _contractions.Length; i++) { fullContractions.AddRange(_contractions[i]); _contractions[i].Clear(); _contractions[i] = null; } _contractions = null; //temp = new byte[3 * 8]; codeBits = 0; codeByte = 0; current = 0; List <byte> tempCounts = new List <byte>(); List <byte> tempData = new List <byte>(); List <byte> codes = new List <byte>(); List <List <byte> > counts = new List <List <byte> >(); List <List <byte> > data = new List <List <byte> >(); for (int i = 0; i < srcLen;) { if (codeBits == 8) { codes.Add(codeByte); counts.Add(tempCounts); data.Add(tempData); tempCounts = new List <byte>(); tempData = new List <byte>(); codeBits = 0; codeByte = 0; } if (current < fullContractions.Count && fullContractions[current].Location == i) { if (fullContractions[current].Size >= 0x12) { byte b1 = (byte)(fullContractions[current].Offset >> 8), b2 = (byte)(fullContractions[current].Offset & 0xFF); if (YAY0Comp) { tempCounts.Add(b1); tempCounts.Add(b2); } else { tempData.Add(b1); tempData.Add(b2); } tempData.Add((byte)(fullContractions[current].Size - 0x12)); } else { byte b1 = (byte)((fullContractions[current].Offset >> 8) | ((fullContractions[current].Size - 2) << 4)), b2 = (byte)(fullContractions[current].Offset & 0xFF); if (YAY0Comp) { tempCounts.Add(b1); tempCounts.Add(b2); } else { tempData.Add(b1); tempData.Add(b2); } } i += fullContractions[current++].Size; while (current < fullContractions.Count && fullContractions[current].Location < i) { current++; } } else { codeByte |= (byte)(1 << (7 - codeBits)); tempData.Add(_pSrc[i++]); } codeBits++; if (progress != null) { if (i % 0x4000 == 0) { progress.Update(i); } } } codes.Add(codeByte); counts.Add(tempCounts); data.Add(tempData); if (YAY0Comp) { //Write header YAY0 header = new YAY0(); header._tag = YAY0.Tag; header._unCompDataLen = (uint)_sourceLen; uint offset = 0x10 + (uint)codes.Count; header._countOffset = offset; foreach (List <byte> list in counts) { offset += (uint)list.Count; } header._dataOffset = offset; outStream.Write(&header, YAY0.Size); //Write codes foreach (byte c in codes) { outStream.WriteByte(c); } //Write counts foreach (List <byte> list in counts) { outStream.Write(list.ToArray(), 0, list.Count); } //Write data foreach (List <byte> list in data) { outStream.Write(list.ToArray(), 0, list.Count); } } else { for (int i = 0; i < codes.Count; i++) { //Write code outStream.WriteByte(codes[i]); //Write data outStream.Write(data[i].ToArray(), 0, data[i].Count); } } outStream.Flush(); if (progress != null) { progress.Finish(); } return((int)outStream.Length); }
public int CompressYAZ0(VoidPtr srcAddr, int srcLen, Stream outStream, IProgressTracker progress) { int dstLen = 4, bitCount; byte control; byte *sPtr = (byte *)srcAddr;//, ceil = sPtr + srcLen; int matchLength, matchOffset = 0; //Initialize Memory.Fill(_First, 0x40000, 0xFF); _wIndex = _wLength = 0; //Write header YAZ0 header = new YAZ0(); header._tag = YAZ0.Tag; header._unCompDataLen = (uint)srcLen; outStream.Write(&header, YAZ0.Size); byte[] blockBuffer = new byte[17]; int dInd; int lastUpdate = srcLen; int remaining = srcLen; if (progress != null) { progress.Begin(0, remaining, 0); } while (remaining > 0) { dInd = 1; for (bitCount = 0, control = 0; (bitCount < 8) && (remaining > 0); bitCount++) { control <<= 1; if ((matchLength = FindPattern(sPtr, remaining, ref matchOffset)) != 0) { blockBuffer[dInd++] = (byte)(((matchLength - 3) << 4) | ((matchOffset - 1) >> 8)); blockBuffer[dInd++] = (byte)(matchOffset - 1); } else { control |= 1; matchLength = 1; blockBuffer[dInd++] = *sPtr; } Consume(sPtr, matchLength, remaining); sPtr += matchLength; remaining -= matchLength; } //Left-align bits control <<= 8 - bitCount; //Write buffer blockBuffer[0] = control; outStream.Write(blockBuffer, 0, dInd); dstLen += dInd; if (progress != null) { if ((lastUpdate - remaining) > 0x4000) { lastUpdate = remaining; progress.Update(srcLen - remaining); } } } outStream.Flush(); if (progress != null) { progress.Finish(); } return(dstLen); }