using System; using System.Collections.Generic; using System.Text; namespace DSDecmp.Utils { internal static class LZUtil { /// /// Determine the maximum size of a LZ-compressed block starting at newPtr, using the already compressed data /// starting at oldPtr. Takes O(inLength * oldLength) = O(n^2) time. /// /// The start of the data that needs to be compressed. /// The number of bytes that still need to be compressed. /// The start of the raw file. /// The number of bytes already compressed. /// The offset of the start of the longest block to refer to. /// The length of the longest sequence of bytes that can be copied from the already decompressed data. internal static unsafe int GetOccurrenceLength(byte* newPtr, int newLength, byte* oldPtr, int oldLength, out int disp) { disp = 0; if (newLength == 0) return 0; int maxLength = 0; // try every possible 'disp' value (disp = oldLength - i) for (int i = 0; i < oldLength - 1; i++) { // work from the start of the old data to the end, to mimic the original implementation's behaviour // (and going from start to end or from end to start does not influence the compression ratio anyway) byte* currentOldStart = oldPtr + i; int currentLength = 0; // determine the length we can copy if we go back (oldLength - i) bytes // always check the next 'newLength' bytes, and not just the available 'old' bytes, // as the copied data can also originate from what we're currently trying to compress. for (int j = 0; j < newLength; j++) { // stop when the bytes are no longer the same if (*(currentOldStart + j) != *(newPtr + j)) break; currentLength++; } // update the optimal value if (currentLength > maxLength) { maxLength = currentLength; disp = oldLength - i; } } return maxLength; } } }