diff --git a/Assets/Scripts/OpenTS2/Files/Formats/DBPF/DBPFCompression.cs b/Assets/Scripts/OpenTS2/Files/Formats/DBPF/DBPFCompression.cs index 2303444..0dcd4e9 100644 --- a/Assets/Scripts/OpenTS2/Files/Formats/DBPF/DBPFCompression.cs +++ b/Assets/Scripts/OpenTS2/Files/Formats/DBPF/DBPFCompression.cs @@ -11,188 +11,188 @@ using UnityEngine; namespace OpenTS2.Files.Formats.DBPF { - public static class DBPFCompression - { - /// - /// Copies data from source to destination array.
- /// The copy is byte by byte from srcPos to destPos and given length. - ///
- /// The source array. - /// The source Position. - /// The destination array. - /// The destination Position. - /// The length. - public static void ArrayCopy2(byte[] Src, int SrcPos, ref byte[] Dest, int DestPos, long Length) - { - if (Dest.Length < DestPos + Length) - { - byte[] DestExt = new byte[(int)(DestPos + Length)]; - Array.Copy(Dest, 0, DestExt, 0, Dest.Length); - Dest = DestExt; - } + public static class DBPFCompression + { + /// + /// Copies data from source to destination array.
+ /// The copy is byte by byte from srcPos to destPos and given length. + ///
+ /// The source array. + /// The source Position. + /// The destination array. + /// The destination Position. + /// The length. + public static void ArrayCopy2(byte[] Src, int SrcPos, ref byte[] Dest, int DestPos, long Length) + { + if (Dest.Length < DestPos + Length) + { + byte[] DestExt = new byte[(int)(DestPos + Length)]; + Array.Copy(Dest, 0, DestExt, 0, Dest.Length); + Dest = DestExt; + } - for (int i = 0; i < Length/* - 1*/; i++) - Dest[DestPos + i] = Src[SrcPos + i]; - } - /// - /// Copies data from array at destPos-srcPos to array at destPos. - /// - /// The array. - /// The Position to copy from (reverse from end of array!) - /// The Position to copy to. - /// The length of data to copy. - public static void OffsetCopy(ref byte[] array, int srcPos, int destPos, long length) - { - srcPos = destPos - srcPos; + for (int i = 0; i < Length/* - 1*/; i++) + Dest[DestPos + i] = Src[SrcPos + i]; + } + /// + /// Copies data from array at destPos-srcPos to array at destPos. + /// + /// The array. + /// The Position to copy from (reverse from end of array!) + /// The Position to copy to. + /// The length of data to copy. + public static void OffsetCopy(ref byte[] array, int srcPos, int destPos, long length) + { + srcPos = destPos - srcPos; - if (array.Length < destPos + length) - { - byte[] NewArray = new byte[(int)(destPos + length)]; - Array.Copy(array, 0, NewArray, 0, array.Length); - array = NewArray; - } + if (array.Length < destPos + length) + { + byte[] NewArray = new byte[(int)(destPos + length)]; + Array.Copy(array, 0, NewArray, 0, array.Length); + array = NewArray; + } - if (array.Length < srcPos + length) - { - byte[] NewArray = new byte[(int)(srcPos + length)]; - Array.Copy(array, 0, NewArray, 0, array.Length); - array = NewArray; - } + if (array.Length < srcPos + length) + { + byte[] NewArray = new byte[(int)(srcPos + length)]; + Array.Copy(array, 0, NewArray, 0, array.Length); + array = NewArray; + } - for (int i = 0; i < length /*- 1*/; i++) - { - try - { - array[destPos + i] = array[srcPos + i]; - } - catch (Exception) - { - //Fail silently :( - } - } - } - public static byte[] Decompress(byte[] Data, uint UncompressedFileSize) - { + for (int i = 0; i < length /*- 1*/; i++) + { + try + { + array[destPos + i] = array[srcPos + i]; + } + catch (Exception) + { + //Fail silently :( + } + } + } + public static byte[] Decompress(byte[] Data, uint UncompressedFileSize) + { - MemoryStream MemData = new MemoryStream(Data); - BinaryReader Reader = new BinaryReader(MemData); + MemoryStream MemData = new MemoryStream(Data); + BinaryReader Reader = new BinaryReader(MemData); - if (Data.Length > 9) - { - byte[] DecompressedData = new byte[(int)UncompressedFileSize]; - int DataPos = 0; + if (Data.Length > 9) + { + byte[] DecompressedData = new byte[(int)UncompressedFileSize]; + int DataPos = 0; - int Pos = 9; - long Control1 = 0; + int Pos = 9; + long Control1 = 0; - while (Control1 != 0xFC && Pos < Data.Length) - { - Control1 = Data[Pos]; - Pos++; + while (Control1 != 0xFC && Pos < Data.Length) + { + Control1 = Data[Pos]; + Pos++; - if (Pos == Data.Length) - break; + if (Pos == Data.Length) + break; - if (Control1 >= 0 && Control1 <= 127) - { - // 0x00 - 0x7F - long control2 = Data[Pos]; - Pos++; - long numberOfPlainText = (Control1 & 0x03); - ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); - DataPos += (int)numberOfPlainText; - Pos += (int)numberOfPlainText; + if (Control1 >= 0 && Control1 <= 127) + { + // 0x00 - 0x7F + long control2 = Data[Pos]; + Pos++; + long numberOfPlainText = (Control1 & 0x03); + ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); + DataPos += (int)numberOfPlainText; + Pos += (int)numberOfPlainText; - if (DataPos == (DecompressedData.Length)) - break; + if (DataPos == (DecompressedData.Length)) + break; - int offset = (int)(((Control1 & 0x60) << 3) + (control2) + 1); - long numberToCopyFromOffset = ((Control1 & 0x1C) >> 2) + 3; - OffsetCopy(ref DecompressedData, offset, DataPos, numberToCopyFromOffset); - DataPos += (int)numberToCopyFromOffset; + int offset = (int)(((Control1 & 0x60) << 3) + (control2) + 1); + long numberToCopyFromOffset = ((Control1 & 0x1C) >> 2) + 3; + OffsetCopy(ref DecompressedData, offset, DataPos, numberToCopyFromOffset); + DataPos += (int)numberToCopyFromOffset; - if (DataPos == (DecompressedData.Length)) - break; - } - else if ((Control1 >= 128 && Control1 <= 191)) - { - // 0x80 - 0xBF - long control2 = Data[Pos]; - Pos++; - long control3 = Data[Pos]; - Pos++; + if (DataPos == (DecompressedData.Length)) + break; + } + else if ((Control1 >= 128 && Control1 <= 191)) + { + // 0x80 - 0xBF + long control2 = Data[Pos]; + Pos++; + long control3 = Data[Pos]; + Pos++; - long numberOfPlainText = (control2 >> 6) & 0x03; - ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); - DataPos += (int)numberOfPlainText; - Pos += (int)numberOfPlainText; + long numberOfPlainText = (control2 >> 6) & 0x03; + ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); + DataPos += (int)numberOfPlainText; + Pos += (int)numberOfPlainText; - if (DataPos == (DecompressedData.Length)) - break; + if (DataPos == (DecompressedData.Length)) + break; - int offset = (int)(((control2 & 0x3F) << 8) + (control3) + 1); - long numberToCopyFromOffset = (Control1 & 0x3F) + 4; - OffsetCopy(ref DecompressedData, offset, DataPos, numberToCopyFromOffset); - DataPos += (int)numberToCopyFromOffset; + int offset = (int)(((control2 & 0x3F) << 8) + (control3) + 1); + long numberToCopyFromOffset = (Control1 & 0x3F) + 4; + OffsetCopy(ref DecompressedData, offset, DataPos, numberToCopyFromOffset); + DataPos += (int)numberToCopyFromOffset; - if (DataPos == (DecompressedData.Length)) - break; - } - else if (Control1 >= 192 && Control1 <= 223) - { - // 0xC0 - 0xDF - long numberOfPlainText = (Control1 & 0x03); - long control2 = Data[Pos]; - Pos++; - long control3 = Data[Pos]; - Pos++; - long control4 = Data[Pos]; - Pos++; - ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); - DataPos += (int)numberOfPlainText; - Pos += (int)numberOfPlainText; + if (DataPos == (DecompressedData.Length)) + break; + } + else if (Control1 >= 192 && Control1 <= 223) + { + // 0xC0 - 0xDF + long numberOfPlainText = (Control1 & 0x03); + long control2 = Data[Pos]; + Pos++; + long control3 = Data[Pos]; + Pos++; + long control4 = Data[Pos]; + Pos++; + ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); + DataPos += (int)numberOfPlainText; + Pos += (int)numberOfPlainText; - if (DataPos == (DecompressedData.Length)) - break; + if (DataPos == (DecompressedData.Length)) + break; - int offset = (int)(((Control1 & 0x10) << 12) + (control2 << 8) + (control3) + 1); - long numberToCopyFromOffset = ((Control1 & 0x0C) << 6) + (control4) + 5; - OffsetCopy(ref DecompressedData, offset, DataPos, numberToCopyFromOffset); - DataPos += (int)numberToCopyFromOffset; + int offset = (int)(((Control1 & 0x10) << 12) + (control2 << 8) + (control3) + 1); + long numberToCopyFromOffset = ((Control1 & 0x0C) << 6) + (control4) + 5; + OffsetCopy(ref DecompressedData, offset, DataPos, numberToCopyFromOffset); + DataPos += (int)numberToCopyFromOffset; - if (DataPos == (DecompressedData.Length)) - break; - } - else if (Control1 >= 224 && Control1 <= 251) - { - // 0xE0 - 0xFB - long numberOfPlainText = ((Control1 & 0x1F) << 2) + 4; - ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); - DataPos += (int)numberOfPlainText; - Pos += (int)numberOfPlainText; + if (DataPos == (DecompressedData.Length)) + break; + } + else if (Control1 >= 224 && Control1 <= 251) + { + // 0xE0 - 0xFB + long numberOfPlainText = ((Control1 & 0x1F) << 2) + 4; + ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); + DataPos += (int)numberOfPlainText; + Pos += (int)numberOfPlainText; - if (DataPos == (DecompressedData.Length)) - break; - } - else - { - long numberOfPlainText = (Control1 & 0x03); - ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); + if (DataPos == (DecompressedData.Length)) + break; + } + else + { + long numberOfPlainText = (Control1 & 0x03); + ArrayCopy2(Data, Pos, ref DecompressedData, DataPos, numberOfPlainText); - DataPos += (int)numberOfPlainText; - Pos += (int)numberOfPlainText; + DataPos += (int)numberOfPlainText; + Pos += (int)numberOfPlainText; - if (DataPos == (DecompressedData.Length)) - break; - } - } + if (DataPos == (DecompressedData.Length)) + break; + } + } - return DecompressedData; - } + return DecompressedData; + } - //No data to decompress - return Data; - } + //No data to decompress + return Data; + } #region compression //some Compression Data @@ -221,181 +221,181 @@ namespace OpenTS2.Files.Formats.DBPF /* try {*/ - //return Comp(data, true); - #region Init Variables - //contains the latest offset for a combination of two characters - ArrayList[] cmpmap = new ArrayList[0x1000000]; + //return Comp(data, true); + #region Init Variables + //contains the latest offset for a combination of two characters + ArrayList[] cmpmap = new ArrayList[0x1000000]; - //will contain the compressed Data - byte[] cdata = new byte[data.Length]; + //will contain the compressed Data + byte[] cdata = new byte[data.Length]; - //init some vars - int writeindex = 0; - int lastreadindex = 0; - ArrayList indexlist = null; - int copyoffset = 0; - int copycount = 0; - writeindex = 0; - int index = -1; - lastreadindex = 0; - byte[] retdata; - bool end = false; - #endregion - try + //init some vars + int writeindex = 0; + int lastreadindex = 0; + ArrayList indexlist = null; + int copyoffset = 0; + int copycount = 0; + writeindex = 0; + int index = -1; + lastreadindex = 0; + byte[] retdata; + bool end = false; + #endregion + try + { + //begin main Compression Loop + while (index < data.Length - 3) { - //begin main Compression Loop - while (index < data.Length - 3) + #region get all Compression Candidates (list of offsets for all occurances of the current 3 bytes) + do { - #region get all Compression Candidates (list of offsets for all occurances of the current 3 bytes) - do + index++; + if (index >= data.Length - 2) { - index++; - if (index >= data.Length - 2) - { - end = true; - break; - } - int mapindex = data[index] | (data[index + 1] << 0x08) | (data[index + 2] << 0x10); - - indexlist = cmpmap[mapindex]; - if (indexlist == null) - { - indexlist = new ArrayList(); - cmpmap[mapindex] = indexlist; - } - indexlist.Add(index); - } while (index < lastreadindex); - if (end) break; - - #endregion - - #region find the longest repeating byte sequence in the index List (for offset copy) - int offsetcopycount = 0; - int loopcount = 1; - while ((loopcount < indexlist.Count) && (loopcount < compstrength)) - { - int foundindex = (int)indexlist[(indexlist.Count - 1) - loopcount]; - if ((index - foundindex) >= MAX_OFFSET) break; - - loopcount++; - copycount = 3; - while ((data.Length > index + copycount) && (data[index + copycount] == data[foundindex + copycount]) && (copycount < MAX_COPY_COUNT)) - copycount++; - - if (copycount > offsetcopycount) - { - int cof = index - foundindex; - offsetcopycount = copycount; - copyoffset = index - foundindex; - } + end = true; + break; } - #endregion + int mapindex = data[index] | (data[index + 1] << 0x08) | (data[index + 2] << 0x10); - #region Compression + indexlist = cmpmap[mapindex]; + if (indexlist == null) + { + indexlist = new ArrayList(); + cmpmap[mapindex] = indexlist; + } + indexlist.Add(index); + } while (index < lastreadindex); + if (end) break; + + #endregion + + #region find the longest repeating byte sequence in the index List (for offset copy) + int offsetcopycount = 0; + int loopcount = 1; + while ((loopcount < indexlist.Count) && (loopcount < compstrength)) + { + int foundindex = (int)indexlist[(indexlist.Count - 1) - loopcount]; + if ((index - foundindex) >= MAX_OFFSET) break; + + loopcount++; + copycount = 3; + while ((data.Length > index + copycount) && (data[index + copycount] == data[foundindex + copycount]) && (copycount < MAX_COPY_COUNT)) + copycount++; + + if (copycount > offsetcopycount) + { + int cof = index - foundindex; + offsetcopycount = copycount; + copyoffset = index - foundindex; + } + } + #endregion + + #region Compression + + //check if we can compress this + if (offsetcopycount < 3) offsetcopycount = 0; + else if ((offsetcopycount < 4) && (copyoffset > 0x400)) offsetcopycount = 0; + else if ((offsetcopycount < 5) && (copyoffset > 0x4000)) offsetcopycount = 0; - //check if we can compress this - if (offsetcopycount < 3) offsetcopycount = 0; - else if ((offsetcopycount < 4) && (copyoffset > 0x400)) offsetcopycount = 0; - else if ((offsetcopycount < 5) && (copyoffset > 0x4000)) offsetcopycount = 0; //this is offset-compressable? so do the compression if (offsetcopycount > 0) - { - //plaincopy - while ((index - lastreadindex) > 3) - { - copycount = (index - lastreadindex); - while (copycount > 0x71) copycount -= 0x71; - copycount = copycount & 0xfc; - int realcopycount = (copycount >> 2); - - cdata[writeindex++] = (byte)(0xdf + realcopycount); - for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; - } - - //offsetcopy - copycount = index - lastreadindex; - copyoffset--; - if ((offsetcopycount <= 0xa) && (copyoffset < 0x400)) - { - cdata[writeindex++] = (byte)((((copyoffset >> 3) & 0x60) | ((offsetcopycount - 3) << 2)) | copycount); - cdata[writeindex++] = (byte)(copyoffset & 0xff); - } - else if ((offsetcopycount <= 0x43) && (copyoffset < 0x4000)) - { - cdata[writeindex++] = (byte)(0x80 | (offsetcopycount - 4)); - cdata[writeindex++] = (byte)((copycount << 6) | (copyoffset >> 8)); - cdata[writeindex++] = (byte)(copyoffset & 0xff); - } - else if ((offsetcopycount <= MAX_COPY_COUNT) && (copyoffset < MAX_OFFSET)) - { - cdata[writeindex++] = (byte)(((0xc0 | ((copyoffset >> 0x0c) & 0x10)) + (((offsetcopycount - 5) >> 6) & 0x0c)) | copycount); - cdata[writeindex++] = (byte)((copyoffset >> 8) & 0xff); - cdata[writeindex++] = (byte)(copyoffset & 0xff); - cdata[writeindex++] = (byte)((offsetcopycount - 5) & 0xff); - } - else - { - copycount = 0; - offsetcopycount = 0; - } - - //do the offset copy - for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; - lastreadindex += offsetcopycount; - } - #endregion - } //while (main Loop) - - #region Add remaining Data - //add the End Record - index = data.Length; - lastreadindex = Math.Min(index, lastreadindex); - while ((index - lastreadindex) > 3) { - copycount = (index - lastreadindex); - while (copycount > 0x71) copycount -= 0x71; - copycount = copycount & 0xfc; - int realcopycount = (copycount >> 2); + //plaincopy + while ((index - lastreadindex) > 3) + { + copycount = (index - lastreadindex); + while (copycount > 0x71) copycount -= 0x71; + copycount = copycount & 0xfc; + int realcopycount = (copycount >> 2); - cdata[writeindex++] = (byte)(0xdf + realcopycount); + cdata[writeindex++] = (byte)(0xdf + realcopycount); + for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; + } + + //offsetcopy + copycount = index - lastreadindex; + copyoffset--; + if ((offsetcopycount <= 0xa) && (copyoffset < 0x400)) + { + cdata[writeindex++] = (byte)((((copyoffset >> 3) & 0x60) | ((offsetcopycount - 3) << 2)) | copycount); + cdata[writeindex++] = (byte)(copyoffset & 0xff); + } + else if ((offsetcopycount <= 0x43) && (copyoffset < 0x4000)) + { + cdata[writeindex++] = (byte)(0x80 | (offsetcopycount - 4)); + cdata[writeindex++] = (byte)((copycount << 6) | (copyoffset >> 8)); + cdata[writeindex++] = (byte)(copyoffset & 0xff); + } + else if ((offsetcopycount <= MAX_COPY_COUNT) && (copyoffset < MAX_OFFSET)) + { + cdata[writeindex++] = (byte)(((0xc0 | ((copyoffset >> 0x0c) & 0x10)) + (((offsetcopycount - 5) >> 6) & 0x0c)) | copycount); + cdata[writeindex++] = (byte)((copyoffset >> 8) & 0xff); + cdata[writeindex++] = (byte)(copyoffset & 0xff); + cdata[writeindex++] = (byte)((offsetcopycount - 5) & 0xff); + } + else + { + copycount = 0; + offsetcopycount = 0; + } + + //do the offset copy for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; + lastreadindex += offsetcopycount; } - - copycount = index - lastreadindex; - cdata[writeindex++] = (byte)(0xfc + copycount); - for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; #endregion + } //while (main Loop) - #region Trim Data & and add Header - //make a resulting Array of the apropriate size - retdata = new byte[writeindex + 9]; + #region Add remaining Data + //add the End Record + index = data.Length; + lastreadindex = Math.Min(index, lastreadindex); + while ((index - lastreadindex) > 3) + { + copycount = (index - lastreadindex); + while (copycount > 0x71) copycount -= 0x71; + copycount = copycount & 0xfc; + int realcopycount = (copycount >> 2); - byte[] sz = BitConverter.GetBytes((uint)(retdata.Length)); - for (int i = 0; i < 4; i++) retdata[i] = sz[i]; - //Compress signature - sz = BitConverter.GetBytes(0xFB10); - for (int i = 0; i < 2; i++) retdata[i + 4] = sz[i]; + cdata[writeindex++] = (byte)(0xdf + realcopycount); + for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; + } - sz = BitConverter.GetBytes((uint)data.Length); - for (int i = 0; i < 3; i++) retdata[i + 6] = sz[2 - i]; + copycount = index - lastreadindex; + cdata[writeindex++] = (byte)(0xfc + copycount); + for (int i = 0; i < copycount; i++) cdata[writeindex++] = data[lastreadindex++]; + #endregion - for (int i = 0; i < writeindex; i++) retdata[i + 9] = cdata[i]; + #region Trim Data & and add Header + //make a resulting Array of the apropriate size + retdata = new byte[writeindex + 9]; + + byte[] sz = BitConverter.GetBytes((uint)(retdata.Length)); + for (int i = 0; i < 4; i++) retdata[i] = sz[i]; + //Compress signature + sz = BitConverter.GetBytes(0xFB10); + for (int i = 0; i < 2; i++) retdata[i + 4] = sz[i]; + + sz = BitConverter.GetBytes((uint)data.Length); + for (int i = 0; i < 3; i++) retdata[i + 6] = sz[2 - i]; + + for (int i = 0; i < writeindex; i++) retdata[i + 9] = cdata[i]; #endregion return retdata; - } - finally - { - foreach (ArrayList a in cmpmap) - if (a != null) a.Clear(); + } + finally + { + foreach (ArrayList a in cmpmap) + if (a != null) a.Clear(); - cmpmap = null; - cdata = null; - retdata = null; - if (indexlist != null) indexlist.Clear(); - indexlist = null; - } - + cmpmap = null; + cdata = null; + retdata = null; + if (indexlist != null) indexlist.Clear(); + indexlist = null; + } /*} catch (Exception ex) @@ -406,4 +406,4 @@ namespace OpenTS2.Files.Formats.DBPF } #endregion } -} +} \ No newline at end of file