diff --git a/SabreTools.Serialization/UnshieldSharp/Reader.cs b/SabreTools.Serialization/UnshieldSharp/Reader.cs
deleted file mode 100644
index 4f1144af..00000000
--- a/SabreTools.Serialization/UnshieldSharp/Reader.cs
+++ /dev/null
@@ -1,249 +0,0 @@
-using System;
-using System.IO;
-using SabreTools.Models.InstallShieldCabinet;
-using Header = SabreTools.Serialization.Wrappers.InstallShieldCabinet;
-
-namespace UnshieldSharpInternal
-{
- internal class Reader : IDisposable
- {
- #region Private Instance Variables
-
- ///
- /// Cabinet file to read from
- ///
- private readonly Header _cabinet;
-
- ///
- /// Currently selected index
- ///
- private readonly uint _index;
-
- ///
- /// File descriptor defining the currently selected index
- ///
- private readonly FileDescriptor _fileDescriptor;
-
- ///
- /// Offset in the data where the file exists
- ///
- private ulong _dataOffset;
-
- ///
- /// 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
-
- #region Constructors
-
- private Reader(Header cabinet, uint index, FileDescriptor fileDescriptor)
- {
- _cabinet = cabinet;
- _index = index;
- _fileDescriptor = fileDescriptor;
- }
-
- #endregion
-
- ///
- /// Create a new from an existing cabinet, index, and file descriptor
- ///
- public static Reader? Create(Header cabinet, int index, FileDescriptor fileDescriptor)
- {
- var reader = new Reader(cabinet, (uint)index, fileDescriptor);
- 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.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
-
- ///
- /// 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
- Header.Deobfuscate(buffer, size, ref _obfuscationOffset);
-
- return true;
- }
-
- ///
- /// Open the next volume based on the current index
- ///
- private bool OpenNextVolume(out ushort nextVolume)
- {
- nextVolume = (ushort)(_volumeId + 1);
- return OpenVolume(nextVolume);
- }
-
- ///
- /// Open the volume at the inputted index
- ///
- private bool OpenVolume(ushort volume)
- {
- // Read the volume from the cabinet set
- var next = _cabinet.OpenVolume(volume, out var volumeStream);
- if (next?.VolumeHeader == null || volumeStream == null)
- {
- Console.Error.WriteLine($"Failed to open input cabinet file {volume}");
- return false;
- }
-
- // Assign the next items
- _volumeFile?.Close();
- _volumeFile = volumeStream;
- _volumeHeader = next.VolumeHeader;
-
- // Enable support for split archives for IS5
- if (_cabinet.MajorVersion == 5)
- {
- if (_index < (_cabinet.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 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 f3dac980..dad9ea4f 100644
--- a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
+++ b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
@@ -5,7 +5,6 @@ using SabreTools.Hashing;
using SabreTools.IO.Compression.zlib;
using SabreTools.Models.InstallShieldCabinet;
using SabreTools.Serialization.Interfaces;
-using UnshieldSharpInternal;
using static SabreTools.Models.InstallShieldCabinet.Constants;
namespace SabreTools.Serialization.Wrappers
@@ -940,5 +939,254 @@ namespace SabreTools.Serialization.Wrappers
private static int ROL8(int x, byte n) => (x << n) | (x >> (8 - n));
#endregion
+
+ #region Helper Classes
+
+ ///
+ /// Helper to read a single file from a cabinet set
+ ///
+ private class Reader : IDisposable
+ {
+ #region Private Instance Variables
+
+ ///
+ /// Cabinet file to read from
+ ///
+ private readonly InstallShieldCabinet _cabinet;
+
+ ///
+ /// Currently selected index
+ ///
+ private readonly uint _index;
+
+ ///
+ /// File descriptor defining the currently selected index
+ ///
+ private readonly FileDescriptor _fileDescriptor;
+
+ ///
+ /// Offset in the data where the file exists
+ ///
+ private ulong _dataOffset;
+
+ ///
+ /// 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
+
+ #region Constructors
+
+ private Reader(InstallShieldCabinet cabinet, uint index, FileDescriptor fileDescriptor)
+ {
+ _cabinet = cabinet;
+ _index = index;
+ _fileDescriptor = fileDescriptor;
+ }
+
+ #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, (uint)index, fileDescriptor);
+ 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.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
+
+ ///
+ /// 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
+ Deobfuscate(buffer, size, ref _obfuscationOffset);
+
+ return true;
+ }
+
+ ///
+ /// Open the next volume based on the current index
+ ///
+ private bool OpenNextVolume(out ushort nextVolume)
+ {
+ nextVolume = (ushort)(_volumeId + 1);
+ return OpenVolume(nextVolume);
+ }
+
+ ///
+ /// Open the volume at the inputted index
+ ///
+ private bool OpenVolume(ushort volume)
+ {
+ // Read the volume from the cabinet set
+ var next = _cabinet.OpenVolume(volume, out var volumeStream);
+ if (next?.VolumeHeader == null || volumeStream == null)
+ {
+ Console.Error.WriteLine($"Failed to open input cabinet file {volume}");
+ return false;
+ }
+
+ // Assign the next items
+ _volumeFile?.Close();
+ _volumeFile = volumeStream;
+ _volumeHeader = next.VolumeHeader;
+
+ // Enable support for split archives for IS5
+ if (_cabinet.MajorVersion == 5)
+ {
+ if (_index < (_cabinet.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 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
+ }
+
+ #endregion
}
}