code to use 7zip (unmanaged) to write archives, not active for the moment, still stuff to do
This commit is contained in:
parent
9430b9f206
commit
4ee816e8bc
|
@ -252,14 +252,12 @@ namespace BizHawk.Client.Common
|
||||||
sw.Flush();
|
sw.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
public BinaryStateSaver(string path, bool stateVersionTag = true) // stateVersionTag is a hack for reusing this for movie code
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">not closed when finished!</param>
|
|
||||||
public BinaryStateSaver(Stream s, bool stateVersionTag = true) // stateVersionTag is a hack for reusing this for movie code
|
|
||||||
{
|
{
|
||||||
_zip = new IonicZipWriter(s, Global.Config.SaveStateCompressionLevelNormal);
|
_zip = new IonicZipWriter(path, Global.Config.SaveStateCompressionLevelNormal);
|
||||||
//_zip = new SharpZipWriter(s, Global.Config.SaveStateCompressionLevelNormal);
|
//_zip = new SharpZipWriter(path, Global.Config.SaveStateCompressionLevelNormal);
|
||||||
|
//_zip = new SevenZipWriter(path, Global.Config.SaveStateCompressionLevelNormal);
|
||||||
|
|
||||||
if (stateVersionTag)
|
if (stateVersionTag)
|
||||||
{
|
{
|
||||||
|
|
|
@ -190,6 +190,7 @@
|
||||||
<Compile Include="SaveSlotManager.cs" />
|
<Compile Include="SaveSlotManager.cs" />
|
||||||
<Compile Include="SavestateManager.cs" />
|
<Compile Include="SavestateManager.cs" />
|
||||||
<Compile Include="SevenZipSharpArchiveHandler.cs" />
|
<Compile Include="SevenZipSharpArchiveHandler.cs" />
|
||||||
|
<Compile Include="SevenZipWriter.cs" />
|
||||||
<Compile Include="SharpZipWriter.cs" />
|
<Compile Include="SharpZipWriter.cs" />
|
||||||
<Compile Include="SystemInfo.cs" />
|
<Compile Include="SystemInfo.cs" />
|
||||||
<Compile Include="tools\Cheat.cs" />
|
<Compile Include="tools\Cheat.cs" />
|
||||||
|
|
|
@ -13,10 +13,10 @@ namespace BizHawk.Client.Common
|
||||||
private ZipOutputStream z;
|
private ZipOutputStream z;
|
||||||
private int level;
|
private int level;
|
||||||
|
|
||||||
public IonicZipWriter(Stream s, int compressionlevel)
|
public IonicZipWriter(string path, int compressionlevel)
|
||||||
{
|
{
|
||||||
level = compressionlevel;
|
level = compressionlevel;
|
||||||
z = new ZipOutputStream(s, true)
|
z = new ZipOutputStream(path)
|
||||||
{
|
{
|
||||||
EnableZip64 = Zip64Option.Never,
|
EnableZip64 = Zip64Option.Never,
|
||||||
CompressionLevel = (Ionic.Zlib.CompressionLevel)level
|
CompressionLevel = (Ionic.Zlib.CompressionLevel)level
|
||||||
|
|
|
@ -13,8 +13,7 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
// the old method of text savestate save is now gone.
|
// 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
|
// 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(filename))
|
||||||
using (var bs = new BinaryStateSaver(fs))
|
|
||||||
{
|
{
|
||||||
if (Global.Config.SaveStateType == Config.SaveStateTypeE.Text ||
|
if (Global.Config.SaveStateType == Config.SaveStateTypeE.Text ||
|
||||||
(Global.Config.SaveStateType == Config.SaveStateTypeE.Default && !Global.Emulator.BinarySaveStatesPreferred))
|
(Global.Config.SaveStateType == Config.SaveStateTypeE.Default && !Global.Emulator.BinarySaveStatesPreferred))
|
||||||
|
|
|
@ -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<Stream> callback)
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, Stream>();
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,12 +13,12 @@ namespace BizHawk.Client.Common
|
||||||
private ZipOutputStream z;
|
private ZipOutputStream z;
|
||||||
private int level;
|
private int level;
|
||||||
|
|
||||||
public SharpZipWriter(Stream s, int compressionlevel)
|
public SharpZipWriter(string path, int compressionlevel)
|
||||||
{
|
{
|
||||||
level = compressionlevel;
|
level = compressionlevel;
|
||||||
z = new ZipOutputStream(s)
|
z = new ZipOutputStream(new FileStream(path, FileMode.Create, FileAccess.Write))
|
||||||
{
|
{
|
||||||
IsStreamOwner = false,
|
IsStreamOwner = true,
|
||||||
UseZip64 = UseZip64.Off
|
UseZip64 = UseZip64.Off
|
||||||
};
|
};
|
||||||
z.SetLevel(level);
|
z.SetLevel(level);
|
||||||
|
|
|
@ -147,8 +147,7 @@ namespace BizHawk.Client.Common
|
||||||
Directory.CreateDirectory(file.Directory.ToString());
|
Directory.CreateDirectory(file.Directory.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var fs = new FileStream(fn, FileMode.Create, FileAccess.Write))
|
using (var bs = new BinaryStateSaver(fn, false))
|
||||||
using (var bs = new BinaryStateSaver(fs, false))
|
|
||||||
{
|
{
|
||||||
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
|
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
|
||||||
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
|
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
|
||||||
|
|
|
@ -18,8 +18,7 @@ namespace BizHawk.Client.Common
|
||||||
Directory.CreateDirectory(file.Directory.ToString());
|
Directory.CreateDirectory(file.Directory.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var fs = new FileStream(fn, FileMode.Create, FileAccess.Write))
|
using (var bs = new BinaryStateSaver(fn, false))
|
||||||
using (var bs = new BinaryStateSaver(fs, false))
|
|
||||||
{
|
{
|
||||||
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
|
bs.PutLump(BinaryStateLump.Movieheader, tw => tw.WriteLine(Header.ToString()));
|
||||||
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
|
bs.PutLump(BinaryStateLump.Comments, tw => tw.WriteLine(CommentsString()));
|
||||||
|
|
|
@ -92,12 +92,12 @@ namespace BizHawk.Emulation.DiscSystem
|
||||||
long mDataLength;
|
long mDataLength;
|
||||||
public long Length { get { return mDataLength; } }
|
public long Length { get { return mDataLength; } }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if(RiffSource != null)
|
if (RiffSource != null)
|
||||||
RiffSource.Dispose();
|
RiffSource.Dispose();
|
||||||
RiffSource = null;
|
RiffSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue