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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </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
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -190,6 +190,7 @@
|
|||
<Compile Include="SaveSlotManager.cs" />
|
||||
<Compile Include="SavestateManager.cs" />
|
||||
<Compile Include="SevenZipSharpArchiveHandler.cs" />
|
||||
<Compile Include="SevenZipWriter.cs" />
|
||||
<Compile Include="SharpZipWriter.cs" />
|
||||
<Compile Include="SystemInfo.cs" />
|
||||
<Compile Include="tools\Cheat.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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 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);
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue