diff --git a/ExtractionTool/ExtractionTool.csproj b/ExtractionTool/ExtractionTool.csproj
index fadaef33..b8203284 100644
--- a/ExtractionTool/ExtractionTool.csproj
+++ b/ExtractionTool/ExtractionTool.csproj
@@ -67,7 +67,6 @@
-
\ No newline at end of file
diff --git a/ExtractionTool/Program.cs b/ExtractionTool/Program.cs
index 0cebd591..46bcdfe2 100644
--- a/ExtractionTool/Program.cs
+++ b/ExtractionTool/Program.cs
@@ -286,7 +286,7 @@ namespace ExtractionTool
if (!File.Exists(file))
return false;
- var cabfile = UnshieldSharp.InstallShieldCabinet.Open(file);
+ var cabfile = UnshieldSharpInternal.InstallShieldCabinet.Open(file);
if (cabfile?.HeaderList == null)
return false;
diff --git a/SabreTools.Serialization/SabreTools.Serialization.csproj b/SabreTools.Serialization/SabreTools.Serialization.csproj
index 8c232075..772b15df 100644
--- a/SabreTools.Serialization/SabreTools.Serialization.csproj
+++ b/SabreTools.Serialization/SabreTools.Serialization.csproj
@@ -27,6 +27,7 @@
+
diff --git a/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs b/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs
new file mode 100644
index 00000000..9b5e6b9e
--- /dev/null
+++ b/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs
@@ -0,0 +1,274 @@
+using System;
+using System.IO;
+using SabreTools.Hashing;
+using SabreTools.IO.Compression.zlib;
+using SabreTools.Models.InstallShieldCabinet;
+using Header = SabreTools.Serialization.Wrappers.InstallShieldCabinet;
+
+namespace UnshieldSharpInternal
+{
+ // TODO: Figure out if individual parts of a split cab can be extracted separately
+ internal class InstallShieldCabinet
+ {
+ ///
+ /// Linked CAB headers
+ ///
+ public Header? HeaderList { get; private set; }
+
+ ///
+ /// Base filename path for related CAB files
+ ///
+ public string? FilenamePattern { get; private set; }
+
+ ///
+ /// Default buffer size
+ ///
+ private const int BUFFER_SIZE = 64 * 1024;
+
+ ///
+ /// Maximum size of the window in bits
+ ///
+ /// TODO: Remove when Serialization is updated
+ private const int MAX_WBITS = 15;
+
+ #region Open Cabinet
+
+ ///
+ /// Open a file as an InstallShield CAB
+ ///
+ public static InstallShieldCabinet? Open(string filename)
+ {
+ var cabinet = new InstallShieldCabinet();
+
+ cabinet.FilenamePattern = Header.CreateFilenamePattern(filename);
+ if (cabinet.FilenamePattern == null)
+ {
+ Console.Error.WriteLine("Failed to create filename pattern");
+ return null;
+ }
+
+ cabinet.HeaderList = Header.OpenSet(cabinet.FilenamePattern);
+ if (cabinet.HeaderList == null)
+ {
+ Console.Error.WriteLine("Failed to read header files");
+ return null;
+ }
+
+ return cabinet;
+ }
+
+ #endregion
+
+ #region File
+
+ ///
+ /// Save the file at the given index to the filename specified
+ ///
+ public bool FileSave(int index, string filename, bool useOld = false)
+ {
+ if (HeaderList == null)
+ {
+ Console.Error.WriteLine("Header list is not built");
+ return false;
+ }
+
+ // Get the file descriptor
+ if (!HeaderList.TryGetFileDescriptor(index, out var fileDescriptor) || fileDescriptor == null)
+ return false;
+
+ // If the file is split
+ if (fileDescriptor.LinkFlags == LinkFlags.LINK_PREV)
+ return FileSave((int)fileDescriptor.LinkPrevious, filename, useOld);
+
+ // Get the reader at the index
+ var reader = Reader.Create(this, index, fileDescriptor);
+ if (reader == null)
+ return false;
+
+ // Create the output file and hasher
+ FileStream output = File.OpenWrite(filename);
+ var md5 = new HashWrapper(HashType.MD5);
+
+ ulong bytesLeft = Header.GetReadableBytes(fileDescriptor);
+ byte[] inputBuffer;
+ byte[] outputBuffer = new byte[BUFFER_SIZE];
+ ulong totalWritten = 0;
+
+ // Read while there are bytes remaining
+ while (bytesLeft > 0)
+ {
+ ulong bytesToWrite = BUFFER_SIZE;
+ int result;
+
+ // Handle compressed files
+#if NET20 || NET35
+ if ((fileDescriptor.Flags & FileFlags.FILE_COMPRESSED) != 0)
+#else
+ if (fileDescriptor.Flags.HasFlag(FileFlags.FILE_COMPRESSED))
+#endif
+ {
+ // Attempt to read the length value
+ byte[] lengthArr = new byte[sizeof(ushort)];
+ if (!reader.Read(lengthArr, 0, lengthArr.Length))
+ {
+ Console.Error.WriteLine($"Failed to read {lengthArr.Length} bytes of file {index} ({HeaderList.GetFileName(index)}) from input cabinet file {fileDescriptor.Volume}");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Validate the number of bytes to read
+ ushort bytesToRead = BitConverter.ToUInt16(lengthArr, 0);
+ if (bytesToRead == 0)
+ {
+ Console.Error.WriteLine("bytesToRead can't be zero");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Attempt to read the specified number of bytes
+ inputBuffer = new byte[BUFFER_SIZE + 1];
+ if (!reader.Read(inputBuffer, 0, bytesToRead))
+ {
+ Console.Error.WriteLine($"Failed to read {lengthArr.Length} bytes of file {index} ({HeaderList.GetFileName(index)}) from input cabinet file {fileDescriptor.Volume}");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Add a null byte to make inflate happy
+ inputBuffer[bytesToRead] = 0;
+ ulong readBytes = (ulong)(bytesToRead + 1);
+
+ // Uncompress into a buffer
+ if (useOld)
+ result = Header.UncompressOld(outputBuffer, ref bytesToWrite, inputBuffer, ref readBytes);
+ else
+ result = Header.Uncompress(outputBuffer, ref bytesToWrite, inputBuffer, ref readBytes);
+
+ // If we didn't get a positive result that's not a data error (false positives)
+ if (result != zlibConst.Z_OK && result != zlibConst.Z_DATA_ERROR)
+ {
+ Console.Error.WriteLine($"Decompression failed with code {result.ToZlibConstName()}. bytes_to_read={bytesToRead}, volume={fileDescriptor.Volume}, read_bytes={readBytes}");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Set remaining bytes
+ bytesLeft -= 2;
+ bytesLeft -= bytesToRead;
+ }
+
+ // Handle uncompressed files
+ else
+ {
+ bytesToWrite = Math.Min(bytesLeft, BUFFER_SIZE);
+ if (!reader.Read(outputBuffer, 0, (int)bytesToWrite))
+ {
+ Console.Error.WriteLine($"Failed to write {bytesToWrite} bytes from input cabinet file {fileDescriptor.Volume}");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Set remaining bytes
+ bytesLeft -= (uint)bytesToWrite;
+ }
+
+ // Hash and write the next block
+ md5.Process(outputBuffer, 0, (int)bytesToWrite);
+ output?.Write(outputBuffer, 0, (int)bytesToWrite);
+ totalWritten += bytesToWrite;
+ }
+
+ // Validate the number of bytes written
+ if (fileDescriptor.ExpandedSize != totalWritten)
+ {
+ Console.Error.WriteLine($"Expanded size expected to be {fileDescriptor.ExpandedSize}, but was {totalWritten}");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Finalize output values
+ md5.Terminate();
+ reader?.Dispose();
+ output?.Close();
+
+ // Failing the file has been disabled because for a subset of CABs the values don't seem to match
+ // TODO: Investigate what is causing this to fail and what data needs to be hashed
+
+ // // Validate the data written, if required
+ // if (HeaderList!.MajorVersion >= 6)
+ // {
+ // string? md5result = md5.CurrentHashString;
+ // if (md5result == null || md5result != BitConverter.ToString(fileDescriptor.MD5!))
+ // {
+ // Console.Error.WriteLine($"MD5 checksum failure for file {index} ({HeaderList.GetFileName(index)})");
+ // return false;
+ // }
+ // }
+
+ return true;
+ }
+
+ ///
+ /// Save the file at the given index to the filename specified as raw
+ ///
+ public bool FileSaveRaw(int index, string filename)
+ {
+ if (HeaderList == null)
+ {
+ Console.Error.WriteLine("Header list is not built");
+ return false;
+ }
+
+ // Get the file descriptor
+ if (!HeaderList.TryGetFileDescriptor(index, out var fileDescriptor) || fileDescriptor == null)
+ return false;
+
+ // If the file is split
+ if (fileDescriptor.LinkFlags == LinkFlags.LINK_PREV)
+ return FileSaveRaw((int)fileDescriptor.LinkPrevious, filename);
+
+ // Get the reader at the index
+ var reader = Reader.Create(this, index, fileDescriptor);
+ if (reader == null)
+ return false;
+
+ // Create the output file
+ FileStream output = File.OpenWrite(filename);
+
+ ulong bytesLeft = Header.GetReadableBytes(fileDescriptor);
+ byte[] outputBuffer = new byte[BUFFER_SIZE];
+
+ // Read while there are bytes remaining
+ while (bytesLeft > 0)
+ {
+ ulong bytesToWrite = Math.Min(bytesLeft, BUFFER_SIZE);
+ if (!reader.Read(outputBuffer, 0, (int)bytesToWrite))
+ {
+ Console.Error.WriteLine($"Failed to read {bytesToWrite} bytes from input cabinet file {fileDescriptor.Volume}");
+ reader.Dispose();
+ output?.Close();
+ return false;
+ }
+
+ // Set remaining bytes
+ bytesLeft -= (uint)bytesToWrite;
+
+ // Write the next block
+ output.Write(outputBuffer, 0, (int)bytesToWrite);
+ }
+
+ // Finalize output values
+ reader.Dispose();
+ output?.Close();
+ return true;
+ }
+
+ #endregion
+ }
+}
diff --git a/SabreTools.Serialization/UnshieldSharp/Reader.cs b/SabreTools.Serialization/UnshieldSharp/Reader.cs
new file mode 100644
index 00000000..16f13423
--- /dev/null
+++ b/SabreTools.Serialization/UnshieldSharp/Reader.cs
@@ -0,0 +1,254 @@
+using System;
+using System.IO;
+using SabreTools.IO.Extensions;
+using SabreTools.Models.InstallShieldCabinet;
+using static SabreTools.Models.InstallShieldCabinet.Constants;
+
+namespace UnshieldSharpInternal
+{
+ internal class Reader : IDisposable
+ {
+ #region Private Instance Variables
+
+ ///
+ /// Cabinet file to read from
+ ///
+ private InstallShieldCabinet? _cabinet;
+
+ ///
+ /// Currently selected index
+ ///
+ private uint _index;
+
+ ///
+ /// File descriptor defining the currently selected index
+ ///
+ private FileDescriptor? _fileDescriptor;
+
+ ///
+ /// Number of bytes left in the current volume
+ ///
+ private ulong _volumeBytesLeft;
+
+ ///
+ /// Handle to the current volume stream
+ ///
+ private Stream? _volumeFile;
+
+ ///
+ /// Current volume header
+ ///
+ private VolumeHeader? _volumeHeader;
+
+ ///
+ /// Current volume ID
+ ///
+ private ushort _volumeId;
+
+ ///
+ /// Offset for obfuscation seed
+ ///
+ private uint _obfuscationOffset;
+
+ #endregion
+
+ ///
+ /// Create a new from an existing cabinet, index, and file descriptor
+ ///
+ public static Reader? Create(InstallShieldCabinet cabinet, int index, FileDescriptor fileDescriptor)
+ {
+ var reader = new Reader
+ {
+ _cabinet = cabinet,
+ _index = (uint)index,
+ _fileDescriptor = fileDescriptor,
+ };
+
+ // If the cabinet header list is invalid
+ if (reader._cabinet.HeaderList == null)
+ {
+ Console.Error.WriteLine($"Header list is invalid");
+ return null;
+ }
+
+ for (; ; )
+ {
+ // If the volume is invalid
+ if (!reader.OpenVolume(fileDescriptor.Volume))
+ {
+ Console.Error.WriteLine($"Failed to open volume {fileDescriptor.Volume}");
+ return null;
+ }
+ else if (reader._volumeFile == null || reader._volumeHeader == null)
+ {
+ Console.Error.WriteLine($"Volume {fileDescriptor.Volume} is invalid");
+ return null;
+ }
+
+ // Start with the correct volume for IS5 cabinets
+ if (reader._cabinet.HeaderList.MajorVersion <= 5 && index > (int)reader._volumeHeader.LastFileIndex)
+ {
+ // Normalize the volume ID for odd cases
+ if (fileDescriptor.Volume == ushort.MinValue || fileDescriptor.Volume == ushort.MaxValue)
+ fileDescriptor.Volume = 1;
+
+ fileDescriptor.Volume++;
+ continue;
+ }
+
+ break;
+ }
+
+ return reader;
+ }
+
+ ///
+ /// Dispose of the current object
+ ///
+ public void Dispose()
+ {
+ _volumeFile?.Close();
+ }
+
+ #region Reading
+
+ ///
+ /// Open the next volume based on the current index
+ ///
+ public bool OpenNextVolume(out ushort nextVolume)
+ {
+ nextVolume = (ushort)(_volumeId + 1);
+ return OpenVolume(nextVolume);
+ }
+
+ ///
+ /// Read a certain number of bytes from the current volume
+ ///
+ public bool Read(byte[] buffer, int start, long size)
+ {
+ long bytesLeft = size;
+ while (bytesLeft > 0)
+ {
+ // Open the next volume, if necessary
+ if (_volumeBytesLeft == 0)
+ {
+ if (!OpenNextVolume(out _))
+ return false;
+ }
+
+ // Get the number of bytes to read from this volume
+ int bytesToRead = (int)Math.Min(bytesLeft, (long)_volumeBytesLeft);
+ if (bytesToRead == 0)
+ break;
+
+ // Read as much as possible from this volume
+ if (bytesToRead != _volumeFile!.Read(buffer, start, bytesToRead))
+ return false;
+
+ // Set the number of bytes left
+ bytesLeft -= bytesToRead;
+ _volumeBytesLeft -= (uint)bytesToRead;
+ }
+
+#if NET20 || NET35
+ if ((_fileDescriptor!.Flags & FileFlags.FILE_OBFUSCATED) != 0)
+#else
+ if (_fileDescriptor!.Flags.HasFlag(FileFlags.FILE_OBFUSCATED))
+#endif
+ SabreTools.Serialization.Wrappers.InstallShieldCabinet.Deobfuscate(buffer, size, ref _obfuscationOffset);
+
+ return true;
+ }
+
+ ///
+ /// Open the volume at the inputted index
+ ///
+ private bool OpenVolume(ushort volume)
+ {
+ // Normalize the volume ID for odd cases
+ if (volume == ushort.MinValue || volume == ushort.MaxValue)
+ volume = 1;
+
+ _volumeFile?.Close();
+ _volumeFile = SabreTools.Serialization.Wrappers.InstallShieldCabinet.OpenFileForReading(_cabinet!.FilenamePattern, volume, CABINET_SUFFIX);
+ if (_volumeFile == null)
+ {
+ Console.Error.WriteLine($"Failed to open input cabinet file {volume}");
+ return false;
+ }
+
+ var commonHeader = _volumeFile.ReadType();
+ if (commonHeader == default)
+ return false;
+
+ _volumeHeader = SabreTools.Serialization.Deserializers.InstallShieldCabinet.ParseVolumeHeader(_volumeFile, _cabinet.HeaderList!.MajorVersion);
+ if (_volumeHeader == null)
+ return false;
+
+ // Enable support for split archives for IS5
+ if (_cabinet.HeaderList.MajorVersion == 5)
+ {
+ if (_index < (_cabinet.HeaderList.FileCount - 1)
+ && _index == _volumeHeader.LastFileIndex
+ && _volumeHeader.LastFileSizeCompressed != _fileDescriptor!.CompressedSize)
+ {
+ _fileDescriptor.Flags |= FileFlags.FILE_SPLIT;
+ }
+ else if (_index > 0
+ && _index == _volumeHeader.FirstFileIndex
+ && _volumeHeader.FirstFileSizeCompressed != _fileDescriptor!.CompressedSize)
+ {
+ _fileDescriptor.Flags |= FileFlags.FILE_SPLIT;
+ }
+ }
+
+ ulong dataOffset, volumeBytesLeftCompressed, volumeBytesLeftExpanded;
+#if NET20 || NET35
+ if ((_fileDescriptor!.Flags & FileFlags.FILE_SPLIT) != 0)
+#else
+ if (_fileDescriptor!.Flags.HasFlag(FileFlags.FILE_SPLIT))
+#endif
+ {
+ if (_index == _volumeHeader.LastFileIndex && _volumeHeader.LastFileOffset != 0x7FFFFFFF)
+ {
+ // can be first file too
+ dataOffset = _volumeHeader.LastFileOffset;
+ volumeBytesLeftExpanded = _volumeHeader.LastFileSizeExpanded;
+ volumeBytesLeftCompressed = _volumeHeader.LastFileSizeCompressed;
+ }
+ else if (_index == _volumeHeader.FirstFileIndex)
+ {
+ dataOffset = _volumeHeader.FirstFileOffset;
+ volumeBytesLeftExpanded = _volumeHeader.FirstFileSizeExpanded;
+ volumeBytesLeftCompressed = _volumeHeader.FirstFileSizeCompressed;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ else
+ {
+ dataOffset = _fileDescriptor.DataOffset;
+ volumeBytesLeftExpanded = _fileDescriptor.ExpandedSize;
+ volumeBytesLeftCompressed = _fileDescriptor.CompressedSize;
+ }
+
+#if NET20 || NET35
+ if ((_fileDescriptor.Flags & FileFlags.FILE_COMPRESSED) != 0)
+#else
+ if (_fileDescriptor.Flags.HasFlag(FileFlags.FILE_COMPRESSED))
+#endif
+ _volumeBytesLeft = volumeBytesLeftCompressed;
+ else
+ _volumeBytesLeft = volumeBytesLeftExpanded;
+
+ _volumeFile.Seek((long)dataOffset, SeekOrigin.Begin);
+ _volumeId = volume;
+
+ return true;
+ }
+
+ #endregion
+ }
+}
diff --git a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
index 42e4d674..089df050 100644
--- a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
+++ b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
@@ -277,7 +277,7 @@ namespace SabreTools.Serialization.Wrappers
/// Cabinet part index to be opened
/// Cabinet files suffix (e.g. `.cab`)
/// A Stream representing the cabinet part, null on error
- private static Stream? OpenFileForReading(string? pattern, int index, string suffix)
+ public static Stream? OpenFileForReading(string? pattern, int index, string suffix)
{
// An invalid pattern means no cabinet files
if (string.IsNullOrEmpty(pattern))
@@ -351,6 +351,84 @@ namespace SabreTools.Serialization.Wrappers
#endregion
+ #region Extraction
+
+ ///
+ /// Uncompress a source byte array to a destination
+ ///
+ public unsafe static int Uncompress(byte[] dest, ref ulong destLen, byte[] source, ref ulong sourceLen)
+ {
+ fixed (byte* sourcePtr = source)
+ fixed (byte* destPtr = dest)
+ {
+ var stream = new ZLib.z_stream_s
+ {
+ next_in = sourcePtr,
+ avail_in = (uint)sourceLen,
+ next_out = destPtr,
+ avail_out = (uint)destLen,
+ };
+
+ // make second parameter negative to disable checksum verification
+ int err = ZLib.inflateInit2_(stream, -MAX_WBITS, ZLib.zlibVersion(), source.Length);
+ if (err != zlibConst.Z_OK)
+ return err;
+
+ err = ZLib.inflate(stream, 1);
+ if (err != zlibConst.Z_STREAM_END)
+ {
+ ZLib.inflateEnd(stream);
+ return err;
+ }
+
+ destLen = stream.total_out;
+ sourceLen = stream.total_in;
+ return ZLib.inflateEnd(stream);
+ }
+ }
+
+ ///
+ /// Uncompress a source byte array to a destination (old version)
+ ///
+ public unsafe static int UncompressOld(byte[] dest, ref ulong destLen, byte[] source, ref ulong sourceLen)
+ {
+ fixed (byte* sourcePtr = source)
+ fixed (byte* destPtr = dest)
+ {
+ var stream = new ZLib.z_stream_s
+ {
+ next_in = sourcePtr,
+ avail_in = (uint)sourceLen,
+ next_out = destPtr,
+ avail_out = (uint)destLen,
+ };
+
+ destLen = 0;
+ sourceLen = 0;
+
+ // make second parameter negative to disable checksum verification
+ int err = ZLib.inflateInit2_(stream, -MAX_WBITS, ZLib.zlibVersion(), source.Length);
+ if (err != zlibConst.Z_OK)
+ return err;
+
+ while (stream.avail_in > 1)
+ {
+ err = ZLib.inflate(stream, 1);
+ if (err != zlibConst.Z_OK)
+ {
+ ZLib.inflateEnd(stream);
+ return err;
+ }
+ }
+
+ destLen = stream.total_out;
+ sourceLen = stream.total_in;
+ return ZLib.inflateEnd(stream);
+ }
+ }
+
+ #endregion
+
#region File
///
@@ -519,90 +597,12 @@ namespace SabreTools.Serialization.Wrappers
#endregion
- #region Extraction
-
- ///
- /// Uncompress a source byte array to a destination
- ///
- public unsafe static int Uncompress(byte[] dest, ref ulong destLen, byte[] source, ref ulong sourceLen)
- {
- fixed (byte* sourcePtr = source)
- fixed (byte* destPtr = dest)
- {
- var stream = new ZLib.z_stream_s
- {
- next_in = sourcePtr,
- avail_in = (uint)sourceLen,
- next_out = destPtr,
- avail_out = (uint)destLen,
- };
-
- // make second parameter negative to disable checksum verification
- int err = ZLib.inflateInit2_(stream, -MAX_WBITS, ZLib.zlibVersion(), source.Length);
- if (err != zlibConst.Z_OK)
- return err;
-
- err = ZLib.inflate(stream, 1);
- if (err != zlibConst.Z_STREAM_END)
- {
- ZLib.inflateEnd(stream);
- return err;
- }
-
- destLen = stream.total_out;
- sourceLen = stream.total_in;
- return ZLib.inflateEnd(stream);
- }
- }
-
- ///
- /// Uncompress a source byte array to a destination (old version)
- ///
- public unsafe static int UncompressOld(byte[] dest, ref ulong destLen, byte[] source, ref ulong sourceLen)
- {
- fixed (byte* sourcePtr = source)
- fixed (byte* destPtr = dest)
- {
- var stream = new ZLib.z_stream_s
- {
- next_in = sourcePtr,
- avail_in = (uint)sourceLen,
- next_out = destPtr,
- avail_out = (uint)destLen,
- };
-
- destLen = 0;
- sourceLen = 0;
-
- // make second parameter negative to disable checksum verification
- int err = ZLib.inflateInit2_(stream, -MAX_WBITS, ZLib.zlibVersion(), source.Length);
- if (err != zlibConst.Z_OK)
- return err;
-
- while (stream.avail_in > 1)
- {
- err = ZLib.inflate(stream, 1);
- if (err != zlibConst.Z_OK)
- {
- ZLib.inflateEnd(stream);
- return err;
- }
- }
-
- destLen = stream.total_out;
- sourceLen = stream.total_in;
- return ZLib.inflateEnd(stream);
- }
- }
-
- #endregion
-
#region Obfuscation
///
/// Deobfuscate a buffer
///
- private void Deobfuscate(byte[] buffer, long size, ref uint offset)
+ public static void Deobfuscate(byte[] buffer, long size, ref uint offset)
{
offset = Deobfuscate(buffer, size, offset);
}
@@ -611,7 +611,7 @@ namespace SabreTools.Serialization.Wrappers
/// Deobfuscate a buffer with a seed value
///
/// Seed is 0 at file start
- private static uint Deobfuscate(byte[] buffer, long size, uint seed)
+ public static uint Deobfuscate(byte[] buffer, long size, uint seed)
{
for (int i = 0; size > 0; size--, i++, seed++)
{
@@ -624,7 +624,7 @@ namespace SabreTools.Serialization.Wrappers
///
/// Obfuscate a buffer
///
- private void Obfuscate(byte[] buffer, long size, ref uint offset)
+ public static void Obfuscate(byte[] buffer, long size, ref uint offset)
{
offset = Obfuscate(buffer, size, offset);
}
@@ -633,7 +633,7 @@ namespace SabreTools.Serialization.Wrappers
/// Obfuscate a buffer with a seed value
///
/// Seed is 0 at file start
- private static uint Obfuscate(byte[] buffer, long size, uint seed)
+ public static uint Obfuscate(byte[] buffer, long size, uint seed)
{
for (int i = 0; size > 0; size--, i++, seed++)
{