diff --git a/BizHawk.Client.Common/BinarySaveStates.cs b/BizHawk.Client.Common/BinarySaveStates.cs
index 3d095e4c17..b72284579e 100644
--- a/BizHawk.Client.Common/BinarySaveStates.cs
+++ b/BizHawk.Client.Common/BinarySaveStates.cs
@@ -252,14 +252,12 @@ namespace BizHawk.Client.Common
sw.Flush();
}
- ///
- ///
- ///
- /// not closed when finished!
- public BinaryStateSaver(Stream s, bool stateVersionTag = true) // stateVersionTag is a hack for reusing this for movie code
+
+ public BinaryStateSaver(string path, bool stateVersionTag = true) // stateVersionTag is a hack for reusing this for movie code
{
- _zip = new IonicZipWriter(s, Global.Config.SaveStateCompressionLevelNormal);
- //_zip = new SharpZipWriter(s, Global.Config.SaveStateCompressionLevelNormal);
+ _zip = new IonicZipWriter(path, Global.Config.SaveStateCompressionLevelNormal);
+ //_zip = new SharpZipWriter(path, Global.Config.SaveStateCompressionLevelNormal);
+ //_zip = new SevenZipWriter(path, Global.Config.SaveStateCompressionLevelNormal);
if (stateVersionTag)
{
diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj
index 85265a57d7..605bd10acf 100644
--- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj
+++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj
@@ -190,6 +190,7 @@
+
diff --git a/BizHawk.Client.Common/IonicZipWriter.cs b/BizHawk.Client.Common/IonicZipWriter.cs
index 0450656134..532825829b 100644
--- a/BizHawk.Client.Common/IonicZipWriter.cs
+++ b/BizHawk.Client.Common/IonicZipWriter.cs
@@ -13,10 +13,10 @@ namespace BizHawk.Client.Common
private ZipOutputStream z;
private int level;
- public IonicZipWriter(Stream s, int compressionlevel)
+ public IonicZipWriter(string path, int compressionlevel)
{
level = compressionlevel;
- z = new ZipOutputStream(s, true)
+ z = new ZipOutputStream(path)
{
EnableZip64 = Zip64Option.Never,
CompressionLevel = (Ionic.Zlib.CompressionLevel)level
diff --git a/BizHawk.Client.Common/SavestateManager.cs b/BizHawk.Client.Common/SavestateManager.cs
index 1ec6be7034..945141c890 100644
--- a/BizHawk.Client.Common/SavestateManager.cs
+++ b/BizHawk.Client.Common/SavestateManager.cs
@@ -13,8 +13,7 @@ namespace BizHawk.Client.Common
{
// the old method of text savestate save is now gone.
// a text savestate is just like a binary savestate, but with a different core lump
- using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
- using (var bs = new BinaryStateSaver(fs))
+ using (var bs = new BinaryStateSaver(filename))
{
if (Global.Config.SaveStateType == Config.SaveStateTypeE.Text ||
(Global.Config.SaveStateType == Config.SaveStateTypeE.Default && !Global.Emulator.BinarySaveStatesPreferred))
diff --git a/BizHawk.Client.Common/SevenZipWriter.cs b/BizHawk.Client.Common/SevenZipWriter.cs
new file mode 100644
index 0000000000..f15d1f9425
--- /dev/null
+++ b/BizHawk.Client.Common/SevenZipWriter.cs
@@ -0,0 +1,275 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace BizHawk.Client.Common
+{
+ public class SevenZipWriter : IZipWriter
+ {
+ private class RangBuffer
+ {
+ const int LEN = 4096;
+ const int MASK = 4095;
+ byte[] buff = new byte[LEN];
+
+ int wpos = 0;
+ int rpos = 0;
+
+ bool writeclosed;
+ bool readclosed;
+
+ object sharedlock = new object();
+
+ public Stream W { get; private set; }
+ public Stream R { get; private set; }
+
+ public RangBuffer()
+ {
+ W = new WStream(this);
+ R = new RStream(this);
+ }
+
+ public int Read(byte[] buffer, int offset, int count)
+ {
+ int ret = 0;
+ while (count > 0)
+ {
+ lock (sharedlock)
+ {
+ int start = rpos;
+ int end = wpos;
+ if (end < start) // wrap
+ end = LEN;
+ if (end - start > count)
+ end = start + count;
+
+ int c = end - start;
+ if (c > 0)
+ {
+ Buffer.BlockCopy(buff, start, buffer, offset, c);
+ count -= c;
+ ret += c;
+ offset += c;
+ rpos = end & MASK;
+ }
+ else if (writeclosed)
+ {
+ break;
+ }
+ else
+ {
+ // todo: don't spin here
+ }
+ }
+ }
+ return ret;
+ }
+
+ public void CloseRead()
+ {
+ lock (sharedlock)
+ readclosed = true;
+ }
+
+ public int Write(byte[] buffer, int offset, int count)
+ {
+ int ret = 0;
+ while (count > 0)
+ {
+ lock (sharedlock)
+ {
+ int start = wpos;
+ int end = (rpos - 1) & MASK;
+ if (end < start) // wrap
+ end = LEN;
+ if (end - start > count)
+ end = start + count;
+
+ int c = end - start;
+ if (c > 0)
+ {
+ Buffer.BlockCopy(buffer, offset, buff, start, c);
+ count -= c;
+ ret += c;
+ offset += c;
+ wpos = end & MASK;
+ }
+ else if (readclosed)
+ {
+ break;
+ }
+ else
+ {
+ // todo: don't spin here
+ }
+ }
+ }
+ return ret;
+ }
+
+ public void CloseWrite()
+ {
+ lock (sharedlock)
+ writeclosed = true;
+ }
+
+ private class WStream : Stream
+ {
+ public override bool CanRead { get { return false; } }
+ public override bool CanSeek { get { return false; } }
+ public override bool CanWrite { get { return true; } }
+ public override void Flush() { }
+ public override long Length { get { throw new NotSupportedException(); } }
+ public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+ public override void SetLength(long value) { throw new NotSupportedException(); }
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ private RangBuffer _r;
+ private long _total; // bytes written so far
+ public WStream(RangBuffer r)
+ {
+ this._r = r;
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ int cnt = _r.Write(buffer, offset, count);
+ _total += cnt;
+ if (cnt < count)
+ throw new IOException("broken pipe");
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _r != null)
+ {
+ _r.CloseWrite();
+ _r = null;
+ }
+ base.Dispose(disposing);
+ }
+ }
+ private class RStream : Stream
+ {
+ public override bool CanRead { get { return true; } }
+ public override bool CanSeek { get { return false; } }
+ public override bool CanWrite { get { return false; } }
+ public override void Flush() { }
+ public override long Length { get { return 1; } } // { get { throw new NotSupportedException(); } }
+ public override long Seek(long offset, SeekOrigin origin) { return 0; } // { throw new NotSupportedException(); }
+ public override void SetLength(long value) { throw new NotSupportedException(); }
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ private RangBuffer _r;
+ private long _total; // bytes read so far
+ public RStream(RangBuffer r)
+ {
+ this._r = r;
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ int cnt = _r.Read(buffer, offset, count);
+ _total += cnt;
+ return cnt;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _r != null)
+ {
+ _r.CloseRead();
+ _r = null;
+ }
+ base.Dispose(disposing);
+ }
+ }
+ }
+
+ SevenZip.SevenZipCompressor svc;
+
+ bool first = true;
+ string path;
+ int compressionlevel;
+
+ public SevenZipWriter(string path, int compressionlevel)
+ {
+ this.path = path;
+ this.compressionlevel = compressionlevel;
+
+ svc = new SevenZip.SevenZipCompressor();
+ svc.ArchiveFormat = SevenZip.OutArchiveFormat.Zip;
+
+ switch (compressionlevel)
+ {
+ default:
+ case 0: svc.CompressionLevel = SevenZip.CompressionLevel.None; break;
+ case 1:
+ case 2: svc.CompressionLevel = SevenZip.CompressionLevel.Fast; break;
+ case 3:
+ case 4: svc.CompressionLevel = SevenZip.CompressionLevel.Low; break;
+ case 5:
+ case 6: svc.CompressionLevel = SevenZip.CompressionLevel.Normal; break;
+ case 7:
+ case 8: svc.CompressionLevel = SevenZip.CompressionLevel.High; break;
+ case 9: svc.CompressionLevel = SevenZip.CompressionLevel.Ultra; break;
+ }
+ }
+
+ public void WriteItem(string name, Action callback)
+ {
+ var dict = new Dictionary();
+ var r = new RangBuffer();
+ dict[name] = r.R;
+ if (first)
+ {
+ first = false;
+ svc.CompressionMode = SevenZip.CompressionMode.Create;
+ }
+ else
+ {
+ svc.CompressionMode = SevenZip.CompressionMode.Append;
+ }
+
+ var task = Task.Factory.StartNew(() =>
+ {
+ svc.CompressStreamDictionary(dict, path);
+ });
+ try
+ {
+ callback(r.W);
+ }
+ finally
+ {
+ r.W.Dispose();
+ }
+ task.Wait();
+ }
+
+ public void Dispose()
+ {
+ // nothing to do
+ }
+ }
+}
diff --git a/BizHawk.Client.Common/SharpZipWriter.cs b/BizHawk.Client.Common/SharpZipWriter.cs
index 5277cd4ffc..1845c24559 100644
--- a/BizHawk.Client.Common/SharpZipWriter.cs
+++ b/BizHawk.Client.Common/SharpZipWriter.cs
@@ -13,12 +13,12 @@ namespace BizHawk.Client.Common
private ZipOutputStream z;
private int level;
- public SharpZipWriter(Stream s, int compressionlevel)
+ public SharpZipWriter(string path, int compressionlevel)
{
level = compressionlevel;
- z = new ZipOutputStream(s)
+ z = new ZipOutputStream(new FileStream(path, FileMode.Create, FileAccess.Write))
{
- IsStreamOwner = false,
+ IsStreamOwner = true,
UseZip64 = UseZip64.Off
};
z.SetLevel(level);
diff --git a/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs b/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs
index eaf136748b..1d2b58050b 100644
--- a/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs
+++ b/BizHawk.Client.Common/movie/bk2/Bk2Movie.IO.cs
@@ -147,8 +147,7 @@ namespace BizHawk.Client.Common
Directory.CreateDirectory(file.Directory.ToString());
}
- using (var fs = new FileStream(fn, FileMode.Create, FileAccess.Write))
- using (var bs = new BinaryStateSaver(fs, false))
+ using (var bs = new BinaryStateSaver(fn, false))
{
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
diff --git a/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs b/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs
index 3f4ec30565..dc966cfc3c 100644
--- a/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs
+++ b/BizHawk.Client.Common/movie/tasproj/TasMovie.IO.cs
@@ -18,8 +18,7 @@ namespace BizHawk.Client.Common
Directory.CreateDirectory(file.Directory.ToString());
}
- using (var fs = new FileStream(fn, FileMode.Create, FileAccess.Write))
- using (var bs = new BinaryStateSaver(fs, false))
+ using (var bs = new BinaryStateSaver(fn, false))
{
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
diff --git a/BizHawk.Emulation.DiscSystem/Blobs/Blob_WaveFile.cs b/BizHawk.Emulation.DiscSystem/Blobs/Blob_WaveFile.cs
index 3a8f88fb99..8f99575cf6 100644
--- a/BizHawk.Emulation.DiscSystem/Blobs/Blob_WaveFile.cs
+++ b/BizHawk.Emulation.DiscSystem/Blobs/Blob_WaveFile.cs
@@ -92,12 +92,12 @@ namespace BizHawk.Emulation.DiscSystem
long mDataLength;
public long Length { get { return mDataLength; } }
- public void Dispose()
+ public void Dispose()
{
- if(RiffSource != null)
+ if (RiffSource != null)
RiffSource.Dispose();
RiffSource = null;
}
}
}
-}
\ No newline at end of file
+}