2 Commits

Author SHA1 Message Date
gjefferyes
5d9d63fb08 Very early SevenZip WIP version 2015-03-18 08:48:48 -05:00
gjefferyes
7830068257 2015-03-18 08:45:57 -05:00
55 changed files with 9683 additions and 3477 deletions

View File

@@ -7,6 +7,7 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using ROMVault2.Properties;
using ROMVault2.RvDB;
using ROMVault2.Utils;
@@ -548,7 +549,7 @@ namespace ROMVault2.DatReaders
int errorCode = IO.FileStream.OpenFileRead(strFilename, out _fileStream);
if (errorCode != 0)
return errorCode;
_streamReader = new StreamReader(_fileStream, Program.Enc);
_streamReader = new StreamReader(_fileStream, Encoding.UTF8);
return 0;
}
public static void Close()
@@ -578,7 +579,7 @@ namespace ROMVault2.DatReaders
while ((_line.Trim().Length == 0) && (!_streamReader.EndOfStream))
{
_line = _streamReader.ReadLine();
_line = (_line??"").Replace("" + (char)9, " ");
_line = (_line ?? "").Replace("" + (char)9, " ");
if (_line.TrimStart().Length > 2 && _line.TrimStart().Substring(0, 2) == @"//") _line = "";
if (_line.TrimStart().Length > 1 && _line.TrimStart().Substring(0, 1) == @"#") _line = "";
if (_line.TrimStart().Length > 1 && _line.TrimStart().Substring(0, 1) == @";") _line = "";

View File

@@ -124,6 +124,12 @@ namespace ROMVault2.DatReaders
tDat.AddData(RvDat.DatData.FileType, "zip");
thisFileType = FileType.ZipFile;
break;
#if sevenzip
case "7z":
tDat.AddData(RvDat.DatData.FileType, "7z");
thisFileType = FileType.SevenZipFile;
break;
#endif
case "unzip":
case "file":
tDat.AddData(RvDat.DatData.FileType, "file");

View File

@@ -284,7 +284,7 @@ namespace ROMVault2
FileType ft = dbDir.FileType;
// if we are checking a dir or zip recurse into it.
if (ft != FileType.Zip && ft != FileType.Dir) return EFile.Keep;
if (ft != FileType.Zip && ft != FileType.Dir && ft!=FileType.SevenZip) return EFile.Keep;
RvDir tDir = dbDir as RvDir;
// remove all DATStatus's here they will get set back correctly when adding dats back in below.
@@ -296,7 +296,7 @@ namespace ROMVault2
tDir.ChildRemove(i);
i--;
}
if (ft == FileType.Zip && dbDir.GotStatus == GotStatus.Corrupt) return EFile.Keep;
if ((ft == FileType.Zip || ft==FileType.SevenZip) && dbDir.GotStatus == GotStatus.Corrupt) return EFile.Keep;
// if this directory is now empty it should be deleted
return tDir.ChildCount == 0 ? EFile.Delete : EFile.Keep;
@@ -544,7 +544,7 @@ namespace ROMVault2
FileType ft = dbChild.FileType;
if (ft == FileType.Zip || ft == FileType.Dir)
if (ft == FileType.Zip || ft==FileType.SevenZip || ft == FileType.Dir)
{
RvDir dChild = (RvDir)dbChild;
RvDir dNewChild = (RvDir)newDatChild;
@@ -605,7 +605,7 @@ namespace ROMVault2
FileType ft = dbChild.FileType;
if (ft == FileType.Zip || ft == FileType.Dir)
if (ft == FileType.Zip || ft == FileType.Dir || ft==FileType.SevenZip)
{
RvDir dbDir = (RvDir)dbChild;
for (int i = 0; i < dbDir.ChildCount; i++)
@@ -627,7 +627,7 @@ namespace ROMVault2
// filetypes are now know to be the same
// Dir's and Zip's are not deep scanned so matching here is done
if ((v1 == FileType.Dir) || (v1 == FileType.Zip))
if ((v1 == FileType.Dir) || (v1 == FileType.Zip) || (v1==FileType.SevenZip))
return true;
RvFile f1 = (RvFile)var1;

View File

@@ -15,6 +15,7 @@ using ROMVault2.RvDB;
using ROMVault2.SupportedFiles;
using ROMVault2.SupportedFiles.CHD;
using ROMVault2.SupportedFiles.Files;
using ROMVault2.SupportedFiles.SevenZip;
using ROMVault2.SupportedFiles.Zip;
using ROMVault2.Utils;
using FileInfo = ROMVault2.IO.FileInfo;
@@ -140,11 +141,16 @@ namespace ROMVault2
switch (ft)
{
case FileType.Zip:
case FileType.SevenZip:
{
fileDir = new RvDir(ft);
// open the zip file
ZipFile checkZ = new ZipFile();
ICompress checkZ;
if (ft == FileType.Zip)
checkZ = new ZipFile();
else
checkZ = new SevenZ();
ZipReturn zr = checkZ.ZipFileOpen(fullDir, dbDir.TimeStamp, true);
@@ -251,6 +257,19 @@ namespace ROMVault2
string fExt = Path.GetExtension(oFile.Name);
switch (fExt.ToLower())
{
#if sevenzip
case ".7z":
{
RvDir tGame = new RvDir(FileType.SevenZip)
{
Name = Path.GetFileNameWithoutExtension(oFile.Name),
TimeStamp = oFile.LastWriteTime,
};
tGame.SetStatus(chechingDatStatus, GotStatus.Got);
fileDir.ChildAdd(tGame);
}
break;
#endif
case ".zip":
{
RvDir tGame = new RvDir(FileType.Zip)
@@ -510,6 +529,7 @@ namespace ROMVault2
switch (dbChild.FileType)
{
case FileType.Zip:
case FileType.SevenZip:
if (dbChild.TimeStamp != fileChild.TimeStamp || EScanLevel == eScanLevel.Level3 ||
(EScanLevel == eScanLevel.Level2 && !IsDeepScanned((RvDir)dbChild)))
{
@@ -530,7 +550,8 @@ namespace ROMVault2
break;
case FileType.File:
case FileType.ZipFile:
if (dbChild.TimeStamp == fileChild.TimeStamp && dbChild.GotStatus == GotStatus.Corrupt)
case FileType.SevenZipFile:
if (dbChild.TimeStamp == fileChild.TimeStamp && dbChild.GotStatus == GotStatus.Corrupt)
fileChild.GotStatus = GotStatus.Corrupt;
dbChild.FileAdd(fileChild);
@@ -555,6 +576,7 @@ namespace ROMVault2
switch (fileChild.FileType)
{
case FileType.Zip:
case FileType.SevenZip:
dbDir.ChildAdd(fileChild, dbIndex);
CheckADir((RvDir)fileChild, false);
break;
@@ -576,6 +598,7 @@ namespace ROMVault2
dbDir.ChildAdd(fileChild, dbIndex);
break;
case FileType.ZipFile:
case FileType.SevenZipFile:
dbDir.ChildAdd(fileChild, dbIndex);
break;
default:
@@ -669,7 +692,7 @@ namespace ROMVault2
// filetypes are now know to be the same
// Dir's and Zip's are not deep scanned so matching here is done
if ((dbfileType == FileType.Dir) || (dbfileType == FileType.Zip))
if ((dbfileType == FileType.Dir) || (dbfileType == FileType.Zip) || (dbfileType==FileType.SevenZip))
return true;
RvFile dbFileF = (RvFile)dbFile;

View File

@@ -7,9 +7,12 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Security.Cryptography;
using ROMVault2.RvDB;
using ROMVault2.SupportedFiles;
using ROMVault2.SupportedFiles.SevenZip;
using ROMVault2.SupportedFiles.Zip;
using ROMVault2.SupportedFiles.Zip.ZLib;
using ROMVault2.Utils;
@@ -44,7 +47,7 @@ namespace ROMVault2
/// <param name="foundFile">If we are SHA1/MD5 checking the source file for the first time, and it is different from what we expected the correct values for this file are returned in foundFile</param>
/// <returns>ReturnCode.Good is the valid return code otherwire we have an error</returns>
public static ReturnCode CopyFile(RvFile fileIn, ref ZipFile zipFileOut, string zipFilenameOut, RvFile fileOut, bool forceRaw, out string error, out RvFile foundFile)
public static ReturnCode CopyFile(RvFile fileIn, ref ICompress zipFileOut, string zipFilenameOut, RvFile fileOut, bool forceRaw, out string error, out RvFile foundFile)
{
foundFile = null;
error = "";
@@ -59,120 +62,21 @@ namespace ROMVault2
bool sourceTrrntzip = false;
ZipFile zipFileIn = null;
System.IO.Stream readStream = null;
ICompress zipFileIn = null;
Stream readStream = null;
ReturnCode retC;
bool isZeroLengthFile = DBHelper.IsZeroLengthFile(fileOut);
if (!isZeroLengthFile)
{
#region check that the in and out file match
if (fileOut.FileStatusIs(FileStatus.SizeFromDAT) && fileOut.Size != null && fileIn.Size != fileOut.Size)
{
error = "Source and destination Size does not match. Logic Error.";
return ReturnCode.LogicError;
}
if (fileOut.FileStatusIs(FileStatus.CRCFromDAT) && fileOut.CRC != null && !ArrByte.bCompare(fileIn.CRC, fileOut.CRC))
{
error = "Source and destination CRC does not match. Logic Error.";
return ReturnCode.LogicError;
}
retC = CheckInputAndOutputFile(fileIn, fileOut, out error);
if (retC != ReturnCode.Good)
return retC;
if (fileOut.FileStatusIs(FileStatus.SHA1FromDAT) && fileIn.FileStatusIs(FileStatus.SHA1Verified))
{
if (fileIn.SHA1 != null && fileOut.SHA1 != null && !ArrByte.bCompare(fileIn.SHA1, fileOut.SHA1))
{
error = "Source and destination SHA1 does not match. Logic Error.";
return ReturnCode.LogicError;
}
}
if (fileOut.FileStatusIs(FileStatus.MD5CHDFromDAT) && fileIn.FileStatusIs(FileStatus.MD5Verified))
{
if (fileIn.MD5 != null && fileOut.MD5 != null && !ArrByte.bCompare(fileIn.MD5, fileOut.MD5))
{
error = "Source and destination SHA1 does not match. Logic Error.";
return ReturnCode.LogicError;
}
}
#endregion
#region Find and Check/Open Input Files
if (fileIn.FileType == FileType.ZipFile) // Input is a ZipFile
{
RvDir zZipFileIn = fileIn.Parent;
if (zZipFileIn.FileType != FileType.Zip)
{
error = "Zip File Open but Source File is not a zip, Logic Error.";
return ReturnCode.LogicError;
}
string fileNameIn = zZipFileIn.FullName;
sourceTrrntzip = (zZipFileIn.ZipStatus & ZipStatus.TrrntZip) == ZipStatus.TrrntZip;
//if (zZipFileIn.ZipFileType == RvZip.ZipType.Zip)
//{
zipFileIn = new ZipFile();
ZipReturn zr1;
if (fileIn.ZipFileHeaderPosition != null)
zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, false);
else
zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, true);
switch (zr1)
{
case ZipReturn.ZipGood:
break;
case ZipReturn.ZipErrorFileNotFound:
error = "File not found, Rescan required before fixing " + fileIn.Name;
return ReturnCode.FileSystemError;
case ZipReturn.ZipErrorTimeStamp:
error = "File has changed, Rescan required before fixing " + fileIn.Name;
return ReturnCode.FileSystemError;
default:
error = "Error Open Zip" + zr1 + ", with File " + fileIn.DatFullName;
return ReturnCode.FileSystemError;
}
if (fileIn.ZipFileHeaderPosition != null)
zipFileIn.ZipFileOpenReadStreamQuick((ulong)fileIn.ZipFileHeaderPosition, rawCopy, out readStream, out streamSize, out compressionMethod);
else
zipFileIn.ZipFileOpenReadStream(fileIn.ZipFileIndex, rawCopy, out readStream, out streamSize, out compressionMethod);
}
else // Input is a regular file
{
string fileNameIn = fileIn.FullName;
if (!IO.File.Exists(fileNameIn))
{
error = "Rescan needed, File Changed :" + fileNameIn;
return ReturnCode.RescanNeeded;
}
IO.FileInfo fileInInfo = new IO.FileInfo(fileNameIn);
if (fileInInfo.LastWriteTime != fileIn.TimeStamp)
{
error = "Rescan needed, File Changed :" + fileNameIn;
return ReturnCode.RescanNeeded;
}
int errorCode = IO.FileStream.OpenFileRead(fileNameIn, out readStream);
if (errorCode != 0)
{
error = new Win32Exception(errorCode).Message + ". " + fileNameIn;
return ReturnCode.FileSystemError;
}
if (fileIn.Size == null)
{
error = "Null File Size found in Fixing File :" + fileNameIn;
return ReturnCode.LogicError;
}
streamSize = (ulong)fileIn.Size;
if ((ulong)readStream.Length != streamSize)
{
error = "Rescan needed, File Length Changed :" + fileNameIn;
return ReturnCode.RescanNeeded;
}
}
#endregion
retC = OpenInputStream(fileIn, rawCopy, out zipFileIn, out sourceTrrntzip, out readStream, out streamSize, out compressionMethod, out error);
if (retC != ReturnCode.Good)
return retC;
}
else
{
@@ -184,72 +88,12 @@ namespace ROMVault2
#region Find and Check/Open Output Files
System.IO.Stream writeStream;
if (fileOut.FileType == FileType.ZipFile)
{
// if ZipFileOut == null then we have not open the output zip yet so open it from writing.
if (zipFileOut == null)
{
if (IO.Path.GetFileName(zipFilenameOut) == "__RomVault.tmp")
{
if (IO.File.Exists(zipFilenameOut))
IO.File.Delete(zipFilenameOut);
}
else if (IO.File.Exists(zipFilenameOut))
{
error = "Rescan needed, File Changed :" + zipFilenameOut;
return ReturnCode.RescanNeeded;
}
Stream writeStream;
zipFileOut = new ZipFile();
ZipReturn zrf = zipFileOut.ZipFileCreate(zipFilenameOut);
if (zrf != ZipReturn.ZipGood)
{
error = "Error Opening Write Stream " + zrf;
return ReturnCode.FileSystemError;
}
}
else
{
if (zipFileOut.ZipOpen != ZipOpenType.OpenWrite)
{
error = "Output Zip File is not set to OpenWrite, Logic Error.";
return ReturnCode.LogicError;
}
retC = OpenOutputStream(fileOut, fileIn, ref zipFileOut, zipFilenameOut, compressionMethod, rawCopy, sourceTrrntzip, out writeStream, out error);
if (retC != ReturnCode.Good)
return retC;
if (zipFileOut.ZipFilename != (new IO.FileInfo(zipFilenameOut).FullName))
{
error = "Output Zip file has changed name from " + zipFileOut.ZipFilename + " to " + zipFilenameOut + ". Logic Error";
return ReturnCode.LogicError;
}
}
if (fileIn.Size == null)
{
error = "Null File Size found in Fixing File :" + fileIn.FullName;
return ReturnCode.LogicError;
}
ZipReturn zr = zipFileOut.ZipFileOpenWriteStream(rawCopy, sourceTrrntzip, fileOut.Name, (ulong)fileIn.Size, compressionMethod, out writeStream);
if (zr != ZipReturn.ZipGood)
{
error = "Error Opening Write Stream " + zr;
return ReturnCode.FileSystemError;
}
}
else
{
if (IO.File.Exists(zipFilenameOut) && fileOut.GotStatus != GotStatus.Corrupt)
{
error = "Rescan needed, File Changed :" + zipFilenameOut;
return ReturnCode.RescanNeeded;
}
int errorCode = IO.FileStream.OpenFileWrite(zipFilenameOut, out writeStream);
if (errorCode != 0)
{
error = new Win32Exception(errorCode).Message + ". " + zipFilenameOut;
return ReturnCode.FileSystemError;
}
}
#endregion
byte[] bCRC;
@@ -374,7 +218,7 @@ namespace ROMVault2
#region close the ReadStream
if (fileIn.FileType == FileType.ZipFile && zipFileIn != null)
if ((fileIn.FileType == FileType.ZipFile || fileIn.FileType == FileType.SevenZipFile) && zipFileIn != null)
{
ZipReturn zr = zipFileIn.ZipFileCloseReadStream();
if (zr != ZipReturn.ZipGood)
@@ -408,7 +252,7 @@ namespace ROMVault2
#region close the WriteStream
if (fileOut.FileType == FileType.ZipFile)
if (fileOut.FileType == FileType.ZipFile || fileOut.FileType == FileType.SevenZipFile)
{
ZipReturn zr = zipFileOut.ZipFileCloseWriteStream(bCRC);
if (zr != ZipReturn.ZipGood)
@@ -516,7 +360,7 @@ namespace ROMVault2
if (sourceFailed)
{
if (fileIn.FileType == FileType.ZipFile)
if (fileIn.FileType == FileType.ZipFile || fileIn.FileType == FileType.SevenZipFile)
{
RvFile tZFile = new RvFile(FileType.ZipFile);
foundFile = tZFile;
@@ -548,7 +392,7 @@ namespace ROMVault2
}
}
if (fileOut.FileType == FileType.ZipFile)
if (fileOut.FileType == FileType.ZipFile || fileOut.FileType == FileType.SevenZipFile)
{
fileOut.FileStatusSet(FileStatus.SizeFromHeader | FileStatus.CRCFromHeader);
}
@@ -671,5 +515,227 @@ namespace ROMVault2
return false;
}
private static ReturnCode CheckInputAndOutputFile(RvFile fileIn, RvFile fileOut, out string error)
{
if (fileOut.FileStatusIs(FileStatus.SizeFromDAT) && fileOut.Size != null && fileIn.Size != fileOut.Size)
{
error = "Source and destination Size does not match. Logic Error.";
return ReturnCode.LogicError;
}
if (fileOut.FileStatusIs(FileStatus.CRCFromDAT) && fileOut.CRC != null && !ArrByte.bCompare(fileIn.CRC, fileOut.CRC))
{
error = "Source and destination CRC does not match. Logic Error.";
return ReturnCode.LogicError;
}
if (fileOut.FileStatusIs(FileStatus.SHA1FromDAT) && fileIn.FileStatusIs(FileStatus.SHA1Verified))
{
if (fileIn.SHA1 != null && fileOut.SHA1 != null && !ArrByte.bCompare(fileIn.SHA1, fileOut.SHA1))
{
error = "Source and destination SHA1 does not match. Logic Error.";
return ReturnCode.LogicError;
}
}
if (fileOut.FileStatusIs(FileStatus.MD5CHDFromDAT) && fileIn.FileStatusIs(FileStatus.MD5Verified))
{
if (fileIn.MD5 != null && fileOut.MD5 != null && !ArrByte.bCompare(fileIn.MD5, fileOut.MD5))
{
error = "Source and destination SHA1 does not match. Logic Error.";
return ReturnCode.LogicError;
}
}
error = "";
return ReturnCode.Good;
}
private static ReturnCode OpenInputStream(RvFile fileIn, bool rawCopy, out ICompress zipFileIn, out bool sourceTrrntzip, out Stream readStream, out ulong streamSize, out ushort compressionMethod, out string error)
{
zipFileIn = null;
sourceTrrntzip = false;
readStream = null;
streamSize = 0;
compressionMethod = 0;
switch (fileIn.FileType)
{
case FileType.SevenZipFile:
case FileType.ZipFile:
{
RvDir zZipFileIn = fileIn.Parent;
if (zZipFileIn.FileType != DBTypeGet.DirFromFile(fileIn.FileType))
{
error = "SevenZip File Open but Source File is not a SevenZip, Logic Error.";
return ReturnCode.LogicError;
}
string fileNameIn = zZipFileIn.FullName;
ZipReturn zr1;
if (fileIn.FileType == FileType.SevenZipFile)
{
sourceTrrntzip = false;
zipFileIn = new SevenZ();
zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, true);
}
else
{
sourceTrrntzip = (zZipFileIn.ZipStatus & ZipStatus.TrrntZip) == ZipStatus.TrrntZip;
zipFileIn = new ZipFile();
zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, fileIn.ZipFileHeaderPosition == null);
}
switch (zr1)
{
case ZipReturn.ZipGood:
break;
case ZipReturn.ZipErrorFileNotFound:
error = "File not found, Rescan required before fixing " + fileIn.Name;
return ReturnCode.FileSystemError;
case ZipReturn.ZipErrorTimeStamp:
error = "File has changed, Rescan required before fixing " + fileIn.Name;
return ReturnCode.FileSystemError;
default:
error = "Error Open Zip" + zr1 + ", with File " + fileIn.DatFullName;
return ReturnCode.FileSystemError;
}
if (fileIn.FileType == FileType.SevenZipFile)
{
SevenZ z = zipFileIn as SevenZ;
z.ZipFileOpenReadStream(fileIn.ZipFileIndex, out readStream, out streamSize);
}
else
{
ZipFile z = zipFileIn as ZipFile;
if (fileIn.ZipFileHeaderPosition != null)
z.ZipFileOpenReadStreamQuick((ulong)fileIn.ZipFileHeaderPosition, rawCopy, out readStream, out streamSize, out compressionMethod);
else
z.ZipFileOpenReadStream(fileIn.ZipFileIndex, rawCopy, out readStream, out streamSize, out compressionMethod);
}
}
break;
default:
{
string fileNameIn = fileIn.FullName;
if (!IO.File.Exists(fileNameIn))
{
error = "Rescan needed, File Changed :" + fileNameIn;
return ReturnCode.RescanNeeded;
}
IO.FileInfo fileInInfo = new IO.FileInfo(fileNameIn);
if (fileInInfo.LastWriteTime != fileIn.TimeStamp)
{
error = "Rescan needed, File Changed :" + fileNameIn;
return ReturnCode.RescanNeeded;
}
int errorCode = IO.FileStream.OpenFileRead(fileNameIn, out readStream);
if (errorCode != 0)
{
error = new Win32Exception(errorCode).Message + ". " + fileNameIn;
return ReturnCode.FileSystemError;
}
if (fileIn.Size == null)
{
error = "Null File Size found in Fixing File :" + fileNameIn;
return ReturnCode.LogicError;
}
streamSize = (ulong)fileIn.Size;
if ((ulong)readStream.Length != streamSize)
{
error = "Rescan needed, File Length Changed :" + fileNameIn;
return ReturnCode.RescanNeeded;
}
}
break;
}
error = "";
return ReturnCode.Good;
}
private static ReturnCode OpenOutputStream(RvFile fileOut, RvFile fileIn, ref ICompress zipFileOut, string zipFilenameOut, ushort compressionMethod, bool rawCopy, bool sourceTrrntzip, out System.IO.Stream writeStream, out string error)
{
writeStream = null;
switch (fileOut.FileType)
{
case FileType.ZipFile:
case FileType.SevenZipFile:
{
// if ZipFileOut == null then we have not open the output zip yet so open it from writing.
if (zipFileOut == null)
{
if (IO.Path.GetFileName(zipFilenameOut) == "__RomVault.tmp")
{
if (IO.File.Exists(zipFilenameOut))
IO.File.Delete(zipFilenameOut);
}
else if (IO.File.Exists(zipFilenameOut))
{
error = "Rescan needed, File Changed :" + zipFilenameOut;
return ReturnCode.RescanNeeded;
}
if (fileOut.FileType == FileType.ZipFile)
zipFileOut = new ZipFile();
else
zipFileOut = new SevenZ();
ZipReturn zrf = zipFileOut.ZipFileCreate(zipFilenameOut);
if (zrf != ZipReturn.ZipGood)
{
error = "Error Opening Write Stream " + zrf;
return ReturnCode.FileSystemError;
}
}
else
{
if (zipFileOut.ZipOpen != ZipOpenType.OpenWrite)
{
error = "Output Zip File is not set to OpenWrite, Logic Error.";
return ReturnCode.LogicError;
}
if (zipFileOut.ZipFilename != (new IO.FileInfo(zipFilenameOut).FullName))
{
error = "Output Zip file has changed name from " + zipFileOut.ZipFilename + " to " + zipFilenameOut + ". Logic Error";
return ReturnCode.LogicError;
}
}
if (fileIn.Size == null)
{
error = "Null File Size found in Fixing File :" + fileIn.FullName;
return ReturnCode.LogicError;
}
ZipReturn zr = zipFileOut.ZipFileOpenWriteStream(rawCopy, sourceTrrntzip, fileOut.Name, (ulong)fileIn.Size, compressionMethod, out writeStream);
if (zr != ZipReturn.ZipGood)
{
error = "Error Opening Write Stream " + zr;
return ReturnCode.FileSystemError;
}
}
break;
default:
{
if (IO.File.Exists(zipFilenameOut) && fileOut.GotStatus != GotStatus.Corrupt)
{
error = "Rescan needed, File Changed :" + zipFilenameOut;
return ReturnCode.RescanNeeded;
}
int errorCode = IO.FileStream.OpenFileWrite(zipFilenameOut, out writeStream);
if (errorCode != 0)
{
error = new Win32Exception(errorCode).Message + ". " + zipFilenameOut;
return ReturnCode.FileSystemError;
}
}
break;
}
error = "";
return ReturnCode.Good;
}
}
}

View File

@@ -14,6 +14,7 @@ using ROMVault2.Properties;
using ROMVault2.RvDB;
using ROMVault2.SupportedFiles;
using ROMVault2.SupportedFiles.Zip;
using ROMVault2.Utils;
namespace ROMVault2
{
@@ -133,6 +134,7 @@ namespace ROMVault2
switch (child.FileType)
{
case FileType.Zip:
case FileType.SevenZip:
if (!thisSelected)
continue;
RvDir tZip = (RvDir)child;
@@ -230,6 +232,23 @@ namespace ROMVault2
} while (returnCode == ReturnCode.StartOver);
break;
case FileType.SevenZip:
if (!thisSelected)
return ReturnCode.Good;
if (!String.IsNullOrEmpty(child.FileName))
{
string strDir = child.Parent.FullName;
File.Move(Path.Combine(strDir, child.FileName + ".z7"), Path.Combine(strDir, child.Name + ".z7"));
child.FileName = null;
}
do
{
returnCode = FixZip((RvDir)child);
} while (returnCode == ReturnCode.StartOver);
break;
case FileType.Dir:
if (thisSelected)
{
@@ -418,7 +437,7 @@ namespace ROMVault2
ReportProgress(new bgwShowFix(Path.GetDirectoryName(fixFileFullName), "", Path.GetFileName(fixFileFullName), fixFile.Size, "-->", "ToSort", "", fixFile.Name));
ZipFile tempZipOut = null;
ICompress tempZipOut = null;
RvFile foundFile;
ReturnCode returnCode = FixFileCopy.CopyFile(fixFile, ref tempZipOut, toSortFullName, toSortRom, false, out _error, out foundFile);
switch (returnCode)
@@ -481,7 +500,7 @@ namespace ROMVault2
_bgw.ReportProgress(0, new bgwShowFix(Path.GetDirectoryName(fixFileFullName), "", Path.GetFileName(fixFileFullName), fixFile.Size, "-->", "Corrupt", "", fixFile.Name));
ZipFile tempZipOut = null;
ICompress tempZipOut = null;
RvFile foundFile;
ReturnCode returnCode = FixFileCopy.CopyFile(fixFile, ref tempZipOut, toSortCorruptFullName, toSortCorruptRom, false, out _error, out foundFile);
switch (returnCode)
@@ -642,7 +661,7 @@ namespace ROMVault2
// now we can fix the file.
ZipFile tempZipOut = null;
ICompress tempZipOut = null;
RvFile foundFile;
ReturnCode returnCode;
@@ -851,7 +870,8 @@ namespace ROMVault2
return ReturnCode.Good;
}
if (!fixZip.DirStatus.HasFixable() && needsTrrntzipped && fixZip.FileType == FileType.SevenZip)
return ReturnCode.Good;
string fixZipFullName = fixZip.TreeFullName;
@@ -869,10 +889,10 @@ namespace ROMVault2
ReportError.LogOut((RvFile)fixZip.Child(intLoop));
ReportError.LogOut("");
ZipFile tempZipOut = null;
ICompress tempZipOut = null;
ZipFile toSortCorruptOut = null;
ZipFile toSortZipOut = null;
ICompress toSortCorruptOut = null;
ICompress toSortZipOut = null;
RvDir toSortGame = null;
RvDir toSortCorruptGame = null;
@@ -880,9 +900,11 @@ namespace ROMVault2
ReturnCode returnCode;
List<RvFile> fixZipTemp = new List<RvFile>();
FileType fixFileType = fixZip.FileType;
for (int iRom = 0; iRom < fixZip.ChildCount; iRom++)
{
RvFile zipFileFixing = new RvFile(FileType.ZipFile);
RvFile zipFileFixing = new RvFile(DBTypeGet.FileFromDir(fixFileType));
fixZip.Child(iRom).CopyTo(zipFileFixing);
if (iRom == fixZipTemp.Count)
@@ -1063,7 +1085,7 @@ namespace ROMVault2
string ts = lstFixRomTable[0].Parent.FullName;
string sourceDir;
string sourceFile;
if (lstFixRomTable[0].FileType == FileType.ZipFile)
if (lstFixRomTable[0].FileType == FileType.ZipFile || lstFixRomTable[0].FileType == FileType.SevenZipFile)
{
sourceDir = Path.GetDirectoryName(ts);
sourceFile = Path.GetFileName(ts);
@@ -1593,6 +1615,7 @@ namespace ROMVault2
switch (fileToCheck.FileType)
{
case FileType.ZipFile:
case FileType.SevenZipFile:
{
string fullPathCheckDelete = fileToCheck.Parent.FullName;
if (!File.Exists(fullPathCheckDelete))
@@ -1775,6 +1798,7 @@ namespace ROMVault2
_processList.Add(tCheck);
break;
case FileType.ZipFile:
case FileType.SevenZipFile:
RvDir p = tCheck.Parent;
if (fastProcess)

View File

@@ -71,7 +71,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackgroundImage = global::ROMVault2.rvImages.romvaultTZ;
this.BackgroundImage = global::ROMVault2.rvImages1.romvaultTZ;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.ClientSize = new System.Drawing.Size(471, 172);
this.Controls.Add(this.label2);

View File

@@ -28,19 +28,14 @@
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain));
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain));
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.btnReport = new System.Windows.Forms.Button();
this.btnFixFiles = new System.Windows.Forms.Button();
this.btnFindFixes = new System.Windows.Forms.Button();
this.btnScanRoms = new System.Windows.Forms.Button();
this.btnUpdateDats = new System.Windows.Forms.Button();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.splitContainer3 = new System.Windows.Forms.SplitContainer();
this.gbDatInfo = new System.Windows.Forms.GroupBox();
@@ -109,6 +104,11 @@
this.dataGridViewImageColumn1 = new System.Windows.Forms.DataGridViewImageColumn();
this.dataGridViewImageColumn2 = new System.Windows.Forms.DataGridViewImageColumn();
this.dataGridViewImageColumn3 = new System.Windows.Forms.DataGridViewImageColumn();
this.btnReport = new System.Windows.Forms.Button();
this.btnFixFiles = new System.Windows.Forms.Button();
this.btnFindFixes = new System.Windows.Forms.Button();
this.btnScanRoms = new System.Windows.Forms.Button();
this.btnUpdateDats = new System.Windows.Forms.Button();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
@@ -154,71 +154,6 @@
this.splitContainer1.SplitterDistance = 80;
this.splitContainer1.TabIndex = 5;
//
// btnReport
//
this.btnReport.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnReport.BackgroundImage")));
this.btnReport.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnReport.Location = new System.Drawing.Point(0, 320);
this.btnReport.Name = "btnReport";
this.btnReport.Size = new System.Drawing.Size(80, 80);
this.btnReport.TabIndex = 13;
this.btnReport.Text = "Generate Reports";
this.btnReport.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnReport.UseVisualStyleBackColor = true;
this.btnReport.Click += new System.EventHandler(this.BtnReportClick);
//
// btnFixFiles
//
this.btnFixFiles.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnFixFiles.BackgroundImage")));
this.btnFixFiles.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnFixFiles.Location = new System.Drawing.Point(0, 240);
this.btnFixFiles.Name = "btnFixFiles";
this.btnFixFiles.Size = new System.Drawing.Size(80, 80);
this.btnFixFiles.TabIndex = 10;
this.btnFixFiles.Text = "Fix ROMs";
this.btnFixFiles.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnFixFiles.UseVisualStyleBackColor = true;
this.btnFixFiles.Click += new System.EventHandler(this.BtnFixFilesClick);
//
// btnFindFixes
//
this.btnFindFixes.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnFindFixes.BackgroundImage")));
this.btnFindFixes.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnFindFixes.Location = new System.Drawing.Point(0, 160);
this.btnFindFixes.Name = "btnFindFixes";
this.btnFindFixes.Size = new System.Drawing.Size(80, 80);
this.btnFindFixes.TabIndex = 9;
this.btnFindFixes.Text = "Find Fixes";
this.btnFindFixes.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnFindFixes.UseVisualStyleBackColor = true;
this.btnFindFixes.Click += new System.EventHandler(this.BtnFindFixesClick);
//
// btnScanRoms
//
this.btnScanRoms.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnScanRoms.BackgroundImage")));
this.btnScanRoms.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnScanRoms.Location = new System.Drawing.Point(0, 80);
this.btnScanRoms.Name = "btnScanRoms";
this.btnScanRoms.Size = new System.Drawing.Size(80, 80);
this.btnScanRoms.TabIndex = 8;
this.btnScanRoms.Text = "Scan ROMs";
this.btnScanRoms.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnScanRoms.UseVisualStyleBackColor = true;
this.btnScanRoms.Click += new System.EventHandler(this.BtnScanRomsClick);
//
// btnUpdateDats
//
this.btnUpdateDats.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnUpdateDats.BackgroundImage")));
this.btnUpdateDats.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnUpdateDats.Location = new System.Drawing.Point(0, 0);
this.btnUpdateDats.Name = "btnUpdateDats";
this.btnUpdateDats.Size = new System.Drawing.Size(80, 80);
this.btnUpdateDats.TabIndex = 0;
this.btnUpdateDats.Text = "Update DATs";
this.btnUpdateDats.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnUpdateDats.UseVisualStyleBackColor = true;
this.btnUpdateDats.Click += new System.EventHandler(this.BtnUpdateDatsClick);
//
// splitContainer2
//
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -653,10 +588,10 @@
this.GameGrid.Size = new System.Drawing.Size(697, 267);
this.GameGrid.TabIndex = 4;
this.GameGrid.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.GameGrid_CellFormatting);
this.GameGrid.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.GameGridColumnHeaderMouseClick);
this.GameGrid.SelectionChanged += new System.EventHandler(this.GameGridSelectionChanged);
this.GameGrid.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.GameGridMouseDoubleClick);
this.GameGrid.MouseUp += new System.Windows.Forms.MouseEventHandler(this.GameGrid_MouseUp);
this.GameGrid.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.GameGridColumnHeaderMouseClick);
//
// Type
//
@@ -665,7 +600,6 @@
this.Type.Name = "Type";
this.Type.ReadOnly = true;
this.Type.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.Type.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.Type.Width = 40;
//
// CGame
@@ -690,7 +624,6 @@
this.CCorrect.Name = "CCorrect";
this.CCorrect.ReadOnly = true;
this.CCorrect.Resizable = System.Windows.Forms.DataGridViewTriState.False;
this.CCorrect.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.CCorrect.Width = 500;
//
// RomGrid
@@ -760,7 +693,6 @@
this.CGot.Name = "CGot";
this.CGot.ReadOnly = true;
this.CGot.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.CGot.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.CGot.Width = 65;
//
// CRom
@@ -972,6 +904,71 @@
this.dataGridViewImageColumn3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
this.dataGridViewImageColumn3.Width = 65;
//
// btnReport
//
this.btnReport.BackgroundImage = global::ROMVault2.rvImages1.btnReport_BackgroundImage;
this.btnReport.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnReport.Location = new System.Drawing.Point(0, 320);
this.btnReport.Name = "btnReport";
this.btnReport.Size = new System.Drawing.Size(80, 80);
this.btnReport.TabIndex = 13;
this.btnReport.Text = "Generate Reports";
this.btnReport.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnReport.UseVisualStyleBackColor = true;
this.btnReport.Click += new System.EventHandler(this.BtnReportClick);
//
// btnFixFiles
//
this.btnFixFiles.BackgroundImage = global::ROMVault2.rvImages1.btnFixFiles_BackgroundImage;
this.btnFixFiles.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnFixFiles.Location = new System.Drawing.Point(0, 240);
this.btnFixFiles.Name = "btnFixFiles";
this.btnFixFiles.Size = new System.Drawing.Size(80, 80);
this.btnFixFiles.TabIndex = 10;
this.btnFixFiles.Text = "Fix ROMs";
this.btnFixFiles.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnFixFiles.UseVisualStyleBackColor = true;
this.btnFixFiles.Click += new System.EventHandler(this.BtnFixFilesClick);
//
// btnFindFixes
//
this.btnFindFixes.BackgroundImage = global::ROMVault2.rvImages1.btnFindFixes_BackgroundImage;
this.btnFindFixes.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnFindFixes.Location = new System.Drawing.Point(0, 160);
this.btnFindFixes.Name = "btnFindFixes";
this.btnFindFixes.Size = new System.Drawing.Size(80, 80);
this.btnFindFixes.TabIndex = 9;
this.btnFindFixes.Text = "Find Fixes";
this.btnFindFixes.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnFindFixes.UseVisualStyleBackColor = true;
this.btnFindFixes.Click += new System.EventHandler(this.BtnFindFixesClick);
//
// btnScanRoms
//
this.btnScanRoms.BackgroundImage = global::ROMVault2.rvImages1.btnScanRoms_BackgroundImage;
this.btnScanRoms.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnScanRoms.Location = new System.Drawing.Point(0, 80);
this.btnScanRoms.Name = "btnScanRoms";
this.btnScanRoms.Size = new System.Drawing.Size(80, 80);
this.btnScanRoms.TabIndex = 8;
this.btnScanRoms.Text = "Scan ROMs";
this.btnScanRoms.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnScanRoms.UseVisualStyleBackColor = true;
this.btnScanRoms.Click += new System.EventHandler(this.BtnScanRomsClick);
//
// btnUpdateDats
//
this.btnUpdateDats.BackgroundImage = global::ROMVault2.rvImages1.btnUpdateDats_BackgroundImage;
this.btnUpdateDats.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.btnUpdateDats.Location = new System.Drawing.Point(0, 0);
this.btnUpdateDats.Name = "btnUpdateDats";
this.btnUpdateDats.Size = new System.Drawing.Size(80, 80);
this.btnUpdateDats.TabIndex = 0;
this.btnUpdateDats.Text = "Update DATs";
this.btnUpdateDats.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnUpdateDats.UseVisualStyleBackColor = true;
this.btnUpdateDats.Click += new System.EventHandler(this.BtnUpdateDatsClick);
//
// FrmMain
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;

View File

@@ -774,6 +774,12 @@ namespace ROMVault2
else
bitmapName = "Zip" + tRvDir.RepStatus;
break;
case FileType.SevenZip:
if (tRvDir.RepStatus == RepStatus.DirCorrect && tRvDir.ZipStatus == ZipStatus.TrrntZip)
bitmapName = "SevenZipTZ";
else
bitmapName = "SevenZip" + tRvDir.RepStatus;
break;
default:
// hack because DirDirInToSort image doesnt exist.
if (tRvDir.RepStatus == RepStatus.DirInToSort)

View File

@@ -117,411 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="btnReport.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
<data name="btnFixFiles.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
YII=
</value>
</data>
<data name="btnFindFixes.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
RU5ErkJggg==
</value>
</data>
<data name="btnScanRoms.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
<data name="btnUpdateDats.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
<metadata name="Type.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@@ -567,6 +162,7 @@
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAUAEBAAAAAAIABoBAAAVgAAACAgAAAAACAAqBAAAL4EAAAwMAAAAAAgAKglAABmFQAAQEAAAAAA

View File

@@ -29,7 +29,6 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmSplashScreen));
this.lblStatus = new System.Windows.Forms.Label();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.progressBar = new System.Windows.Forms.ProgressBar();
@@ -76,7 +75,7 @@
// FrmSplashScreen
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
this.BackgroundImage = global::ROMVault2.rvImages1.romvaultTZ;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.ClientSize = new System.Drawing.Size(465, 207);
this.ControlBox = false;

View File

@@ -123,447 +123,4 @@
<metadata name="bgWork.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>104, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
</value>
</data>
</root>

View File

@@ -70,7 +70,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>..\..\Stage\</OutputPath>
<DefineConstants>TRACE;UNMANAGED;COMPRESS;LZMA_STREAM;DOTNET20</DefineConstants>
<DefineConstants>TRACE;UNMANAGED;COMPRESS;LZMA_STREAM;DOTNET20;sevenzip</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -82,6 +82,7 @@
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<Prefer32Bit>false</Prefer32Bit>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>chip.ico</ApplicationIcon>
@@ -118,6 +119,36 @@
<Compile Include="rvTreeRow.cs" />
<Compile Include="rvImages.cs" />
<Compile Include="SupportedFiles\Files\UnCompFiles.cs" />
<Compile Include="SupportedFiles\ICompress.cs" />
<Compile Include="SupportedFiles\SevenZip\Common\CRC.cs" />
<Compile Include="SupportedFiles\SevenZip\Common\ICoder.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZMA\LzmaBase.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZMA\LzmaDecoder.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZMA\LzmaEncoder.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZ\IMatchFinder.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZ\LzBinTree.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZ\LzInWindow.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\LZ\LzOutWindow.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\RangeCoder\RangeCoder.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\RangeCoder\RangeCoderBit.cs" />
<Compile Include="SupportedFiles\SevenZip\Compress\RangeCoder\RangeCoderBitTree.cs" />
<Compile Include="SupportedFiles\SevenZip\DirUtil.cs" />
<Compile Include="SupportedFiles\SevenZip\Filters\BCJ2Filter.cs" />
<Compile Include="SupportedFiles\SevenZip\Filters\BCJFilter.cs" />
<Compile Include="SupportedFiles\SevenZip\Filters\Filter.cs" />
<Compile Include="SupportedFiles\SevenZip\LZMACompressFile.cs" />
<Compile Include="SupportedFiles\SevenZip\SevenZip.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\BindPair.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\Coder.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\FileInfo.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\Folder.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\Header.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\PackedStreamInfo.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\SignatureHeader.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\StreamsInfo.cs" />
<Compile Include="SupportedFiles\SevenZip\Structure\UnpackedStreamInfo.cs" />
<Compile Include="SupportedFiles\SevenZip\TesterStream.cs" />
<Compile Include="SupportedFiles\SevenZip\Util.cs" />
<Compile Include="SupportedFiles\ZipEnums.cs" />
<Compile Include="Utils\ArrByte.cs" />
<Compile Include="BackGroundWorkerInterface.cs" />

View File

@@ -92,6 +92,19 @@ namespace ROMVault2
StatusCheck[(int)FileType.Zip, (int)DatStatus.NotInDat, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.Zip, (int)DatStatus.NotInDat, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InDatCollect, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.DirCorrect };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InDatCollect, (int)GotStatus.Corrupt] = new List<RepStatus> { RepStatus.DirCorrupt };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InDatCollect, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InDatCollect, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.DirMissing };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InToSort, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.DirInToSort };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InToSort, (int)GotStatus.Corrupt] = new List<RepStatus> { RepStatus.DirCorrupt };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InToSort, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.InToSort, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.NotInDat, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.DirUnknown };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.NotInDat, (int)GotStatus.Corrupt] = new List<RepStatus> { RepStatus.DirCorrupt };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.NotInDat, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.SevenZip, (int)DatStatus.NotInDat, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
StatusCheck[(int)FileType.File, (int)DatStatus.InDatBad, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.File, (int)DatStatus.InDatBad, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.NotCollected };
@@ -111,7 +124,7 @@ namespace ROMVault2
StatusCheck[(int)FileType.File, (int)DatStatus.NotInDat, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.Unknown, RepStatus.Ignore, RepStatus.Delete, RepStatus.MoveToSort, RepStatus.NeededForFix, RepStatus.Rename };
StatusCheck[(int)FileType.File, (int)DatStatus.NotInDat, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.File, (int)DatStatus.NotInDat, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
StatusCheck[(int)FileType.ZipFile, (int)DatStatus.InDatBad, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.NotCollected };
StatusCheck[(int)FileType.ZipFile, (int)DatStatus.InDatBad, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.Correct };
@@ -128,6 +141,22 @@ namespace ROMVault2
StatusCheck[(int)FileType.ZipFile, (int)DatStatus.NotInDat, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.Unknown, RepStatus.Delete, RepStatus.MoveToSort, RepStatus.NeededForFix, RepStatus.Rename };
StatusCheck[(int)FileType.ZipFile, (int)DatStatus.NotInDat, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatBad, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.NotCollected };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatBad, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.Correct };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatCollect, (int)GotStatus.Corrupt] = new List<RepStatus> { RepStatus.Corrupt, RepStatus.MoveToCorrupt, RepStatus.CorruptCanBeFixed };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatCollect, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.Correct };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatCollect, (int)GotStatus.FileLocked] = new List<RepStatus> { RepStatus.UnScanned };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatCollect, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Missing, RepStatus.CanBeFixed };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatMerged, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.UnNeeded, RepStatus.Delete, RepStatus.NeededForFix, RepStatus.Rename };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InDatMerged, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.NotCollected };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InToSort, (int)GotStatus.Corrupt] = new List<RepStatus> { RepStatus.Corrupt, RepStatus.Delete };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InToSort, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.InToSort, RepStatus.NeededForFix, RepStatus.Delete };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.InToSort, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.NotInDat, (int)GotStatus.Corrupt] = new List<RepStatus> { RepStatus.Corrupt, RepStatus.MoveToCorrupt, RepStatus.Delete };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.NotInDat, (int)GotStatus.Got] = new List<RepStatus> { RepStatus.Unknown, RepStatus.Delete, RepStatus.MoveToSort, RepStatus.NeededForFix, RepStatus.Rename };
StatusCheck[(int)FileType.SevenZipFile, (int)DatStatus.NotInDat, (int)GotStatus.NotGot] = new List<RepStatus> { RepStatus.Deleted };
DisplayOrder = new[]
{
RepStatus.Error,
@@ -169,7 +198,7 @@ namespace ROMVault2
tBase.RepStatusReset();
FileType ftBase = tBase.FileType;
if (ftBase != FileType.Zip && ftBase != FileType.Dir) return;
if (ftBase != FileType.Zip && ftBase != FileType.SevenZip && ftBase != FileType.Dir) return;
RvDir tDir = (RvDir)tBase;

View File

@@ -13,7 +13,7 @@ namespace ROMVault2.RvDB
{
public enum DatStatus { InDatCollect, InDatMerged, InDatBad, NotInDat, InToSort }
public enum GotStatus { NotGot, Got, Corrupt, FileLocked }
public enum FileType { Unknown, Dir, Zip, xSevenZip, xRAR, File, ZipFile, xSevenZipFile }
public enum FileType { Unknown, Dir, Zip, SevenZip, xRAR, File, ZipFile, SevenZipFile }
public abstract class RvBase
{
@@ -184,7 +184,7 @@ namespace ROMVault2.RvDB
switch (FileType)
{
case FileType.Zip: return ".zip";
//case FileType.SevenZip: return ".7z";
case FileType.SevenZip: return ".7z";
//case FileType.RAR: return ".rar";
}
return "";

View File

@@ -26,7 +26,7 @@ namespace ROMVault2.RvDB
public RvDir(FileType type)
: base(type)
{
if (type != FileType.Dir && type != FileType.Zip)
if (type != FileType.Dir && type != FileType.Zip && type !=FileType.SevenZip)
ReportError.SendAndShow("Trying to set Dir type to " + type);
}

View File

@@ -32,7 +32,7 @@ namespace ROMVault2.RvDB
public RvFile(FileType type)
: base(type)
{
if (type != FileType.File && type != FileType.ZipFile)
if (type != FileType.File && type != FileType.ZipFile && type != FileType.SevenZipFile)
ReportError.SendAndShow("Trying to set file type to " + type);
}

View File

@@ -0,0 +1,31 @@
using System;
using TrrntSevenZip.IO;
namespace TrrntSevenZip.SupportedFiles
{
public static class DirUtil
{
public static void CreateDirForFile(string sFilename)
{
string strTemp = Path.GetDirectoryName(sFilename);
if (String.IsNullOrEmpty(strTemp)) return;
if (Directory.Exists(strTemp)) return;
while (strTemp.Length > 0 && !Directory.Exists(strTemp))
{
int pos = strTemp.LastIndexOf(Path.DirectorySeparatorChar);
if (pos < 0) pos = 0;
strTemp = strTemp.Substring(0, pos);
}
while (sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1) > 0)
{
strTemp = sFilename.Substring(0, sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1));
Directory.CreateDirectory(strTemp);
}
}
}
}

View File

@@ -0,0 +1,40 @@
using System.IO;
namespace ROMVault2.SupportedFiles
{
public interface ICompress
{
int LocalFilesCount();
string Filename(int i);
ulong? LocalHeader(int i);
ulong UncompressedSize(int i);
byte[] CRC32(int i);
ZipReturn FileStatus(int i);
byte[] MD5(int i);
byte[] SHA1(int i);
ZipOpenType ZipOpen { get; }
ZipReturn ZipFileOpen(string newFilename, long timestamp, bool readHeaders);
void ZipFileClose();
ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, out Stream stream);
ZipReturn ZipFileCloseReadStream();
void DeepScan();
ZipStatus ZipStatus { get; }
string ZipFilename { get; }
long TimeStamp { get; }
void ZipFileAddDirectory();
ZipReturn ZipFileCreate(string newFilename);
ZipReturn ZipFileCloseWriteStream(byte[] crc32);
ZipReturn ZipFileRollBack();
void ZipFileCloseFailed();
}
}

View File

@@ -0,0 +1,55 @@
// Common/CRC.cs
namespace ROMVault2.SupportedFiles.SevenZip.Common
{
public class CRC
{
public static readonly uint[] Table;
static CRC()
{
Table = new uint[256];
const uint kPoly = 0xEDB88320;
for (uint i = 0; i < 256; i++)
{
uint r = i;
for (int j = 0; j < 8; j++)
if ((r & 1) != 0)
r = (r >> 1) ^ kPoly;
else
r >>= 1;
Table[i] = r;
}
}
uint _value = 0xFFFFFFFF;
public void Init() { _value = 0xFFFFFFFF; }
public void UpdateByte(byte b)
{
_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
}
public void Update(byte[] data, uint offset, uint size)
{
for (uint i = 0; i < size; i++)
_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
}
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
public static uint CalculateDigest(byte[] data, uint offset, uint size)
{
CRC crc = new CRC();
// crc.Init();
crc.Update(data, offset, size);
return crc.GetDigest();
}
public static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
{
return (CalculateDigest(data, offset, size) == digest);
}
}
}

View File

@@ -0,0 +1,157 @@
// ICoder.h
using System;
namespace ROMVault2.SupportedFiles.SevenZip.Common
{
/// <summary>
/// The exception that is thrown when an error in input stream occurs during decoding.
/// </summary>
class DataErrorException : ApplicationException
{
public DataErrorException(): base("Data Error") { }
}
/// <summary>
/// The exception that is thrown when the value of an argument is outside the allowable range.
/// </summary>
class InvalidParamException : ApplicationException
{
public InvalidParamException(): base("Invalid Parameter") { }
}
public interface ICodeProgress
{
/// <summary>
/// Callback progress.
/// </summary>
/// <param name="inSize">
/// input size. -1 if unknown.
/// </param>
/// <param name="outSize">
/// output size. -1 if unknown.
/// </param>
void SetProgress(Int64 inSize, Int64 outSize);
};
public interface ICoder
{
/// <summary>
/// Codes streams.
/// </summary>
/// <param name="inStream">
/// input Stream.
/// </param>
/// <param name="outStream">
/// output Stream.
/// </param>
/// <param name="inSize">
/// input Size. -1 if unknown.
/// </param>
/// <param name="outSize">
/// output Size. -1 if unknown.
/// </param>
/// <param name="progress">
/// callback progress reference.
/// </param>
/// <exception cref="DataErrorException">
/// if input stream is not valid
/// </exception>
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress);
};
/*
public interface ICoder2
{
void Code(ISequentialInStream []inStreams,
const UInt64 []inSizes,
ISequentialOutStream []outStreams,
UInt64 []outSizes,
ICodeProgress progress);
};
*/
/// <summary>
/// Provides the fields that represent properties idenitifiers for compressing.
/// </summary>
public enum CoderPropID
{
/// <summary>
/// Specifies default property.
/// </summary>
DefaultProp = 0,
/// <summary>
/// Specifies size of dictionary.
/// </summary>
DictionarySize,
/// <summary>
/// Specifies size of memory for PPM*.
/// </summary>
UsedMemorySize,
/// <summary>
/// Specifies order for PPM methods.
/// </summary>
Order,
/// <summary>
/// Specifies Block Size.
/// </summary>
BlockSize,
/// <summary>
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
/// </summary>
PosStateBits,
/// <summary>
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
/// </summary>
LitContextBits,
/// <summary>
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
/// </summary>
LitPosBits,
/// <summary>
/// Specifies number of fast bytes for LZ*.
/// </summary>
NumFastBytes,
/// <summary>
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
/// </summary>
MatchFinder,
/// <summary>
/// Specifies the number of match finder cyckes.
/// </summary>
MatchFinderCycles,
/// <summary>
/// Specifies number of passes.
/// </summary>
NumPasses,
/// <summary>
/// Specifies number of algorithm.
/// </summary>
Algorithm,
/// <summary>
/// Specifies the number of threads.
/// </summary>
NumThreads,
/// <summary>
/// Specifies mode with end marker.
/// </summary>
EndMarker
};
public interface ISetCoderProperties
{
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
};
public interface IWriteCoderProperties
{
void WriteCoderProperties(System.IO.Stream outStream);
}
public interface ISetDecoderProperties
{
void SetDecoderProperties(byte[] properties);
}
}

View File

@@ -0,0 +1,24 @@
// IMatchFinder.cs
using System;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.LZ
{
interface IInWindowStream
{
void SetStream(System.IO.Stream inStream);
void Init();
void ReleaseStream();
Byte GetIndexByte(Int32 index);
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
UInt32 GetNumAvailableBytes();
}
interface IMatchFinder : IInWindowStream
{
void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
UInt32 GetMatches(UInt32[] distances);
void Skip(UInt32 num);
}
}

View File

@@ -0,0 +1,368 @@
// LzBinTree.cs
using System;
using ROMVault2.SupportedFiles.SevenZip.Common;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.LZ
{
public class BinTree : InWindow, IMatchFinder
{
UInt32 _cyclicBufferPos;
UInt32 _cyclicBufferSize = 0;
UInt32 _matchMaxLen;
UInt32[] _son;
UInt32[] _hash;
UInt32 _cutValue = 0xFF;
UInt32 _hashMask;
UInt32 _hashSizeSum = 0;
bool HASH_ARRAY = true;
const UInt32 kHash2Size = 1 << 10;
const UInt32 kHash3Size = 1 << 16;
const UInt32 kBT2HashSize = 1 << 16;
const UInt32 kStartMaxLen = 1;
const UInt32 kHash3Offset = kHash2Size;
const UInt32 kEmptyHashValue = 0;
const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
UInt32 kNumHashDirectBytes = 0;
UInt32 kMinMatchCheck = 4;
UInt32 kFixHashSize = kHash2Size + kHash3Size;
public void SetType(int numHashBytes)
{
HASH_ARRAY = (numHashBytes > 2);
if (HASH_ARRAY)
{
kNumHashDirectBytes = 0;
kMinMatchCheck = 4;
kFixHashSize = kHash2Size + kHash3Size;
}
else
{
kNumHashDirectBytes = 2;
kMinMatchCheck = 2 + 1;
kFixHashSize = 0;
}
}
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
public new void ReleaseStream() { base.ReleaseStream(); }
public new void Init()
{
base.Init();
for (UInt32 i = 0; i < _hashSizeSum; i++)
_hash[i] = kEmptyHashValue;
_cyclicBufferPos = 0;
ReduceOffsets(-1);
}
public new void MovePos()
{
if (++_cyclicBufferPos >= _cyclicBufferSize)
_cyclicBufferPos = 0;
base.MovePos();
if (_pos == kMaxValForNormalize)
Normalize();
}
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{ return base.GetMatchLen(index, distance, limit); }
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
{
if (historySize > kMaxValForNormalize - 256)
throw new Exception();
_cutValue = 16 + (matchMaxLen >> 1);
UInt32 windowReservSize = (historySize + keepAddBufferBefore +
matchMaxLen + keepAddBufferAfter) / 2 + 256;
base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
_matchMaxLen = matchMaxLen;
UInt32 cyclicBufferSize = historySize + 1;
if (_cyclicBufferSize != cyclicBufferSize)
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
UInt32 hs = kBT2HashSize;
if (HASH_ARRAY)
{
hs = historySize - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF;
if (hs > (1 << 24))
hs >>= 1;
_hashMask = hs;
hs++;
hs += kFixHashSize;
}
if (hs != _hashSizeSum)
_hash = new UInt32[_hashSizeSum = hs];
}
public UInt32 GetMatches(UInt32[] distances)
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if (lenLimit < kMinMatchCheck)
{
MovePos();
return 0;
}
}
UInt32 offset = 0;
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
UInt32 cur = _bufferOffset + _pos;
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
UInt32 hashValue, hash2Value = 0, hash3Value = 0;
if (HASH_ARRAY)
{
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
hash2Value = temp & (kHash2Size - 1);
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
hash3Value = temp & (kHash3Size - 1);
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
}
else
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
UInt32 curMatch = _hash[kFixHashSize + hashValue];
if (HASH_ARRAY)
{
UInt32 curMatch2 = _hash[hash2Value];
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
_hash[hash2Value] = _pos;
_hash[kHash3Offset + hash3Value] = _pos;
if (curMatch2 > matchMinPos)
if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
{
distances[offset++] = maxLen = 2;
distances[offset++] = _pos - curMatch2 - 1;
}
if (curMatch3 > matchMinPos)
if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
{
if (curMatch3 == curMatch2)
offset -= 2;
distances[offset++] = maxLen = 3;
distances[offset++] = _pos - curMatch3 - 1;
curMatch2 = curMatch3;
}
if (offset != 0 && curMatch2 == curMatch)
{
offset -= 2;
maxLen = kStartMaxLen;
}
}
_hash[kFixHashSize + hashValue] = _pos;
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
UInt32 ptr1 = (_cyclicBufferPos << 1);
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
if (kNumHashDirectBytes != 0)
{
if (curMatch > matchMinPos)
{
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
_bufferBase[cur + kNumHashDirectBytes])
{
distances[offset++] = maxLen = kNumHashDirectBytes;
distances[offset++] = _pos - curMatch - 1;
}
}
}
UInt32 count = _cutValue;
while(true)
{
if(curMatch <= matchMinPos || count-- == 0)
{
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
break;
}
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
UInt32 pby1 = _bufferOffset + curMatch;
UInt32 len = Math.Min(len0, len1);
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
{
while(++len != lenLimit)
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
break;
if (maxLen < len)
{
distances[offset++] = maxLen = len;
distances[offset++] = delta - 1;
if (len == lenLimit)
{
_son[ptr1] = _son[cyclicPos];
_son[ptr0] = _son[cyclicPos + 1];
break;
}
}
}
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
{
_son[ptr1] = curMatch;
ptr1 = cyclicPos + 1;
curMatch = _son[ptr1];
len1 = len;
}
else
{
_son[ptr0] = curMatch;
ptr0 = cyclicPos;
curMatch = _son[ptr0];
len0 = len;
}
}
MovePos();
return offset;
}
public void Skip(UInt32 num)
{
do
{
UInt32 lenLimit;
if (_pos + _matchMaxLen <= _streamPos)
lenLimit = _matchMaxLen;
else
{
lenLimit = _streamPos - _pos;
if (lenLimit < kMinMatchCheck)
{
MovePos();
continue;
}
}
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
UInt32 cur = _bufferOffset + _pos;
UInt32 hashValue;
if (HASH_ARRAY)
{
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
UInt32 hash2Value = temp & (kHash2Size - 1);
_hash[hash2Value] = _pos;
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
UInt32 hash3Value = temp & (kHash3Size - 1);
_hash[kHash3Offset + hash3Value] = _pos;
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
}
else
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
UInt32 curMatch = _hash[kFixHashSize + hashValue];
_hash[kFixHashSize + hashValue] = _pos;
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
UInt32 ptr1 = (_cyclicBufferPos << 1);
UInt32 len0, len1;
len0 = len1 = kNumHashDirectBytes;
UInt32 count = _cutValue;
while (true)
{
if (curMatch <= matchMinPos || count-- == 0)
{
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
break;
}
UInt32 delta = _pos - curMatch;
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
(_cyclicBufferPos - delta) :
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
UInt32 pby1 = _bufferOffset + curMatch;
UInt32 len = Math.Min(len0, len1);
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
{
while (++len != lenLimit)
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
break;
if (len == lenLimit)
{
_son[ptr1] = _son[cyclicPos];
_son[ptr0] = _son[cyclicPos + 1];
break;
}
}
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
{
_son[ptr1] = curMatch;
ptr1 = cyclicPos + 1;
curMatch = _son[ptr1];
len1 = len;
}
else
{
_son[ptr0] = curMatch;
ptr0 = cyclicPos;
curMatch = _son[ptr0];
len0 = len;
}
}
MovePos();
}
while (--num != 0);
}
void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
{
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 value = items[i];
if (value <= subValue)
value = kEmptyHashValue;
else
value -= subValue;
items[i] = value;
}
}
void Normalize()
{
UInt32 subValue = _pos - _cyclicBufferSize;
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
NormalizeLinks(_hash, _hashSizeSum, subValue);
ReduceOffsets((Int32)subValue);
}
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
}
}

View File

@@ -0,0 +1,132 @@
// LzInWindow.cs
using System;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.LZ
{
public class InWindow
{
public Byte[] _bufferBase = null; // pointer to buffer with data
System.IO.Stream _stream;
UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
UInt32 _pointerToLastSafePosition;
public UInt32 _bufferOffset;
public UInt32 _blockSize; // Size of Allocated memory block
public UInt32 _pos; // offset (from _buffer) of curent byte
UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
public void MoveBlock()
{
UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0)
offset--;
UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
// check negative offset ????
for (UInt32 i = 0; i < numBytes; i++)
_bufferBase[i] = _bufferBase[offset + i];
_bufferOffset -= offset;
}
public virtual void ReadBlock()
{
if (_streamEndWasReached)
return;
while (true)
{
int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
if (size == 0)
return;
int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
if (numReadBytes == 0)
{
_posLimit = _streamPos;
UInt32 pointerToPostion = _bufferOffset + _posLimit;
if (pointerToPostion > _pointerToLastSafePosition)
_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
_streamEndWasReached = true;
return;
}
_streamPos += (UInt32)numReadBytes;
if (_streamPos >= _pos + _keepSizeAfter)
_posLimit = _streamPos - _keepSizeAfter;
}
}
void Free() { _bufferBase = null; }
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
{
_keepSizeBefore = keepSizeBefore;
_keepSizeAfter = keepSizeAfter;
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
if (_bufferBase == null || _blockSize != blockSize)
{
Free();
_blockSize = blockSize;
_bufferBase = new Byte[_blockSize];
}
_pointerToLastSafePosition = _blockSize - keepSizeAfter;
}
public void SetStream(System.IO.Stream stream) { _stream = stream; }
public void ReleaseStream() { _stream = null; }
public void Init()
{
_bufferOffset = 0;
_pos = 0;
_streamPos = 0;
_streamEndWasReached = false;
ReadBlock();
}
public void MovePos()
{
_pos++;
if (_pos > _posLimit)
{
UInt32 pointerToPostion = _bufferOffset + _pos;
if (pointerToPostion > _pointerToLastSafePosition)
MoveBlock();
ReadBlock();
}
}
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
// index + limit have not to exceed _keepSizeAfter;
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
{
if (_streamEndWasReached)
if ((_pos + index) + limit > _streamPos)
limit = _streamPos - (UInt32)(_pos + index);
distance++;
// Byte *pby = _buffer + (size_t)_pos + index;
UInt32 pby = _bufferOffset + _pos + (UInt32)index;
UInt32 i;
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
return i;
}
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
public void ReduceOffsets(Int32 subValue)
{
_bufferOffset += (UInt32)subValue;
_posLimit -= (UInt32)subValue;
_pos -= (UInt32)subValue;
_streamPos -= (UInt32)subValue;
}
}
}

View File

@@ -0,0 +1,135 @@
// LzOutWindow.cs
namespace ROMVault2.SupportedFiles.SevenZip.Compress.LZ
{
public class OutWindow
{
byte[] _buffer = null;
uint _pos;
uint _windowSize = 0;
uint _streamPos;
System.IO.Stream _stream;
public uint TrainSize = 0;
public void Create(uint windowSize)
{
if (_windowSize != windowSize)
{
// System.GC.Collect();
_buffer = new byte[windowSize];
}
_windowSize = windowSize;
_pos = 0;
_streamPos = 0;
}
public void Init(System.IO.Stream stream, bool solid)
{
ReleaseStream();
_stream = stream;
if (!solid)
{
_streamPos = 0;
_pos = 0;
TrainSize = 0;
}
}
public bool Train(System.IO.Stream stream)
{
long len = stream.Length;
uint size = (len < _windowSize) ? (uint)len : _windowSize;
TrainSize = size;
stream.Position = len - size;
_streamPos = _pos = 0;
while (size > 0)
{
uint curSize = _windowSize - _pos;
if (size < curSize)
curSize = size;
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
if (numReadBytes == 0)
return false;
size -= (uint)numReadBytes;
_pos += (uint)numReadBytes;
_streamPos += (uint)numReadBytes;
if (_pos == _windowSize)
_streamPos = _pos = 0;
}
return true;
}
public void ReleaseStream()
{
Flush();
_stream = null;
}
public void Flush()
{
uint size = _pos - _streamPos;
if (size == 0)
return;
if (_stream != null)
_stream.Write(_buffer, (int)_streamPos, (int)size);
if (_pos >= _windowSize)
_pos = 0;
_streamPos = _pos;
}
public void CopyBlock(uint distance, uint len)
{
uint l = 0;
uint pos = _pos - distance - 1;
if (pos >= _windowSize)
pos += _windowSize;
for (; len > 0; len--)
{
if (pos >= _windowSize)
pos = 0;
_buffer[_pos++] = _buffer[pos++];
if (_pos >= _windowSize)
Flush();
}
}
public void CopyBlockRetBlock(uint distance, uint len, ref byte[] outbuffer)
{
if (outbuffer == null || outbuffer.Length < len)
outbuffer=new byte[len];
uint l = 0;
uint pos = _pos - distance - 1;
if (pos >= _windowSize)
pos += _windowSize;
for (; len > 0; len--)
{
if (pos >= _windowSize)
pos = 0;
outbuffer[l++] = _buffer[pos];
_buffer[_pos++] = _buffer[pos++];
if (_pos >= _windowSize)
Flush();
}
}
public void PutByte(byte b)
{
_buffer[_pos++] = b;
if (_pos >= _windowSize)
Flush();
}
public byte GetByte(uint distance)
{
uint pos = _pos - distance - 1;
if (pos >= _windowSize)
pos += _windowSize;
return _buffer[pos];
}
}
}

View File

@@ -0,0 +1,76 @@
// LzmaBase.cs
namespace ROMVault2.SupportedFiles.SevenZip.Compress.LZMA
{
internal abstract class Base
{
public const uint kNumRepDistances = 4;
public const uint kNumStates = 12;
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
public struct State
{
public uint Index;
public void Init() { Index = 0; }
public void UpdateChar()
{
if (Index < 4) Index = 0;
else if (Index < 10) Index -= 3;
else Index -= 6;
}
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
public bool IsCharState() { return Index < 7; }
}
public const int kNumPosSlotBits = 6;
public const int kDicLogSizeMin = 0;
// public const int kDicLogSizeMax = 30;
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
public const uint kMatchMinLen = 2;
public static uint GetLenToPosState(uint len)
{
len -= kMatchMinLen;
if (len < kNumLenToPosStates)
return len;
return (uint)(kNumLenToPosStates - 1);
}
public const int kNumAlignBits = 4;
public const uint kAlignTableSize = 1 << kNumAlignBits;
public const uint kAlignMask = (kAlignTableSize - 1);
public const uint kStartPosModelIndex = 4;
public const uint kEndPosModelIndex = 14;
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
public const uint kNumLitPosStatesBitsEncodingMax = 4;
public const uint kNumLitContextBitsMax = 8;
public const int kNumPosStatesBitsMax = 4;
public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
public const int kNumPosStatesBitsEncodingMax = 4;
public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
public const int kNumLowLenBits = 3;
public const int kNumMidLenBits = 3;
public const int kNumHighLenBits = 8;
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
(1 << kNumHighLenBits);
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
}
}

View File

@@ -0,0 +1,597 @@
// LzmaDecoder.cs
using System;
using System.IO;
using ROMVault2.SupportedFiles.SevenZip.Common;
using ROMVault2.SupportedFiles.SevenZip.Compress.RangeCoder;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.LZMA
{
public class Decoder : Stream, ICoder, ISetDecoderProperties
{
class LenDecoder
{
BitDecoder m_Choice = new BitDecoder();
BitDecoder m_Choice2 = new BitDecoder();
BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
uint m_NumPosStates = 0;
public void Create(uint numPosStates)
{
for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
{
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
}
m_NumPosStates = numPosStates;
}
public void Init()
{
m_Choice.Init();
for (uint posState = 0; posState < m_NumPosStates; posState++)
{
m_LowCoder[posState].Init();
m_MidCoder[posState].Init();
}
m_Choice2.Init();
m_HighCoder.Init();
}
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
{
if (m_Choice.Decode(rangeDecoder) == 0)
return m_LowCoder[posState].Decode(rangeDecoder);
else
{
uint symbol = Base.kNumLowLenSymbols;
if (m_Choice2.Decode(rangeDecoder) == 0)
symbol += m_MidCoder[posState].Decode(rangeDecoder);
else
{
symbol += Base.kNumMidLenSymbols;
symbol += m_HighCoder.Decode(rangeDecoder);
}
return symbol;
}
}
}
class LiteralDecoder
{
struct Decoder2
{
BitDecoder[] m_Decoders;
public void Create() { m_Decoders = new BitDecoder[0x300]; }
public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
{
uint symbol = 1;
do
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
while (symbol < 0x100);
return (byte)symbol;
}
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
{
uint symbol = 1;
do
{
uint matchBit = (uint)(matchByte >> 7) & 1;
matchByte <<= 1;
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
symbol = (symbol << 1) | bit;
if (matchBit != bit)
{
while (symbol < 0x100)
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
break;
}
}
while (symbol < 0x100);
return (byte)symbol;
}
}
Decoder2[] m_Coders;
int m_NumPrevBits;
int m_NumPosBits;
uint m_PosMask;
public void Create(int numPosBits, int numPrevBits)
{
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
m_NumPosBits == numPosBits)
return;
m_NumPosBits = numPosBits;
m_PosMask = ((uint)1 << numPosBits) - 1;
m_NumPrevBits = numPrevBits;
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
m_Coders = new Decoder2[numStates];
for (uint i = 0; i < numStates; i++)
m_Coders[i].Create();
}
public void Init()
{
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
for (uint i = 0; i < numStates; i++)
m_Coders[i].Init();
}
uint GetState(uint pos, byte prevByte)
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
};
LZ.OutWindow m_OutWindow = new LZ.OutWindow();
RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();
BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
LenDecoder m_LenDecoder = new LenDecoder();
LenDecoder m_RepLenDecoder = new LenDecoder();
LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
uint m_DictionarySize;
uint m_DictionarySizeCheck;
uint m_PosStateMask;
public Decoder()
{
m_DictionarySize = 0xFFFFFFFF;
for (int i = 0; i < Base.kNumLenToPosStates; i++)
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
}
void SetDictionarySize(uint dictionarySize)
{
if (m_DictionarySize != dictionarySize)
{
m_DictionarySize = dictionarySize;
m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));
m_OutWindow.Create(blockSize);
}
}
void SetLiteralProperties(int lp, int lc)
{
if (lp > 8)
throw new InvalidParamException();
if (lc > 8)
throw new InvalidParamException();
m_LiteralDecoder.Create(lp, lc);
}
void SetPosBitsProperties(int pb)
{
if (pb > Base.kNumPosStatesBitsMax)
throw new InvalidParamException();
uint numPosStates = (uint)1 << pb;
m_LenDecoder.Create(numPosStates);
m_RepLenDecoder.Create(numPosStates);
m_PosStateMask = numPosStates - 1;
}
bool _solid = false;
void Init(Stream inStream, Stream outStream)
{
m_RangeDecoder.Init(inStream);
m_OutWindow.Init(outStream, _solid);
uint i;
for (i = 0; i < Base.kNumStates; i++)
{
for (uint j = 0; j <= m_PosStateMask; j++)
{
uint index = (i << Base.kNumPosStatesBitsMax) + j;
m_IsMatchDecoders[index].Init();
m_IsRep0LongDecoders[index].Init();
}
m_IsRepDecoders[i].Init();
m_IsRepG0Decoders[i].Init();
m_IsRepG1Decoders[i].Init();
m_IsRepG2Decoders[i].Init();
}
m_LiteralDecoder.Init();
for (i = 0; i < Base.kNumLenToPosStates; i++)
m_PosSlotDecoder[i].Init();
// m_PosSpecDecoder.Init();
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
m_PosDecoders[i].Init();
m_LenDecoder.Init();
m_RepLenDecoder.Init();
m_PosAlignDecoder.Init();
}
public void Code(Stream inStream, Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress)
{
Init(inStream, outStream);
Base.State state = new Base.State();
state.Init();
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
UInt64 nowPos64 = 0;
UInt64 outSize64 = (UInt64)outSize;
if (nowPos64 < outSize64)
{
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
throw new DataErrorException();
state.UpdateChar();
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
m_OutWindow.PutByte(b);
nowPos64++;
}
while (nowPos64 < outSize64)
{
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
// while(nowPos64 < next)
{
uint posState = (uint)nowPos64 & m_PosStateMask;
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
{
byte b;
byte prevByte = m_OutWindow.GetByte(0);
if (!state.IsCharState())
b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
else
b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
m_OutWindow.PutByte(b);
state.UpdateChar();
nowPos64++;
}
else
{
uint len;
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
{
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
{
state.UpdateShortRep();
m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
nowPos64++;
continue;
}
}
else
{
UInt32 distance;
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{
distance = rep1;
}
else
{
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
distance = rep2;
else
{
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
state.UpdateRep();
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
state.UpdateMatch();
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
if (posSlot >= Base.kStartPosModelIndex)
{
int numDirectBits = (int)((posSlot >> 1) - 1);
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
if (posSlot < Base.kEndPosModelIndex)
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
else
{
rep0 += (m_RangeDecoder.DecodeDirectBits(
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
}
}
else
rep0 = posSlot;
}
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
{
if (rep0 == 0xFFFFFFFF)
break;
throw new DataErrorException();
}
m_OutWindow.CopyBlock(rep0, len);
nowPos64 += len;
}
}
}
m_OutWindow.Flush();
m_OutWindow.ReleaseStream();
m_RangeDecoder.ReleaseStream();
}
public void SetDecoderProperties(byte[] properties)
{
if (properties.Length < 5)
throw new InvalidParamException();
int lc = properties[0] % 9;
int remainder = properties[0] / 9;
int lp = remainder % 5;
int pb = remainder / 5;
if (pb > Base.kNumPosStatesBitsMax)
throw new InvalidParamException();
UInt32 dictionarySize = 0;
for (int i = 0; i < 4; i++)
dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
SetDictionarySize(dictionarySize);
SetLiteralProperties(lp, lc);
SetPosBitsProperties(pb);
}
public bool Train(System.IO.Stream stream)
{
_solid = true;
return m_OutWindow.Train(stream);
}
private Base.State state;
private uint rep0, rep1, rep2, rep3;
private UInt64 nowPos64;
private bool init;
private byte[] outbuffer;
private uint outbufferpos;
private uint outbufferlen;
private uint totalout;
public void SetUpStream(Stream inStream)
{
Init(inStream, null);
state = new Base.State();
state.Init();
rep0 = 0;
rep1 = 0;
rep2 = 0;
rep3 = 0;
nowPos64 = 0;
init = false;
outbufferpos = 0;
outbufferlen = 0;
totalout = 0;
}
public void ReleaseStream()
{
m_RangeDecoder.ReleaseStream();
}
private void GetNextBytes()
{
if (!init)
{
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
throw new DataErrorException();
state.UpdateChar();
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
m_OutWindow.PutByte(b);
nowPos64++;
init = true;
outbuffer=new byte[1];
outbuffer[0] = b;
outbufferlen = 1;
return;
}
uint posState = (uint)nowPos64 & m_PosStateMask;
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
{
byte b;
byte prevByte = m_OutWindow.GetByte(0);
if (!state.IsCharState())
b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
else
b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
m_OutWindow.PutByte(b);
state.UpdateChar();
nowPos64++;
outbuffer[0] = b;
outbufferlen = 1;
return;
}
uint len;
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
{
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
{
state.UpdateShortRep();
byte b = m_OutWindow.GetByte(rep0);
m_OutWindow.PutByte(b);
nowPos64++;
outbuffer[0] = b;
outbufferlen = 1;
return;
}
}
else
{
UInt32 distance;
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
{
distance = rep1;
}
else
{
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
distance = rep2;
else
{
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
state.UpdateRep();
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
state.UpdateMatch();
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
if (posSlot >= Base.kStartPosModelIndex)
{
int numDirectBits = (int)((posSlot >> 1) - 1);
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
if (posSlot < Base.kEndPosModelIndex)
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
else
{
rep0 += (m_RangeDecoder.DecodeDirectBits(
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
}
}
else
rep0 = posSlot;
}
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
{
if (rep0 == 0xFFFFFFFF)
return;
throw new DataErrorException();
}
m_OutWindow.CopyBlockRetBlock(rep0, len, ref outbuffer);
outbufferlen = len;
nowPos64 += len;
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
for (int i = 0; i < offset; i++)
{
if (outbufferpos == outbufferlen)
{
GetNextBytes();
outbufferpos = 0;
}
outbufferpos++;
totalout++;
}
return totalout;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
for (int i = 0; i < count; i++)
{
if (outbufferpos == outbufferlen)
{
GetNextBytes();
outbufferpos = 0;
}
buffer[offset + i] = outbuffer[outbufferpos++];
totalout++;
}
return count;
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { throw new NotImplementedException(); }
}
public override long Position
{
get { return totalout; }
set { }
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
using System;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.RangeCoder
{
class Encoder
{
public const uint kTopValue = (1 << 24);
System.IO.Stream Stream;
public UInt64 Low;
public uint Range;
uint _cacheSize;
byte _cache;
long StartPosition;
public void SetStream(System.IO.Stream stream)
{
Stream = stream;
}
public void ReleaseStream()
{
Stream = null;
}
public void Init()
{
StartPosition = Stream.Position;
Low = 0;
Range = 0xFFFFFFFF;
_cacheSize = 1;
_cache = 0;
}
public void FlushData()
{
for (int i = 0; i < 5; i++)
ShiftLow();
}
public void FlushStream()
{
Stream.Flush();
}
public void CloseStream()
{
Stream.Close();
}
public void Encode(uint start, uint size, uint total)
{
Low += start * (Range /= total);
Range *= size;
while (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
public void ShiftLow()
{
if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
{
byte temp = _cache;
do
{
Stream.WriteByte((byte)(temp + (Low >> 32)));
temp = 0xFF;
}
while (--_cacheSize != 0);
_cache = (byte)(((uint)Low) >> 24);
}
_cacheSize++;
Low = ((uint)Low) << 8;
}
public void EncodeDirectBits(uint v, int numTotalBits)
{
for (int i = numTotalBits - 1; i >= 0; i--)
{
Range >>= 1;
if (((v >> i) & 1) == 1)
Low += Range;
if (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
}
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
{
uint newBound = (Range >> numTotalBits) * size0;
if (symbol == 0)
Range = newBound;
else
{
Low += newBound;
Range -= newBound;
}
while (Range < kTopValue)
{
Range <<= 8;
ShiftLow();
}
}
public long GetProcessedSizeAdd()
{
return _cacheSize +
Stream.Position - StartPosition + 4;
// (long)Stream.GetProcessedSize();
}
}
class Decoder
{
public const uint kTopValue = (1 << 24);
public uint Range;
public uint Code;
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
public System.IO.Stream Stream;
public void Init(System.IO.Stream stream)
{
// Stream.Init(stream);
Stream = stream;
Code = 0;
Range = 0xFFFFFFFF;
for (int i = 0; i < 5; i++)
Code = (Code << 8) | (byte)Stream.ReadByte();
}
public void ReleaseStream()
{
// Stream.ReleaseStream();
Stream = null;
}
public void CloseStream()
{
Stream.Close();
}
public void Normalize()
{
while (Range < kTopValue)
{
Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8;
}
}
public void Normalize2()
{
if (Range < kTopValue)
{
Code = (Code << 8) | (byte)Stream.ReadByte();
Range <<= 8;
}
}
public uint GetThreshold(uint total)
{
return Code / (Range /= total);
}
public void Decode(uint start, uint size, uint total)
{
Code -= start * Range;
Range *= size;
Normalize();
}
public uint DecodeDirectBits(int numTotalBits)
{
uint range = Range;
uint code = Code;
uint result = 0;
for (int i = numTotalBits; i > 0; i--)
{
range >>= 1;
/*
result <<= 1;
if (code >= range)
{
code -= range;
result |= 1;
}
*/
uint t = (code - range) >> 31;
code -= range & (t - 1);
result = (result << 1) | (1 - t);
if (range < kTopValue)
{
code = (code << 8) | (byte)Stream.ReadByte();
range <<= 8;
}
}
Range = range;
Code = code;
return result;
}
public uint DecodeBit(uint size0, int numTotalBits)
{
uint newBound = (Range >> numTotalBits) * size0;
uint symbol;
if (Code < newBound)
{
symbol = 0;
Range = newBound;
}
else
{
symbol = 1;
Code -= newBound;
Range -= newBound;
}
Normalize();
return symbol;
}
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
}
}

View File

@@ -0,0 +1,117 @@
using System;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.RangeCoder
{
struct BitEncoder
{
public const int kNumBitModelTotalBits = 11;
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
const int kNumMoveBits = 5;
const int kNumMoveReducingBits = 2;
public const int kNumBitPriceShiftBits = 6;
uint Prob;
public void Init() { Prob = kBitModelTotal >> 1; }
public void UpdateModel(uint symbol)
{
if (symbol == 0)
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
else
Prob -= (Prob) >> kNumMoveBits;
}
public void Encode(Encoder encoder, uint symbol)
{
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
// UpdateModel(symbol);
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
if (symbol == 0)
{
encoder.Range = newBound;
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
}
else
{
encoder.Low += newBound;
encoder.Range -= newBound;
Prob -= (Prob) >> kNumMoveBits;
}
if (encoder.Range < Encoder.kTopValue)
{
encoder.Range <<= 8;
encoder.ShiftLow();
}
}
private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
static BitEncoder()
{
const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
for (int i = kNumBits - 1; i >= 0; i--)
{
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
UInt32 end = (UInt32)1 << (kNumBits - i);
for (UInt32 j = start; j < end; j++)
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
}
}
public uint GetPrice(uint symbol)
{
return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
}
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
}
struct BitDecoder
{
public const int kNumBitModelTotalBits = 11;
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
const int kNumMoveBits = 5;
uint Prob;
public void UpdateModel(int numMoveBits, uint symbol)
{
if (symbol == 0)
Prob += (kBitModelTotal - Prob) >> numMoveBits;
else
Prob -= (Prob) >> numMoveBits;
}
public void Init() { Prob = kBitModelTotal >> 1; }
public uint Decode(RangeCoder.Decoder rangeDecoder)
{
uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
if (rangeDecoder.Code < newBound)
{
rangeDecoder.Range = newBound;
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
if (rangeDecoder.Range < Decoder.kTopValue)
{
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
rangeDecoder.Range <<= 8;
}
return 0;
}
else
{
rangeDecoder.Range -= newBound;
rangeDecoder.Code -= newBound;
Prob -= (Prob) >> kNumMoveBits;
if (rangeDecoder.Range < Decoder.kTopValue)
{
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
rangeDecoder.Range <<= 8;
}
return 1;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using System;
namespace ROMVault2.SupportedFiles.SevenZip.Compress.RangeCoder
{
struct BitTreeEncoder
{
BitEncoder[] Models;
int NumBitLevels;
public BitTreeEncoder(int numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new BitEncoder[1 << numBitLevels];
}
public void Init()
{
for (uint i = 1; i < (1 << NumBitLevels); i++)
Models[i].Init();
}
public void Encode(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; )
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
}
}
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
{
UInt32 m = 1;
for (UInt32 i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
}
public UInt32 GetPrice(UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; )
{
bitIndex--;
UInt32 bit = (symbol >> bitIndex) & 1;
price += Models[m].GetPrice(bit);
m = (m << 1) + bit;
}
return price;
}
public UInt32 ReverseGetPrice(UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
price += Models[m].GetPrice(bit);
m = (m << 1) | bit;
}
return price;
}
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
int NumBitLevels, UInt32 symbol)
{
UInt32 price = 0;
UInt32 m = 1;
for (int i = NumBitLevels; i > 0; i--)
{
UInt32 bit = symbol & 1;
symbol >>= 1;
unchecked
{
price += Models[startIndex + m].GetPrice(bit);
}
m = (m << 1) | bit;
}
return price;
}
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
{
UInt32 m = 1;
for (int i = 0; i < NumBitLevels; i++)
{
UInt32 bit = symbol & 1;
Models[startIndex + m].Encode(rangeEncoder, bit);
m = (m << 1) | bit;
symbol >>= 1;
}
}
}
struct BitTreeDecoder
{
BitDecoder[] Models;
int NumBitLevels;
public BitTreeDecoder(int numBitLevels)
{
NumBitLevels = numBitLevels;
Models = new BitDecoder[1 << numBitLevels];
}
public void Init()
{
for (uint i = 1; i < (1 << NumBitLevels); i++)
Models[i].Init();
}
public uint Decode(RangeCoder.Decoder rangeDecoder)
{
uint m = 1;
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
m = (m << 1) + Models[m].Decode(rangeDecoder);
return m - ((uint)1 << NumBitLevels);
}
public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
{
uint m = 1;
uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
uint bit = Models[m].Decode(rangeDecoder);
m <<= 1;
m += bit;
symbol |= (bit << bitIndex);
}
return symbol;
}
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
RangeCoder.Decoder rangeDecoder, int NumBitLevels)
{
uint m = 1;
uint symbol = 0;
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
{
uint bit = Models[startIndex + m].Decode(rangeDecoder);
m <<= 1;
m += bit;
symbol |= (bit << bitIndex);
}
return symbol;
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using ROMVault2.IO;
namespace ROMVault2.SupportedFiles.SevenZip
{
public static class DirUtil
{
public static void CreateDirForFile(string sFilename)
{
string strTemp = Path.GetDirectoryName(sFilename);
if (String.IsNullOrEmpty(strTemp)) return;
if (Directory.Exists(strTemp)) return;
while (strTemp.Length > 0 && !Directory.Exists(strTemp))
{
int pos = strTemp.LastIndexOf(Path.DirectorySeparatorChar);
if (pos < 0) pos = 0;
strTemp = strTemp.Substring(0, pos);
}
while (sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1) > 0)
{
strTemp = sFilename.Substring(0, sFilename.IndexOf(Path.DirectorySeparatorChar, strTemp.Length + 1));
Directory.CreateDirectory(strTemp);
}
}
}
}

View File

@@ -0,0 +1,207 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Filters
{
public class BCJ2Filter : Stream
{
private Stream baseStream;
private byte[] input = new byte[4096];
private int inputOffset = 0;
private int inputCount = 0;
private bool endReached = false;
private long position = 0;
private byte[] output = new byte[4];
private int outputOffset = 0;
private int outputCount = 0;
private byte[] control;
private byte[] data1;
private byte[] data2;
private int controlPos = 0;
private int data1Pos = 0;
private int data2Pos = 0;
private ushort[] p = new ushort[256 + 2];
private uint range, code;
private byte prevByte = 0;
private const int kNumTopBits = 24;
private const int kTopValue = 1 << kNumTopBits;
private const int kNumBitModelTotalBits = 11;
private const int kBitModelTotal = 1 << kNumBitModelTotalBits;
private const int kNumMoveBits = 5;
private static bool IsJ(byte b0, byte b1)
{
return (b1 & 0xFE) == 0xE8 || IsJcc(b0, b1);
}
private static bool IsJcc(byte b0, byte b1)
{
return b0 == 0x0F && (b1 & 0xF0) == 0x80;
}
public BCJ2Filter(byte[] control, byte[] data1, byte[] data2, Stream baseStream)
{
this.control = control;
this.data1 = data1;
this.data2 = data2;
this.baseStream = baseStream;
int i;
for (i = 0; i < p.Length; i++)
p[i] = kBitModelTotal >> 1;
code = 0;
range = 0xFFFFFFFF;
for (i = 0; i < 5; i++)
code = (code << 8) | control[controlPos++];
}
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()
{
throw new NotImplementedException();
}
public override long Length
{
get { return baseStream.Length + data1.Length + data2.Length; }
}
public override long Position
{
get
{
return position;
}
set
{
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int size = 0;
byte b = 0;
while (!endReached && size < count)
{
while (outputOffset < outputCount)
{
b = output[outputOffset++];
buffer[offset++] = b;
size++;
position++;
prevByte = b;
if (size == count)
return size;
}
if (inputOffset == inputCount)
{
inputOffset = 0;
inputCount = baseStream.Read(input, 0, input.Length);
if (inputCount == 0)
{
endReached = true;
break;
}
}
b = input[inputOffset++];
buffer[offset++] = b;
size++;
position++;
if (!IsJ(prevByte, b))
prevByte = b;
else
{
int prob;
if (b == 0xE8)
prob = prevByte;
else if (b == 0xE9)
prob = 256;
else
prob = 257;
uint bound = (range >> kNumBitModelTotalBits) * p[prob];
if (code < bound)
{
range = bound;
p[prob] += (ushort)((kBitModelTotal - p[prob]) >> kNumMoveBits);
if (range < kTopValue)
{
range <<= 8;
code = (code << 8) | control[controlPos++];
}
prevByte = b;
}
else
{
range -= bound;
code -= bound;
p[prob] -= (ushort)(p[prob] >> kNumMoveBits);
if (range < kTopValue)
{
range <<= 8;
code = (code << 8) | control[controlPos++];
}
uint dest;
if (b == 0xE8)
dest = (uint)((data1[data1Pos++] << 24) | (data1[data1Pos++] << 16) | (data1[data1Pos++] << 8) | data1[data1Pos++]);
else
dest = (uint)((data2[data2Pos++] << 24) | (data2[data2Pos++] << 16) | (data2[data2Pos++] << 8) | data2[data2Pos++]);
dest -= (uint)(position + 4);
output[0] = (byte)dest;
output[1] = (byte)(dest >> 8);
output[2] = (byte)(dest >> 16);
output[3] = (byte)(dest >> 24);
outputOffset = 0;
outputCount = 4;
}
}
}
return size;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,90 @@
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Filters
{
public class BCJFilter : Filter
{
private static readonly bool[] MASK_TO_ALLOWED_STATUS = new bool[] {true, true, true, false, true, false, false, false};
private static readonly int[] MASK_TO_BIT_NUMBER = new int[] { 0, 1, 2, 2, 3, 3, 3, 3 };
private int pos;
private int prevMask = 0;
public BCJFilter(bool isEncoder, Stream baseStream) : base(isEncoder, baseStream, 5)
{
pos = 5;
}
private static bool test86MSByte(byte b)
{
return b == 0x00 || b == 0xFF;
}
protected override int Transform(byte[] buffer, int offset, int count)
{
int prevPos = offset - 1;
int end = offset + count - 5;
int i;
for (i = offset; i <= end; ++i) {
if ((buffer[i] & 0xFE) != 0xE8)
continue;
prevPos = i - prevPos;
if ((prevPos & ~3) != 0) { // (unsigned)prevPos > 3
prevMask = 0;
} else {
prevMask = (prevMask << (prevPos - 1)) & 7;
if (prevMask != 0) {
if (!MASK_TO_ALLOWED_STATUS[prevMask] || test86MSByte(
buffer[i + 4 - MASK_TO_BIT_NUMBER[prevMask]])) {
prevPos = i;
prevMask = (prevMask << 1) | 1;
continue;
}
}
}
prevPos = i;
if (test86MSByte(buffer[i + 4])) {
int src = buffer[i + 1]
| (buffer[i + 2] << 8)
| (buffer[i + 3] << 16)
| (buffer[i + 4] << 24);
int dest;
while (true) {
if (isEncoder)
dest = src + (pos + i - offset);
else
dest = src - (pos + i - offset);
if (prevMask == 0)
break;
int index = MASK_TO_BIT_NUMBER[prevMask] * 8;
if (!test86MSByte((byte)(dest >> (24 - index))))
break;
src = dest ^ ((1 << (32 - index)) - 1);
}
buffer[i + 1] = (byte)dest;
buffer[i + 2] = (byte)(dest >> 8);
buffer[i + 3] = (byte)(dest >> 16);
buffer[i + 4] = (byte)(~(((dest >> 24) & 1) - 1));
i += 4;
} else {
prevMask = (prevMask << 1) | 1;
}
}
prevPos = i - prevPos;
prevMask = ((prevPos & ~3) != 0) ? 0 : prevMask << (prevPos - 1);
i -= offset;
pos += i;
return i;
}
}
}

View File

@@ -0,0 +1,171 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Filters
{
public abstract class Filter : Stream
{
protected bool isEncoder;
protected Stream baseStream;
private byte[] tail;
private byte[] window;
private int transformed = 0;
private int read = 0;
private bool endReached = false;
private long position = 0;
protected Filter(bool isEncoder, Stream baseStream, int lookahead)
{
this.isEncoder = isEncoder;
this.baseStream = baseStream;
tail = new byte[lookahead - 1];
window = new byte[tail.Length * 2];
}
public Stream BaseStream
{ get { return baseStream; } }
public override bool CanRead
{
get { return !isEncoder; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return isEncoder; }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length
{
get { return baseStream.Length; }
}
public override long Position
{
get
{
return position;
}
set
{
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int size = 0;
if (transformed > 0)
{
int copySize = transformed;
if (copySize > count)
copySize = count;
Buffer.BlockCopy(tail, 0, buffer, offset, copySize);
transformed -= copySize;
read -= copySize;
offset += copySize;
count -= copySize;
size += copySize;
Buffer.BlockCopy(tail, copySize, tail, 0, read);
}
if (count == 0)
{
position += size;
return size;
}
int inSize = read;
if (inSize > count)
inSize = count;
Buffer.BlockCopy(tail, 0, buffer, offset, inSize);
read -= inSize;
Buffer.BlockCopy(tail, inSize, tail, 0, read);
while (!endReached && inSize < count)
{
int baseRead = baseStream.Read(buffer, offset + inSize, count - inSize);
inSize += baseRead;
if (baseRead == 0)
endReached = true;
}
while (!endReached && read < tail.Length)
{
int baseRead = baseStream.Read(tail, read, tail.Length - read);
read += baseRead;
if (baseRead == 0)
endReached = true;
}
if (inSize > tail.Length)
{
transformed = Transform(buffer, offset, inSize);
offset += transformed;
count -= transformed;
size += transformed;
inSize -= transformed;
transformed = 0;
}
if (count == 0)
{
position += size;
return size;
}
Buffer.BlockCopy(buffer, offset, window, 0, inSize);
Buffer.BlockCopy(tail, 0, window, inSize, read);
if (inSize + read > tail.Length)
transformed = Transform(window, 0, inSize + read);
else
transformed = inSize + read;
Buffer.BlockCopy(window, 0, buffer, offset, inSize);
Buffer.BlockCopy(window, inSize, tail, 0, read);
size += inSize;
transformed -= inSize;
position += size;
return size;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (origin != SeekOrigin.Current)
throw new NotImplementedException();
const int bufferSize = 10240;
Byte[] seekBuffer = new byte[bufferSize];
long seekToGo = offset;
while (seekToGo > 0)
{
long get = seekToGo > bufferSize ? bufferSize : seekToGo;
Read(seekBuffer, 0, (int) get);
seekToGo -= get;
}
return position;
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
Transform(buffer, offset, count);
baseStream.Write(buffer, offset, count);
}
protected abstract int Transform(byte[] buffer, int offset, int count);
}
}

View File

@@ -0,0 +1,61 @@
using System;
using System.IO;
using ROMVault2.SupportedFiles.SevenZip.Common;
using ROMVault2.SupportedFiles.SevenZip.Compress.LZMA;
namespace ROMVault2.SupportedFiles.SevenZip
{
public static class LZMACompressFile
{
public static void CompressFile(Stream inStream,Stream outStream,out byte[] codeMSbytes,ICodeProgress p)
{
Int32 dictionary = 1 << 24;
Int32 posStateBits = 2;
Int32 litContextBits = 3; // for normal files
Int32 litPosBits = 0;
Int32 algorithm = 2;
Int32 numFastBytes = 128; //64;
string mf = "bt4";
bool eos = true;
CoderPropID[] propIDs =
{
CoderPropID.DictionarySize,
CoderPropID.PosStateBits,
CoderPropID.LitContextBits,
CoderPropID.LitPosBits,
CoderPropID.Algorithm,
CoderPropID.NumFastBytes,
CoderPropID.MatchFinder,
CoderPropID.EndMarker
};
object[] properties =
{
dictionary,
posStateBits,
litContextBits,
litPosBits,
algorithm,
numFastBytes,
mf,
eos
};
Encoder encoder = new Encoder();
encoder.SetCoderProperties(propIDs, properties);
using (MemoryStream codeMS = new MemoryStream())
{
encoder.WriteCoderProperties(codeMS);
codeMSbytes = new byte[codeMS.Length];
codeMS.Position = 0;
codeMS.Read(codeMSbytes, 0, codeMSbytes.Length);
}
encoder.Code(inStream, outStream, -1, -1, p);
}
}
}

View File

@@ -0,0 +1,782 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using ROMVault2.SupportedFiles.SevenZip.Common;
using ROMVault2.SupportedFiles.SevenZip.Compress.LZMA;
using ROMVault2.SupportedFiles.SevenZip.Filters;
using ROMVault2.SupportedFiles.SevenZip.Structure;
namespace ROMVault2.SupportedFiles.SevenZip
{
public class SevenZ : ICompress
{
public class LocalFile
{
public string FileName;
public ulong UncompressedSize;
public bool isDirectory;
public byte[] crc;
public byte[] sha1;
public byte[] md5;
public int StreamIndex;
public ulong StreamOffset;
public ZipReturn FileStatus = ZipReturn.ZipUntested;
}
private List<LocalFile> _localFiles = new List<LocalFile>();
private IO.FileInfo _zipFileInfo;
private Stream _zipFs;
private ZipOpenType _zipOpen;
private ZipStatus _pZipStatus;
SignatureHeader _signatureHeader;
private bool _compressed = true;
private Stream _tmpOutStream;
private Stream _streamNow;
private int _streamIndex = -1;
public string ZipFilename
{
get { return _zipFileInfo != null ? _zipFileInfo.FullName : ""; }
}
public long TimeStamp
{
get { return _zipFileInfo != null ? _zipFileInfo.LastWriteTime : 0; }
}
public ZipOpenType ZipOpen { get { return _zipOpen; } }
public ZipStatus ZipStatus { get { return _pZipStatus; } }
public int LocalFilesCount() { return _localFiles.Count; }
public string Filename(int i) { return _localFiles[i].FileName; }
public ulong? LocalHeader(int i) { return 0; }
public ulong UncompressedSize(int i) { return _localFiles[i].UncompressedSize; }
public ZipReturn FileStatus(int i) { return _localFiles[i].FileStatus; }
public byte[] CRC32(int i) { return _localFiles[i].crc; }
public byte[] MD5(int i) { return _localFiles[i].md5; }
public byte[] SHA1(int i) { return _localFiles[i].sha1; }
public bool IsDirectory(int i) { return _localFiles[i].isDirectory; }
private long _baseOffset;
#region open 7z files
public ZipReturn ZipFileOpen(string filename, long timestamp,bool readHeaders)
{
Debug.WriteLine(filename);
#region open file stream
try
{
if (!IO.File.Exists(filename))
{
ZipFileClose();
return ZipReturn.ZipErrorFileNotFound;
}
_zipFileInfo = new IO.FileInfo(filename);
if (timestamp != -1 && _zipFileInfo.LastWriteTime != timestamp)
{
ZipFileClose();
return ZipReturn.ZipErrorTimeStamp;
}
int errorCode = IO.FileStream.OpenFileRead(filename, out _zipFs);
if (errorCode != 0)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
}
catch (PathTooLongException)
{
ZipFileClose();
return ZipReturn.ZipFileNameToLong;
}
catch (IOException)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
#endregion
_zipOpen = ZipOpenType.OpenRead;
_pZipStatus = ZipStatus.None;
SignatureHeader signatureHeader = new SignatureHeader();
if (!signatureHeader.Read(new BinaryReader(_zipFs)))
return ZipReturn.ZipSignatureError;
_baseOffset = _zipFs.Position; Util.log("BaseOffset : " + _baseOffset);
Util.log("Loading Stream : " + (_baseOffset + (long)signatureHeader.NextHeaderOffset) + " , Size : " + signatureHeader.NextHeaderSize);
//_zipFs.Seek(_baseOffset + (long)signatureHeader.NextHeaderOffset, SeekOrigin.Begin);
//byte[] mainHeader = new byte[signatureHeader.NextHeaderSize];
//_zipFs.Read(mainHeader, 0, (int)signatureHeader.NextHeaderSize);
//if (!CRC.VerifyDigest(signatureHeader.NextHeaderCRC, mainHeader, 0, (uint)signatureHeader.NextHeaderSize))
// return ZipReturn.Zip64EndOfCentralDirError;
_zipFs.Seek(_baseOffset + (long)signatureHeader.NextHeaderOffset, SeekOrigin.Begin);
ZipReturn zr = Header.ReadHeaderOrPackedHeader(_zipFs, _baseOffset, out _header);
if (zr != ZipReturn.ZipGood)
return zr;
_zipFs.Seek(_baseOffset + (long)(signatureHeader.NextHeaderOffset + signatureHeader.NextHeaderSize), SeekOrigin.Begin);
_pZipStatus = Istorrent7Z() ? ZipStatus.TrrntZip : ZipStatus.None;
PopulateLocalFiles(out _localFiles);
return ZipReturn.ZipGood;
}
private void PopulateLocalFiles(out List<LocalFile> localFiles)
{
int emptyFileIndex = 0;
int folderIndex = 0;
int unpackedStreamsIndex = 0;
ulong streamOffset = 0;
localFiles = new List<LocalFile>();
for (int i = 0; i < _header.FileInfo.Names.Length; i++)
{
LocalFile lf = new LocalFile { FileName = _header.FileInfo.Names[i] };
if (_header.FileInfo.EmptyStreamFlags == null || !_header.FileInfo.EmptyStreamFlags[i])
{
lf.StreamIndex = folderIndex;
lf.StreamOffset = streamOffset;
lf.UncompressedSize = _header.StreamsInfo.Folders[folderIndex].UnpackedStreamInfo[unpackedStreamsIndex].UnpackedSize;
lf.crc = Util.uinttobytes(_header.StreamsInfo.Folders[folderIndex].UnpackedStreamInfo[unpackedStreamsIndex].Crc);
streamOffset += lf.UncompressedSize;
unpackedStreamsIndex++;
if (unpackedStreamsIndex >= _header.StreamsInfo.Folders[folderIndex].UnpackedStreamInfo.Length)
{
folderIndex++;
unpackedStreamsIndex = 0;
streamOffset = 0;
}
}
else
{
lf.UncompressedSize = 0;
lf.crc = new byte[] { 0, 0, 0, 0 };
lf.isDirectory = _header.FileInfo.EmptyFileFlags == null || !_header.FileInfo.EmptyFileFlags[emptyFileIndex++];
if (lf.isDirectory)
if (lf.FileName.Substring(lf.FileName.Length - 1, 1) != "/")
lf.FileName += "/";
}
localFiles.Add(lf);
}
}
public void ZipFileClose()
{
ZipFileClose(null);
}
public void ZipFileClose(ICodeProgress p)
{
if (_zipOpen == ZipOpenType.Closed)
return;
if (_zipOpen == ZipOpenType.OpenRead)
{
ZipFileCloseReadStream();
if (_zipFs != null)
{
_zipFs.Close();
_zipFs.Dispose();
}
_zipOpen = ZipOpenType.Closed;
return;
}
CloseWriting7Zip(p);
_zipFileInfo = new IO.FileInfo(_zipFileInfo.FullName);
_zipOpen = ZipOpenType.Closed;
}
private Header _header;
private bool Istorrent7Z()
{
const int crcsz = 128;
const int t7ZsigSize = 16 + 1 + 9 + 4 + 4;
byte[] kSignature = { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C };
int kSignatureSize = kSignature.Length;
const string sig = "\xa9\x9f\xd1\x57\x08\xa9\xd7\xea\x29\x64\xb2\x36\x1b\x83\x52\x33\x01torrent7z_0.9beta";
byte[] t7Zid = Util.Enc.GetBytes(sig);
int t7ZidSize = t7Zid.Length;
const int tmpbufsize = 256 + t7ZsigSize + 8 + 4;
byte[] buffer = new byte[tmpbufsize];
// read fist 128 bytes, pad with zeros if less bytes
int offs = 0;
_zipFs.Seek(0, SeekOrigin.Begin);
int ar = _zipFs.Read(buffer, offs, crcsz);
if (ar < crcsz)
Util.memset(buffer, offs + ar, 0, crcsz - ar);
offs = crcsz;
long foffs = _zipFs.Length;
foffs = foffs < (crcsz + t7ZsigSize + 4) ? 0 : foffs - (crcsz + t7ZsigSize + 4);
_zipFs.Seek(foffs, SeekOrigin.Begin);
ar = _zipFs.Read(buffer, offs, (crcsz + t7ZsigSize + 4));
if (ar < (crcsz + t7ZsigSize + 4))
{
if (ar >= t7ZsigSize + 4)
{
ar -= t7ZsigSize + 4;
}
if (ar < kSignatureSize)
{
ar = kSignatureSize;
}
Util.memset(buffer, offs + ar, 0, crcsz - ar);
Util.memcpyr(buffer, crcsz * 2 + 8, buffer, offs + ar, t7ZsigSize + 4);
}
else
Util.memcpyr(buffer, crcsz * 2 + 8, buffer, crcsz * 2, t7ZsigSize + 4);
foffs = _zipFs.Length;
foffs -= t7ZsigSize + 4;
//memcpy(buffer, crcsz * 2, &foffs, 8);
buffer[crcsz * 2 + 0] = (byte)((foffs >> 0) & 0xff);
buffer[crcsz * 2 + 1] = (byte)((foffs >> 8) & 0xff);
buffer[crcsz * 2 + 2] = (byte)((foffs >> 16) & 0xff);
buffer[crcsz * 2 + 3] = (byte)((foffs >> 24) & 0xff);
buffer[crcsz * 2 + 4] = 0;
buffer[crcsz * 2 + 5] = 0;
buffer[crcsz * 2 + 6] = 0;
buffer[crcsz * 2 + 7] = 0;
if (Util.memcmp(buffer, 0, kSignature, kSignatureSize))
{
t7Zid[16] = buffer[crcsz * 2 + 4 + 8 + 16];
if (Util.memcmp(buffer, crcsz * 2 + 4 + 8, t7Zid, t7ZidSize))
{
UInt32 inCrc32 = (UInt32)((buffer[crcsz * 2 + 8 + 0]) +
(buffer[crcsz * 2 + 8 + 1] << 8) +
(buffer[crcsz * 2 + 8 + 2] << 16) +
(buffer[crcsz * 2 + 8 + 3] << 24));
buffer[crcsz * 2 + 8 + 0] = 0xff;
buffer[crcsz * 2 + 8 + 1] = 0xff;
buffer[crcsz * 2 + 8 + 2] = 0xff;
buffer[crcsz * 2 + 8 + 3] = 0xff;
uint calcCrc32 = CRC.CalculateDigest(buffer, 0, crcsz * 2 + 8 + t7ZsigSize + 4);
if (inCrc32 == calcCrc32) return true;
}
}
return false;
}
#endregion
public void DeepScan()
{
const int bufferSize = 4096 * 128;
byte[] buffer = new byte[bufferSize];
for (int index = 0; index < _localFiles.Count; index++)
{
if (_localFiles[index].isDirectory || _localFiles[index].UncompressedSize == 0)
{
_localFiles[index].md5 = new byte[] { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e };
_localFiles[index].sha1 = new byte[] { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 };
_localFiles[index].FileStatus = ZipReturn.ZipGood;
continue;
}
ulong sizetogo;
Stream inStream;
ZipReturn zr = ZipFileOpenReadStream(index, out inStream, out sizetogo);
if (zr != ZipReturn.ZipGood)
continue;
if (inStream == null)
continue;
CRC crc32 = new CRC();
MD5 lmd5 = System.Security.Cryptography.MD5.Create();
SHA1 lsha1 = System.Security.Cryptography.SHA1.Create();
while (sizetogo > 0)
{
int sizenow = sizetogo > (ulong)bufferSize ? bufferSize : (int)sizetogo;
inStream.Read(buffer, 0, sizenow);
crc32.Update(buffer, 0, (uint)sizenow);
lmd5.TransformBlock(buffer, 0, sizenow, null, 0);
lsha1.TransformBlock(buffer, 0, sizenow, null, 0);
sizetogo = sizetogo - (ulong)sizenow;
}
lmd5.TransformFinalBlock(buffer, 0, 0);
lsha1.TransformFinalBlock(buffer, 0, 0);
byte[] testcrc = Util.uinttobytes(crc32.GetDigest());
_localFiles[index].md5 = lmd5.Hash;
_localFiles[index].sha1 = lsha1.Hash;
_localFiles[index].FileStatus = Util.ByteArrCompare(_localFiles[index].crc, testcrc) ? ZipReturn.ZipGood : ZipReturn.ZipCRCDecodeError;
}
}
#region read 7z file
public ZipReturn ZipFileOpenReadStream(int index, out Stream stream, out ulong unCompressedSize)
{
Debug.WriteLine("Opening File " + _localFiles[index].FileName);
stream = null;
unCompressedSize = 0;
if (_zipOpen != ZipOpenType.OpenRead)
return ZipReturn.ZipErrorGettingDataStream;
if (IsDirectory(index))
return ZipReturn.ZipTryingToAccessADirectory;
unCompressedSize = _localFiles[index].UncompressedSize;
int thisStreamIndex = _localFiles[index].StreamIndex;
// first see if we can re-use the current open stream
if (_streamIndex == thisStreamIndex)
{
stream = _streamNow;
if (_streamNow is BCJFilter) // it is a BCJ + Decoder stream but need to check the position in the stream can be used.
{
if ((long)_localFiles[index].StreamOffset >= _streamNow.Position)
{
stream.Seek((long)_localFiles[index].StreamOffset - _streamNow.Position, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
}
else if (_streamNow is Decoder) // it is a Decoder stream but need to check the position in the stream can be used.
{
if ((long)_localFiles[index].StreamOffset >= _streamNow.Position)
{
stream.Seek((long)_localFiles[index].StreamOffset - _streamNow.Position, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
}
else // it is an uncompressed stream
{
if (stream != null)
stream.Seek((long)_localFiles[index].StreamOffset - _streamNow.Position, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
}
// need to open a new stream
// first close the old streams
ZipFileCloseReadStream();
// open new stream
_streamIndex = thisStreamIndex;
_zipFs.Seek(_baseOffset + (long)_header.StreamsInfo.PackedStreams[thisStreamIndex].StreamPosition, SeekOrigin.Begin);
byte[] method = _header.StreamsInfo.Folders[_localFiles[index].StreamIndex].Coders[0].Method;
if (method.Length == 3 && method[0] == 3 && method[1] == 1 && method[2] == 1) // LZMA
{
Decoder decoder = new Decoder();
decoder.SetDecoderProperties(_header.StreamsInfo.Folders[_localFiles[index].StreamIndex].Coders[0].Properties);
decoder.SetUpStream(_zipFs);
stream = decoder;
_streamNow = stream;
if (_header.StreamsInfo.Folders[_localFiles[index].StreamIndex].Coders.Length > 1) // BCJ
{
method = _header.StreamsInfo.Folders[_localFiles[index].StreamIndex].Coders[1].Method;
if (method.Length == 4 && method[0] == 3 && method[1] == 3 && method[2] == 1 && method[3] == 3)
{
BCJFilter filter = new BCJFilter(false, stream);
stream = filter;
_streamNow = stream;
stream.Seek((long)_localFiles[index].StreamOffset, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
return ZipReturn.ZipUnsupportedCompression;
}
stream.Seek((long)_localFiles[index].StreamOffset, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
if (method.Length == 1 && method[0] == 33) // lzma2
{
return ZipReturn.ZipUnsupportedCompression;
}
if (method.Length == 1 && method[0] == 0) // uncompressed
{
stream = _zipFs;
_streamNow = stream;
stream.Seek((long)_localFiles[index].StreamOffset, SeekOrigin.Current);
return ZipReturn.ZipGood;
}
if (method.Length == 3 && method[0] == 4 && method[1] == 2 && method[2] == 2) // BZip2
{
return ZipReturn.ZipUnsupportedCompression;
}
if (method.Length == 1 && method[0] == 33) // LZMA2
{
return ZipReturn.ZipUnsupportedCompression;
}
return ZipReturn.ZipUnsupportedCompression;
}
public ZipReturn ZipFileCloseReadStream()
{
if (_streamNow is BCJFilter)
{
Stream baseStream = ((BCJFilter)_streamNow).BaseStream;
_streamNow.Dispose();
_streamNow = baseStream;
}
if (_streamNow is Decoder)
{
_streamNow.Close();
_streamNow.Dispose();
}
_streamNow = null;
return ZipReturn.ZipGood;
}
#endregion
#region write 7z File
public void ZipFileAddDirectory()
{
// do nothing here for 7zip
}
public ZipReturn ZipFileCreate(string newFilename)
{
return ZipFileCreate(newFilename, true);
}
public ZipReturn ZipFileCreate(string newFilename, bool compressOutput)
{
if (_zipOpen != ZipOpenType.Closed)
return ZipReturn.ZipFileAlreadyOpen;
DirUtil.CreateDirForFile(newFilename);
_zipFileInfo = new IO.FileInfo(newFilename);
int errorCode = IO.FileStream.OpenFileWrite(newFilename, out _zipFs);
if (errorCode != 0)
{
ZipFileClose();
return ZipReturn.ZipErrorOpeningFile;
}
_zipOpen = ZipOpenType.OpenWrite;
_signatureHeader = new SignatureHeader();
_header = new Header();
BinaryWriter bw = new BinaryWriter(_zipFs);
_signatureHeader.Write(bw);
_compressed = compressOutput;
_tmpOutStream = compressOutput ? new FileStream(_zipFileInfo.FullName + ".tmp", FileMode.Create, FileAccess.Write) : null;
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileOpenWriteStream(bool raw, bool trrntzip, string filename, ulong uncompressedSize, ushort compressionMethod, out Stream stream)
{
return ZipFileOpenWriteStream(filename, uncompressedSize, out stream);
}
public ZipReturn ZipFileOpenWriteStream(string filename, ulong uncompressedSize, out Stream stream)
{
LocalFile lf = new LocalFile
{
FileName = filename,
UncompressedSize = uncompressedSize,
StreamOffset = (ulong)(_zipFs.Position - _signatureHeader.BaseOffset)
};
_localFiles.Add(lf);
stream = _tmpOutStream ?? _zipFs;
return ZipReturn.ZipGood;
}
public ZipReturn ZipFileCloseWriteStream(byte[] crc32)
{
_localFiles[_localFiles.Count - 1].crc = new[] { crc32[3], crc32[2], crc32[1], crc32[0] };
return ZipReturn.ZipGood;
}
private void Create7ZStructure()
{
int fileCount = _localFiles.Count;
//FileInfo
_header.FileInfo = new Structure.FileInfo
{
Names = new string[fileCount]
};
ulong emptyStreamCount = 0;
ulong emptyFileCount = 0;
for (int i = 0; i < fileCount; i++)
{
_header.FileInfo.Names[i] = _localFiles[i].FileName;
if (_localFiles[i].UncompressedSize != 0)
continue;
if (!_localFiles[i].isDirectory)
emptyFileCount += 1;
emptyStreamCount += 1;
}
ulong outFileCount = (ulong)_localFiles.Count - emptyStreamCount;
_header.FileInfo.EmptyStreamFlags = null;
_header.FileInfo.EmptyFileFlags = null;
_header.FileInfo.Attributes = null;
if (emptyStreamCount > 0)
{
if (emptyStreamCount != emptyFileCount) //then we found directories and need to set the attributes
_header.FileInfo.Attributes = new uint[fileCount];
if (emptyFileCount > 0)
_header.FileInfo.EmptyFileFlags = new bool[emptyStreamCount];
emptyStreamCount = 0;
_header.FileInfo.EmptyStreamFlags = new bool[fileCount];
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize != 0)
continue;
if (_localFiles[i].isDirectory)
_header.FileInfo.Attributes[i] = 0x10; // set attributes to directory
else
_header.FileInfo.EmptyFileFlags[emptyStreamCount] = true; // set empty file flag
_header.FileInfo.EmptyStreamFlags[i] = true;
emptyStreamCount += 1;
}
}
//StreamsInfo
_header.StreamsInfo = new StreamsInfo { PackPosition = 0 };
//StreamsInfo.PackedStreamsInfo
if (_compressed)
{
_header.StreamsInfo.PackedStreams = new PackedStreamInfo[1];
_header.StreamsInfo.PackedStreams[0] = new PackedStreamInfo { PackedSize = _packStreamSize };
}
else
{
_header.StreamsInfo.PackedStreams = new PackedStreamInfo[outFileCount];
int fileIndex = 0;
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize == 0)
continue;
_header.StreamsInfo.PackedStreams[fileIndex++] = new PackedStreamInfo { PackedSize = _localFiles[i].UncompressedSize };
}
}
//StreamsInfo.PackedStreamsInfo, no CRC or StreamPosition required
if (_compressed)
{
//StreamsInfo.Folders
_header.StreamsInfo.Folders = new Folder[1];
Folder folder = new Folder { Coders = new Coder[1] };
//StreamsInfo.Folders.Coder
// flags 0x23
folder.Coders[0] = new Coder
{
Method = new byte[] { 3, 1, 1 },
NumInStreams = 1,
NumOutStreams = 1,
Properties = _codeMSbytes
};
folder.BindPairs = null;
folder.PackedStreamIndices = new[] { (ulong)0 };
folder.UnpackedStreamSizes = new[] { _unpackedStreamSize };
folder.UnpackCRC = null;
folder.UnpackedStreamInfo = new UnpackedStreamInfo[outFileCount];
int fileIndex = 0;
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize == 0)
continue;
UnpackedStreamInfo unpackedStreamInfo = new UnpackedStreamInfo
{
UnpackedSize = _localFiles[i].UncompressedSize,
Crc = Util.bytestouint(_localFiles[i].crc)
};
folder.UnpackedStreamInfo[fileIndex++] = unpackedStreamInfo;
}
_header.StreamsInfo.Folders[0] = folder;
}
else
{
_header.StreamsInfo.Folders = new Folder[outFileCount];
int fileIndex = 0;
for (int i = 0; i < fileCount; i++)
{
if (_localFiles[i].UncompressedSize == 0)
continue;
Folder folder = new Folder { Coders = new Coder[1] };
//StreamsInfo.Folders.Coder
// flags 0x01
folder.Coders[0] = new Coder
{
Method = new byte[] { 0 },
NumInStreams = 1,
NumOutStreams = 1,
Properties = null
};
folder.BindPairs = null;
folder.PackedStreamIndices = new[] { (ulong)i };
folder.UnpackedStreamSizes = new[] { _localFiles[i].UncompressedSize };
folder.UnpackCRC = null;
folder.UnpackedStreamInfo = new UnpackedStreamInfo[1];
UnpackedStreamInfo unpackedStreamInfo = new UnpackedStreamInfo
{
UnpackedSize = _localFiles[i].UncompressedSize,
Crc = Util.bytestouint(_localFiles[i].crc)
};
folder.UnpackedStreamInfo[0] = unpackedStreamInfo;
_header.StreamsInfo.Folders[fileIndex++] = folder;
}
}
}
ulong _packStreamSize;
ulong _unpackedStreamSize;
byte[] _codeMSbytes;
private void CloseWriting7Zip(ICodeProgress p = null)
{
if (_compressed)
{
_unpackedStreamSize = (ulong)_tmpOutStream.Length;
_tmpOutStream.Close();
_tmpOutStream.Dispose();
UInt64 packStreamStart = (UInt64)_zipFs.Position;
using (Stream inStream = new FileStream(_zipFileInfo.FullName + ".tmp", FileMode.Open, FileAccess.Read))
{
LZMACompressFile.CompressFile(inStream, _zipFs, out _codeMSbytes, p);
}
_packStreamSize = (UInt64)_zipFs.Position - packStreamStart;
File.Delete(_zipFileInfo.FullName + ".tmp");
}
Create7ZStructure();
byte[] newHeaderByte;
using (Stream headerMem = new MemoryStream())
{
using (BinaryWriter headerBw = new BinaryWriter(headerMem))
{
_header.WriteHeader(headerBw);
newHeaderByte = new byte[headerMem.Length];
headerMem.Position = 0;
headerMem.Read(newHeaderByte, 0, newHeaderByte.Length);
}
}
CRC mainHeadercrc = new CRC();
mainHeadercrc.Update(newHeaderByte, 0, (uint)newHeaderByte.Length);
UInt32 mainHeaderCRC = mainHeadercrc.GetDigest();
UInt64 headerpos = (UInt64)_zipFs.Position;
BinaryWriter bw = new BinaryWriter(_zipFs);
bw.Write(newHeaderByte);
_signatureHeader.WriteFinal(bw, headerpos, (ulong)newHeaderByte.Length, mainHeaderCRC);
_zipFs.Flush();
_zipFs.Close();
_zipFs.Dispose();
}
#endregion
public void ZipFileAddDirectory(string filename)
{
LocalFile lf = new LocalFile
{
FileName = filename,
UncompressedSize = 0,
isDirectory = true,
StreamOffset = 0
};
_localFiles.Add(lf);
}
public ZipReturn ZipFileRollBack()
{
throw new NotImplementedException();
}
public void ZipFileCloseFailed()
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,24 @@
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class BindPair
{
public ulong InIndex;
public ulong OutIndex;
public void Read(BinaryReader br)
{
InIndex = br.ReadEncodedUInt64();
Util.log("InIndex = " + InIndex);
OutIndex = br.ReadEncodedUInt64();
Util.log("OutIndex = " + OutIndex);
}
public void Write(BinaryWriter bw)
{
bw.WriteEncodedUInt64(InIndex);
bw.WriteEncodedUInt64(OutIndex);
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class Coder
{
public byte[] Method;
public ulong NumInStreams;
public ulong NumOutStreams;
public byte[] Properties;
public void Read(BinaryReader br)
{
Util.log("Begin : ReadCoder", 1);
byte flags = br.ReadByte();
Util.log("Flags = " + flags.ToString("X"));
int decompressionMethodIdSize = flags & 0xf;
Method = br.ReadBytes(decompressionMethodIdSize);
if ((flags & 0x10) != 0)
{
NumInStreams = br.ReadEncodedUInt64();
Util.log("NumInStreams = " + NumInStreams);
NumOutStreams = br.ReadEncodedUInt64();
Util.log("NumOutStreams = " + NumOutStreams);
}
else
{
NumInStreams = 1;
NumOutStreams = 1;
}
if ((flags & 0x20) != 0)
{
ulong propSize = br.ReadEncodedUInt64();
Util.log("PropertiesSize = " + propSize);
Properties = br.ReadBytes((int)propSize);
Util.log("Properties = " + Properties);
}
if ((flags & 0x80) != 0)
throw new NotSupportedException("External flag");
Util.log("End : ReadCoder", -1);
}
public void Write(BinaryWriter bw)
{
byte flags = (byte)Method.Length;
if (NumInStreams != 1 || NumOutStreams != 1)
flags = (byte)(flags | 0x10);
if (Properties != null && Properties.Length > 0)
flags = (byte)(flags | 0x20);
bw.Write(flags);
bw.Write(Method);
if (NumInStreams != 1 || NumOutStreams != 1)
{
bw.WriteEncodedUInt64(NumInStreams);
bw.WriteEncodedUInt64(NumOutStreams);
}
if (Properties != null && Properties.Length > 0)
{
bw.WriteEncodedUInt64((ulong) Properties.Length);
bw.Write(Properties);
}
}
}
}

View File

@@ -0,0 +1,128 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class FileInfo
{
public string[] Names;
public bool[] EmptyStreamFlags;
public bool[] EmptyFileFlags;
public uint[] Attributes;
public void Read(BinaryReader br)
{
Util.log("Begin : ReadFileInfo", 1);
ulong size = br.ReadEncodedUInt64();
Names = new string[size];
ulong numEmptyFiles = 0;
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
if (hp == HeaderProperty.kEnd)
{
Util.log("End : ReadFileInfo", -1);
return;
}
ulong bytessize = br.ReadEncodedUInt64();
switch (hp)
{
case HeaderProperty.kName:
if (br.ReadByte() != 0)
throw new Exception("Cannot be external");
Util.log("Looping Names Begin " + size, 1);
for (ulong i = 0; i < size; i++)
{
Names[i] = br.ReadName();
Util.log("enteries[" + i + "]=" + Names[i]);
}
Util.log("Looping Names End " + size, -1);
continue;
case HeaderProperty.kEmptyStream:
Util.log("reading EmptyStreamFlags Total=" + size);
EmptyStreamFlags = Util.ReadBoolFlags(br, (ulong)Names.Length);
for (ulong i = 0; i < size; i++)
if (EmptyStreamFlags[i]) numEmptyFiles++;
continue;
case HeaderProperty.kEmptyFile:
Util.log("reading numEmptyFilesFlags Total=" + numEmptyFiles);
EmptyFileFlags = Util.ReadBoolFlags(br, numEmptyFiles);
continue;
case HeaderProperty.kWinAttributes:
Util.log("skipping bytes " + bytessize);
Attributes = Util.ReadUInt32Def(br, size);
continue;
case HeaderProperty.kLastWriteTime:
Util.log("skipping bytes " + bytessize);
br.ReadBytes((int)bytessize);
continue;
case HeaderProperty.kDummy:
Util.log("skipping bytes " + bytessize);
br.ReadBytes((int)bytessize);
continue;
default:
throw new Exception(hp.ToString());
}
}
}
public void Write(BinaryWriter bw)
{
bw.Write((byte)HeaderProperty.kFilesInfo);
bw.WriteEncodedUInt64((UInt64)Names.Length);
byte[] namebyte;
using (MemoryStream nameMem = new MemoryStream())
{
using (BinaryWriter nameBw = new BinaryWriter(nameMem))
{
nameBw.Write((byte)0); //not external
foreach (string name in Names)
nameBw.WriteName(name);
namebyte = new byte[nameMem.Length];
nameMem.Position = 0;
nameMem.Read(namebyte, 0, namebyte.Length);
}
}
bw.Write((byte)HeaderProperty.kName);
bw.WriteEncodedUInt64((UInt64)namebyte.Length);
bw.Write(namebyte);
if (EmptyStreamFlags != null)
{
bw.Write((byte)HeaderProperty.kEmptyStream);
Util.WriteBoolFlags(bw, EmptyStreamFlags);
}
if (EmptyFileFlags != null)
{
bw.Write((byte)HeaderProperty.kEmptyFile);
Util.WriteBoolFlags(bw, EmptyFileFlags);
}
if (Attributes != null)
{
bw.Write((byte)HeaderProperty.kWinAttributes);
Util.WriteUint32Def(bw, Attributes);
}
bw.Write((byte)HeaderProperty.kEnd);
}
}
}

View File

@@ -0,0 +1,395 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class Folder
{
public Coder[] Coders;
public BindPair[] BindPairs;
public ulong[] PackedStreamIndices;
public ulong[] UnpackedStreamSizes;
public uint? UnpackCRC;
public UnpackedStreamInfo[] UnpackedStreamInfo;
private void ReadFolder(BinaryReader br)
{
Util.log("Begin : Read Folder", 1);
ulong numCoders = br.ReadEncodedUInt64();
Util.log("NumCoders = " + numCoders);
Coders = new Coder[numCoders];
int numInStreams = 0;
int numOutStreams = 0;
Util.log("Looping Coders Begin", 1);
for (ulong i = 0; i < numCoders; i++)
{
Util.log("Looping Coders : " + i);
Coders[i] = new Coder();
Coders[i].Read(br);
numInStreams += (int)Coders[i].NumInStreams;
numOutStreams += (int)Coders[i].NumOutStreams;
}
Util.log("Looping Coders End", -1);
int numBindPairs = numOutStreams - 1;
Util.log("numBindPairs : " + numBindPairs);
BindPairs = new BindPair[numBindPairs];
Util.log("Looping BindPairs Begin", 1);
for (int i = 0; i < numBindPairs; i++)
{
Util.log("Looping BindPairs : " + i);
BindPairs[i] = new BindPair();
BindPairs[i].Read(br);
}
Util.log("Looping BindPairs End", -1);
if (numInStreams < numBindPairs)
throw new NotSupportedException("Error");
int numPackedStreams = numInStreams - numBindPairs;
Util.log("numPackedStreams : " + numPackedStreams);
PackedStreamIndices = new ulong[numPackedStreams];
if (numPackedStreams == 1)
{
uint pi = 0;
for (uint j = 0; j < numInStreams; j++)
{
for (uint k = 0; k < BindPairs.Length; k++)
{
if (BindPairs[k].InIndex == j) continue;
Util.log("PackedStreamIndices[" + pi + "] : " + j);
PackedStreamIndices[pi++] = j;
break;
}
}
}
else
{
for (uint i = 0; i < numPackedStreams; i++)
{
PackedStreamIndices[i] = br.ReadEncodedUInt64();
Util.log("PackedStreamIndices[" + i + "] = " + PackedStreamIndices[i]);
}
}
Util.log("End : Read Folder", -1);
}
private void ReadUnpackedStreamSize(BinaryReader br)
{
ulong outStreams = 0;
foreach (Coder c in Coders)
outStreams += c.NumOutStreams;
Util.log("Looping UnpackedStreamSizes Begin", 1);
UnpackedStreamSizes = new ulong[outStreams];
for (uint j = 0; j < outStreams; j++)
{
UnpackedStreamSizes[j] = br.ReadEncodedUInt64();
Util.log("unpackedStreamSizes[" + j + "] = " + UnpackedStreamSizes[j]);
}
Util.log("Looping UnpackedStreamSizes End", -1);
}
private ulong GetUnpackSize()
{
ulong outStreams = 0;
foreach (Coder coder in Coders)
outStreams += coder.NumInStreams;
for (ulong j = 0; j < outStreams; j++)
{
bool found = false;
foreach (BindPair bindPair in BindPairs)
{
if (bindPair.OutIndex != j)
continue;
found = true;
break;
}
if (!found) return UnpackedStreamSizes[j];
}
return 0;
}
public static void ReadUnPackInfo(BinaryReader br,out Folder[] Folders)
{
Folders = null;
Util.log("Begin : ReadUnPackInfo", 1);
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
switch (hp)
{
case HeaderProperty.kFolder:
{
ulong numFolders = br.ReadEncodedUInt64();
Util.log("NumFolders = " + numFolders);
Folders = new Folder[numFolders];
byte external = br.ReadByte();
Util.log("External = " + external);
switch (external)
{
case 0:
{
Util.log("Looping Folders Begin", 1);
for (uint i = 0; i < numFolders; i++)
{
Util.log("Looping Folders : " + i);
Folders[i] = new Folder();
Folders[i].ReadFolder(br);
}
Util.log("Looping Folders End", -1);
break;
}
case 1:
throw new NotSupportedException("External flag");
}
continue;
}
case HeaderProperty.kCodersUnPackSize:
{
Util.log("Looping Folders Begin", 1);
for (uint i = 0; i < Folders.Length; i++)
{
Util.log("Looping Folders : " + i);
Folders[i].ReadUnpackedStreamSize(br);
}
Util.log("Looping Folders End", -1);
continue;
}
case HeaderProperty.kCRC:
{
uint?[] crcs;
Util.log("Looping CRC Begin", 1);
Util.UnPackCRCs(br,(ulong) Folders.Length, out crcs);
for (int i = 0; i < Folders.Length; i++)
{
Folders[i].UnpackCRC = crcs[i];
Util.log("Folder[" + i + "].UnpackCRC = " + (Folders[i].UnpackCRC ?? 0).ToString("X"));
}
Util.log("Looping CRC End", -1);
continue;
}
case HeaderProperty.kEnd:
Util.log("End : ReadUnPackInfo", -1);
return;
default:
throw new Exception(hp.ToString());
}
}
}
public static void ReadSubStreamsInfo(BinaryReader br,ref Folder[] Folders)
{
Util.log("Begin : ReadSubStreamsInfo", 1);
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
switch (hp)
{
case HeaderProperty.kNumUnPackStream:
{
Util.log("Looping Folders Begin", 1);
for (int f = 0; f < Folders.Length; f++)
{
int numStreams = (int)br.ReadEncodedUInt64();
Util.log("Folders[" + f + "].Length=" + numStreams);
Folders[f].UnpackedStreamInfo = new UnpackedStreamInfo[numStreams];
for (int i = 0; i < numStreams; i++)
Folders[f].UnpackedStreamInfo[i] = new UnpackedStreamInfo();
}
Util.log("Looping Folders End", -1);
continue;
}
case HeaderProperty.kSize:
{
Util.log("Looping Folders Begin", 1);
for (int f = 0; f < Folders.Length; f++)
{
Folder folder = Folders[f];
if (folder.UnpackedStreamInfo.Length == 0)
{
Util.log("Folder size is Zero for " + f + " Begin");
continue;
}
Util.log("Looping Folder UnpackedStreams" + f + " : " + (folder.UnpackedStreamInfo.Length - 1), 1);
ulong sum = 0;
for (int i = 0; i < folder.UnpackedStreamInfo.Length - 1; i++)
{
ulong size = br.ReadEncodedUInt64();
folder.UnpackedStreamInfo[i].UnpackedSize = size;
Util.log("UnpackedStreams[" + i + "].UnpackedSize = " + folder.UnpackedStreamInfo[i].UnpackedSize);
sum += size;
}
Util.log("Looping Folder UnpackedStreams " + f + " End", -1);
Util.log("Sum : " + sum + " : Folder[" + f + "].GetUnpackSize()=" + Folders[f].GetUnpackSize());
folder.UnpackedStreamInfo[folder.UnpackedStreamInfo.Length - 1].UnpackedSize = folder.GetUnpackSize() - sum;
Util.log("UnpackedStreams[" + (folder.UnpackedStreamInfo.Length - 1) + "].UnpackedSize = " + folder.UnpackedStreamInfo[folder.UnpackedStreamInfo.Length - 1].UnpackedSize);
}
Util.log("Looping Folders End", -1);
continue;
}
case HeaderProperty.kCRC:
{
ulong numCRC = 0;
foreach (var folder in Folders)
{
if (folder.UnpackedStreamInfo == null)
{
folder.UnpackedStreamInfo = new UnpackedStreamInfo[1];
folder.UnpackedStreamInfo[0] = new UnpackedStreamInfo();
folder.UnpackedStreamInfo[0].UnpackedSize = folder.GetUnpackSize();
}
if (folder.UnpackedStreamInfo.Length != 1 || !folder.UnpackCRC.HasValue)
numCRC += (ulong)folder.UnpackedStreamInfo.Length;
}
Util.log("Reading CRC Total : " + numCRC);
int crcIndex = 0;
uint?[] crc;
Util.UnPackCRCs(br, numCRC, out crc);
Util.log("Looping Folders Begin", 1);
for (uint i = 0; i < Folders.Length; i++)
{
Folder folder = Folders[i];
if (folder.UnpackedStreamInfo.Length == 1 && folder.UnpackCRC.HasValue)
{
folder.UnpackedStreamInfo[0].Crc = folder.UnpackCRC;
Util.log("UnpackedStreams[0].Crc = " + folder.UnpackedStreamInfo[0].Crc);
}
else
{
Util.log("Looping Folder UnpackedStreams" + i + " : " + (Folders[i].UnpackedStreamInfo.Length), 1);
for (uint j = 0; j < folder.UnpackedStreamInfo.Length; j++, crcIndex++)
{
folder.UnpackedStreamInfo[j].Crc = crc[crcIndex];
Util.log("UnpackedStreams[" + j + "].Crc = " + (folder.UnpackedStreamInfo[j].Crc ?? 0).ToString("X"));
}
Util.log("Looping Folder UnpackedStreams " + i + " End", -1);
}
}
Util.log("Looping Folders End", -1);
continue;
}
case HeaderProperty.kEnd:
Util.log("End : ReadSubStreamsInfo", -1);
return;
default:
throw new Exception(hp.ToString());
}
}
}
private void WriteFolder(BinaryWriter bw)
{
ulong numCoders = (ulong)Coders.Length;
bw.WriteEncodedUInt64(numCoders);
for (ulong i=0;i<numCoders;i++)
Coders[i].Write(bw);
ulong numBindingPairs =BindPairs==null?0: (ulong) BindPairs.Length;
for(ulong i=0;i<numBindingPairs;i++)
BindPairs[i].Write(bw);
//need to look at PAckedStreamIndices but don't need them for basic writing I am doing
}
private void WriteUnpackedStreamSize(BinaryWriter bw)
{
ulong numUnpackedStreamSizes =(ulong) UnpackedStreamSizes.Length;
for (ulong i = 0; i < numUnpackedStreamSizes; i++)
bw.WriteEncodedUInt64(UnpackedStreamSizes[i]);
}
public static void WriteUnPackInfo(BinaryWriter bw, Folder[] Folders)
{
bw.Write((byte)HeaderProperty.kUnPackInfo);
bw.Write((byte)HeaderProperty.kFolder);
ulong numFolders = (ulong)Folders.Length;
bw.WriteEncodedUInt64(numFolders);
bw.Write((byte)0); //External Flag
for (ulong i = 0; i < numFolders; i++)
Folders[i].WriteFolder(bw);
bw.Write((byte)HeaderProperty.kCodersUnPackSize);
for (ulong i = 0; i < numFolders; i++)
Folders[i].WriteUnpackedStreamSize(bw);
if (Folders[0].UnpackCRC != null)
{
bw.Write((byte)HeaderProperty.kCRC);
throw new NotImplementedException();
}
bw.Write((byte)HeaderProperty.kEnd);
}
public static void WriteSubStreamsInfo(BinaryWriter bw, Folder[] Folders)
{
bw.Write((byte)HeaderProperty.kSubStreamsInfo);
bw.Write((byte)HeaderProperty.kNumUnPackStream);
for (int f = 0; f < Folders.Length; f++)
{
ulong numStreams = (ulong) Folders[f].UnpackedStreamInfo.Length;
bw.WriteEncodedUInt64(numStreams);
}
bw.Write((byte)HeaderProperty.kSize);
for (int f = 0; f < Folders.Length; f++)
{
Folder folder = Folders[f];
for (int i = 0; i < folder.UnpackedStreamInfo.Length - 1; i++)
{
bw.WriteEncodedUInt64(folder.UnpackedStreamInfo[i].UnpackedSize);
}
}
bw.Write((byte)HeaderProperty.kCRC);
bw.Write((byte)1); // crc flags default to true
for (int f = 0; f < Folders.Length; f++)
{
Folder folder = Folders[f];
for (int i = 0; i < folder.UnpackedStreamInfo.Length; i++)
{
bw.Write(Util.uinttobytes(folder.UnpackedStreamInfo[i].Crc));
}
}
bw.Write((byte)HeaderProperty.kEnd);
}
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.IO;
using ROMVault2.SupportedFiles.SevenZip.Compress.LZMA;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class Header
{
public StreamsInfo StreamsInfo;
public FileInfo FileInfo;
public void Read(BinaryReader br)
{
Util.log("Begin : ReadHeader", 1);
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
switch (hp)
{
case HeaderProperty.kMainStreamsInfo:
StreamsInfo = new StreamsInfo();
StreamsInfo.Read(br);
break;
case HeaderProperty.kFilesInfo:
FileInfo = new FileInfo();
FileInfo.Read(br);
break;
case HeaderProperty.kEnd:
Util.log("End : ReadHeader", -1);
return;
default:
throw new Exception(hp.ToString());
}
}
}
private void Write(BinaryWriter bw)
{
bw.Write((byte)HeaderProperty.kHeader);
StreamsInfo.Write(bw);
FileInfo.Write(bw);
bw.Write((byte)HeaderProperty.kEnd);
}
public void WriteHeader(BinaryWriter bw)
{
Write(bw);
}
public static ZipReturn ReadHeaderOrPackedHeader(Stream stream, long baseOffset, out Header header)
{
header = null;
Util.log("Begin : ReadHeaderOrPackedHeader", 1);
BinaryReader br = new BinaryReader(stream);
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
switch (hp)
{
case HeaderProperty.kEncodedHeader:
{
StreamsInfo streamsInfo = new StreamsInfo();
streamsInfo.Read(br);
if (streamsInfo.Folders.Length > 1)
return ZipReturn.ZipUnsupportedCompression;
Folder firstFolder = streamsInfo.Folders[0];
if (firstFolder.Coders.Length > 1)
return ZipReturn.ZipUnsupportedCompression;
byte[] method = firstFolder.Coders[0].Method;
if (!(method.Length == 3 && method[0] == 3 && method[1] == 1 && method[2] == 1)) // LZMA
return ZipReturn.ZipUnsupportedCompression;
stream.Seek(baseOffset + (long)streamsInfo.PackPosition, SeekOrigin.Begin);
using (Decoder decoder = new Decoder())
{
decoder.SetDecoderProperties(firstFolder.Coders[0].Properties);
decoder.SetUpStream(stream);
ZipReturn zr = ReadHeaderOrPackedHeader(decoder, baseOffset, out header);
if (zr != ZipReturn.ZipGood)
return zr;
}
Util.log("End : ReadHeaderOrPackedHeader (Packed)", -1);
return ZipReturn.ZipGood;
}
case HeaderProperty.kHeader:
{
header = new Header();
header.Read(br);
Util.log("End : ReadHeaderOrPackedHeader (UnPacked)", -1);
return ZipReturn.ZipGood;
}
}
return ZipReturn.ZipCenteralDirError;
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class PackedStreamInfo
{
public ulong PackedSize;
public ulong? Crc;
public ulong StreamPosition;
public static void Read(BinaryReader br, out ulong packPosition, out PackedStreamInfo[] packedStreams)
{
Util.log("Begin : ReadPackInfo", 1);
packPosition = br.ReadEncodedUInt64();
Util.log("PackPosition = " + packPosition);
ulong numPackStreams = br.ReadEncodedUInt64();
Util.log("NumPackStreams = " + numPackStreams);
packedStreams = new PackedStreamInfo[numPackStreams];
for (ulong i = 0; i < numPackStreams; i++)
packedStreams[i] = new PackedStreamInfo();
ulong streamPosition = 0;
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
switch (hp)
{
case HeaderProperty.kSize:
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i].StreamPosition = streamPosition;
Util.log("PackdStream[" + i + "].StreamPosition = " + packedStreams[i].StreamPosition);
packedStreams[i].PackedSize = br.ReadEncodedUInt64();
Util.log("PackdStream[" + i + "].PackedSize = " + packedStreams[i].PackedSize);
streamPosition += packedStreams[i].PackedSize;
}
continue;
case HeaderProperty.kCRC:
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i].Crc = br.ReadEncodedUInt64();
Util.log("PackdStream[" + i + "].CRC = " + ((ulong)packedStreams[i].Crc).ToString("X"));
}
continue;
case HeaderProperty.kEnd:
Util.log("End : ReadPackInfo", -1);
return;
default:
throw new Exception(hp.ToString());
}
}
}
public static void Write(BinaryWriter bw,ulong packPosition, PackedStreamInfo[] packedStreams)
{
ulong numPackStreams =(ulong) packedStreams.Length;
bw.Write((byte)HeaderProperty.kPackInfo);
bw.WriteEncodedUInt64(packPosition);
bw.WriteEncodedUInt64(numPackStreams);
bw.Write((byte)HeaderProperty.kSize);
ulong streamPosition = 0;
for (ulong i = 0; i < numPackStreams; i++)
{
packedStreams[i].StreamPosition = streamPosition;
bw.WriteEncodedUInt64(packedStreams[i].PackedSize);
streamPosition += packedStreams[i].PackedSize;
}
// Only checking the first CRC assuming all the reset will be the same
if (packedStreams[0].Crc != null)
{
bw.Write((byte) HeaderProperty.kCRC);
for (ulong i = 0; i < numPackStreams; i++)
bw.WriteEncodedUInt64(packedStreams[i].Crc??0);
}
bw.Write((byte)HeaderProperty.kEnd);
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.IO;
using ROMVault2.SupportedFiles.SevenZip.Common;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
internal class SignatureHeader
{
private static readonly byte[] Signature = {(byte) '7', (byte) 'z', 0xBC, 0xAF, 0x27, 0x1C};
private byte _major;
private byte _minor;
private uint _startHeaderCRC;
public ulong NextHeaderOffset;
public ulong NextHeaderSize;
public uint NextHeaderCRC;
public bool Read(BinaryReader br)
{
Util.log("Begin: Read Header", 1);
byte[] signatureBytes = br.ReadBytes(6);
if (!signatureBytes.Compare(Signature))
{
Util.log("End: Read Header signature Failed", -1);
return false;
}
_major = br.ReadByte();
Util.log("Major = " + _major);
_minor = br.ReadByte();
Util.log("Minor = " + _minor);
_startHeaderCRC = br.ReadUInt32();
Util.log("HeaderCRC = " + _startHeaderCRC.ToString("X"));
long pos = br.BaseStream.Position;
byte[] mainHeader = new byte[8 + 8 + 4];
br.BaseStream.Read(mainHeader, 0, mainHeader.Length);
if (!CRC.VerifyDigest(_startHeaderCRC, mainHeader, 0, (uint)mainHeader.Length))
return false;
br.BaseStream.Seek(pos, SeekOrigin.Begin);
NextHeaderOffset = br.ReadUInt64();
Util.log("NextHeaderOffset = " + NextHeaderOffset);
NextHeaderSize = br.ReadUInt64();
Util.log("NextHeaderSize = " + NextHeaderSize);
NextHeaderCRC = br.ReadUInt32();
Util.log("NextHeaderCRC = " + NextHeaderCRC.ToString("X"));
Util.log("End: Read Header", -1);
return true;
}
private long _crcOffset;
public long BaseOffset { get; private set; }
public void Write(BinaryWriter bw)
{
//SignatureHeader
//~~~~~~~~~~~~~~~
bw.Write(Signature);
//ArchiveVersion
//{
bw.Write((byte) 0); // BYTE Major
bw.Write((byte) 3); // BYTE Minor
//};
_crcOffset = bw.BaseStream.Position;
bw.Write((uint) 0); //HeaderCRC
//StartHeader
//{
bw.Write((ulong) 0); //NextHeaderOffset
bw.Write((ulong) 0); //NextHeaderSize
bw.Write((uint) 0); //NextHeaderCRC
//}
BaseOffset = bw.BaseStream.Position;
}
public void WriteFinal(BinaryWriter bw, ulong headerpos, ulong headerLength, uint headerCRC)
{
long fileEnd = bw.BaseStream.Position;
byte[] sigHeaderBytes;
using (MemoryStream sigHeaderMem = new MemoryStream())
{
using (BinaryWriter sigHeaderBw = new BinaryWriter(sigHeaderMem))
{
sigHeaderBw.Write((ulong) ((long) headerpos - BaseOffset)); //NextHeaderOffset
sigHeaderBw.Write(headerLength); //NextHeaderSize
sigHeaderBw.Write(headerCRC); //NextHeaderCRC
sigHeaderBytes = new byte[sigHeaderMem.Length];
sigHeaderMem.Position = 0;
sigHeaderMem.Read(sigHeaderBytes, 0, sigHeaderBytes.Length);
}
}
CRC sigHeadercrc = new CRC();
sigHeadercrc.Update(sigHeaderBytes, 0, (uint) sigHeaderBytes.Length);
UInt32 sigHeaderCRC = sigHeadercrc.GetDigest();
bw.BaseStream.Position = _crcOffset;
bw.Write(sigHeaderCRC); //Header CRC
bw.Write(sigHeaderBytes);
bw.BaseStream.Seek(fileEnd, SeekOrigin.Begin);
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class StreamsInfo
{
public ulong PackPosition;
public PackedStreamInfo[] PackedStreams;
public Folder[] Folders;
public void Read(BinaryReader br)
{
Util.log("Begin : ReadStreamsInfo", 1);
for (; ; )
{
HeaderProperty hp = (HeaderProperty)br.ReadByte();
Util.log("HeaderProperty = " + hp);
switch (hp)
{
case HeaderProperty.kPackInfo:
PackedStreamInfo.Read(br, out PackPosition, out PackedStreams);
continue;
case HeaderProperty.kUnPackInfo:
Folder.ReadUnPackInfo(br, out Folders);
continue;
case HeaderProperty.kSubStreamsInfo:
Folder.ReadSubStreamsInfo(br, ref Folders);
continue;
case HeaderProperty.kEnd:
Util.log("End : ReadStreamInfo", -1);
return;
default:
throw new Exception(hp.ToString());
}
}
}
public void Write(BinaryWriter bw)
{
bw.Write((byte)HeaderProperty.kMainStreamsInfo);
PackedStreamInfo.Write(bw, PackPosition, PackedStreams);
Folder.WriteUnPackInfo(bw, Folders);
Folder.WriteSubStreamsInfo(bw, Folders);
bw.Write((byte)HeaderProperty.kEnd);
}
}
}

View File

@@ -0,0 +1,8 @@
namespace ROMVault2.SupportedFiles.SevenZip.Structure
{
public class UnpackedStreamInfo
{
public ulong UnpackedSize;
public uint? Crc;
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace ROMVault2.SupportedFiles.SevenZip
{
public class TesterStream : Stream
{
private int pos = 0;
private List<byte> arrByte;
private byte[] testarr;
private int index = 0;
public TesterStream(byte[] test)
{
arrByte=new List<byte>();
testarr = test;
index = 0;
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
for (int i = 0; i < count; i++)
{
buffer[offset + i] = arrByte[pos];
pos += 1;
}
return count;
}
public override void Write(byte[] buffer, int offset, int count)
{
for (int i = 0; i < count; i++)
{
byte test = buffer[i + offset];
arrByte.Add(test);
if (test != testarr[index])
{
Console.WriteLine("Expected ="+testarr[index]+" : Found = "+test);
}
index += 1;
}
}
public override bool CanRead
{
get { throw new NotImplementedException(); }
}
public override bool CanSeek
{
get { throw new NotImplementedException(); }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { return arrByte.Count; }
}
public override long Position { get; set; }
}
}

View File

@@ -0,0 +1,315 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace ROMVault2.SupportedFiles.SevenZip
{
public enum HeaderProperty
{
kEnd,
kHeader,
kArchiveProperties,
kAdditionalStreamsInfo,
kMainStreamsInfo,
kFilesInfo,
kPackInfo,
kUnPackInfo,
kSubStreamsInfo,
kSize,
kCRC,
kFolder,
kCodersUnPackSize,
kNumUnPackStream,
kEmptyStream,
kEmptyFile,
kAnti,
kName,
kCreationTime,
kLastAccessTime,
kLastWriteTime,
kWinAttributes,
kComment,
kEncodedHeader,
kStartPos,
kDummy
}
public static class Util
{
public static readonly Encoding Enc = Encoding.GetEncoding(28591);
private static int indent = 0;
public static void log(string txt, int ind = 0)
{
if (ind < 0) indent += ind;
for (int i = 0; i < indent; i++)
Debug.Write(" ");
Debug.WriteLine(txt);
if (ind == -1)
Debug.WriteLine("");
if (ind > 0) indent += ind;
}
public static void memset(byte[] buffer, int start, byte val, int len)
{
for (int i = 0; i < len; i++)
buffer[start + i] = val;
}
public static void memcpyr(byte[] destBuffer, int destPoint, byte[] sourceBuffer, int sourcePoint, int len)
{
for (int i = len - 1; i >= 0; i--)
destBuffer[destPoint + i] = sourceBuffer[sourcePoint + i];
}
public static bool memcmp(byte[] buffer1, int offset, byte[] buffer2, int len)
{
for (int i = 0; i < len; i++)
{
if (buffer1[offset + i] != buffer2[i])
return false;
}
return true;
}
public static bool Compare(this byte[] b1, byte[] b2)
{
if (b1 == null || b2 == null) return false;
if (b1.Length != b2.Length) return false;
for (int i = 0; i < b1.Length; i++)
if (b1[i] != b2[i]) return false;
return true;
}
public static ulong ReadEncodedUInt64(this BinaryReader br)
{
byte mask = 0x80;
int i;
byte firstByte = br.ReadByte();
ulong value = 0;
for (i = 0; i < 8; i++)
{
if ((firstByte & mask) == 0)
{
ulong highPart = (ulong)(firstByte & (mask - 1));
value += (highPart << (8 * i));
return value;
}
byte b = br.ReadByte();
value |= ((ulong)b << (8 * i));
mask >>= 1;
}
return value;
}
public static void WriteEncodedUInt64(this BinaryWriter bw, ulong value)
{
byte firstByte = 0;
byte mask = 0x80;
int i;
for (i = 0; i < 8; i++)
{
if (value < ((ulong)(1) << (7 * (i + 1))))
{
firstByte |= (byte)(value >> (8 * i));
break;
}
firstByte |= mask;
mask >>= 1;
}
bw.Write(firstByte);
for (; i > 0; i--)
{
bw.Write((byte)value);
value >>= 8;
}
}
public static string ReadName(this BinaryReader br)
{
StringBuilder stringBuilder = new StringBuilder();
for (; ; )
{
char c = (char)br.ReadUInt16();
if (c == 0) return stringBuilder.ToString();
stringBuilder.Append(c);
}
}
public static void WriteName(this BinaryWriter bw, string name)
{
char[] chars = name.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
bw.Write((UInt16)chars[i]);
}
bw.Write((UInt16)0);
}
public static void UnPackCRCs(BinaryReader br, ulong numItems, out uint?[] digests)
{
bool[] digestsDefined = ReadBoolFlagsDefaultTrue(br, numItems);
digests = new uint?[numItems];
for (ulong i = 0; i < numItems; i++)
{
if (digestsDefined[i])
{
digests[i] = br.ReadUInt32();
}
}
}
private static bool[] ReadBoolFlagsDefaultTrue(BinaryReader br, ulong numItems)
{
byte allAreDefined = br.ReadByte();
if (allAreDefined == 0)
{
return ReadBoolFlags(br, numItems);
}
bool[] flags = new bool[numItems];
for (ulong i = 0; i < numItems; i++)
{
flags[i] = true;
}
return flags;
}
public static bool[] ReadBoolFlags(BinaryReader br, ulong numItems)
{
byte b = 0;
byte mask = 0;
bool[] flags = new bool[numItems];
for (ulong i = 0; i < numItems; i++)
{
if (mask == 0)
{
b = br.ReadByte();
mask = 0x80;
}
flags[i] = ((b & mask) != 0);
mask >>= 1;
}
return flags;
}
public static bool[] ReadBoolFlags2(BinaryReader br, ulong numItems)
{
byte allAreDefined = br.ReadByte();
if (allAreDefined == 0)
return ReadBoolFlags(br, numItems);
bool[] flags = new bool[numItems];
for (ulong i = 0; i < numItems; i++)
flags[i] = true;
return flags;
}
public static void WriteUint32Def(BinaryWriter br, uint[] values)
{
br.WriteEncodedUInt64((ulong)(values.Length * 4 + 2));
br.Write((byte)1);
br.Write((byte)0);
for (int i = 0; i < values.Length; i++)
br.Write(values[i]);
}
public static uint[] ReadUInt32Def(BinaryReader br, ulong numItems)
{
uint[] v = new uint[numItems];
bool[] defs = ReadBoolFlags2(br, numItems);
byte tmp = br.ReadByte();
for (ulong i = 0; i < numItems; i++)
v[i] = defs[i] ? br.ReadUInt32() : 0;
return v;
}
public static ulong[] ReadUInt64Def(BinaryReader br, ulong numItems)
{
ulong[] v = new ulong[numItems];
bool[] defs = ReadBoolFlags2(br, numItems);
byte tmp = br.ReadByte();
for (ulong i = 0; i < numItems; i++)
v[i] = defs[i] ? br.ReadUInt64() : 0;
return v;
}
public static void WriteBoolFlags(BinaryWriter bw, bool[] bArray)
{
bw.WriteEncodedUInt64((ulong)((bArray.Length + 7) / 8));
byte mask = 0x80;
byte tmpOut = 0;
for (int i = 0; i < bArray.Length; i++)
{
if (bArray[i])
tmpOut |= mask;
mask >>= 1;
if (mask != 0)
continue;
bw.Write(tmpOut);
mask = 0x80;
tmpOut = 0;
}
if (mask != 0x80)
bw.Write(tmpOut);
}
public static byte[] uinttobytes(uint? crc)
{
if (crc == null) return null;
uint c = (uint)crc;
byte[] b = new byte[4];
b[0] = (byte)((c >> 24) & 0xff);
b[1] = (byte)((c >> 16) & 0xff);
b[2] = (byte)((c >> 8) & 0xff);
b[3] = (byte)((c >> 0) & 0xff);
return b;
}
public static uint? bytestouint(byte[] crc)
{
if (crc == null) return null;
return (uint?)(crc[0] << 24 | (crc[1] << 16) | (crc[2] << 8) | (crc[3] << 0));
}
public static bool ByteArrCompare(byte[] b0, byte[] b1)
{
if (b0 == null || b1 == null)
return false;
if (b0.Length != b1.Length)
return false;
for (int i = 0; i < b0.Length; i++)
{
if (b0[i] != b1[i])
return false;
}
return true;
}
}
}

View File

@@ -18,7 +18,7 @@ using ROMVault2.SupportedFiles.Zip.ZLib;
namespace ROMVault2.SupportedFiles.Zip
{
public class ZipFile
public class ZipFile : ICompress
{
const int Buffersize = 4096 * 128;
private static byte[] _buffer;
@@ -807,7 +807,7 @@ namespace ROMVault2.SupportedFiles.Zip
private ZipStatus _pZipStatus;
private bool _zip64;
public ZipOpenType ZipOpen;
public ZipOpenType ZipOpen { get; private set; }
public ZipStatus ZipStatus { get { return _pZipStatus; } }
@@ -823,7 +823,7 @@ namespace ROMVault2.SupportedFiles.Zip
public byte[] CRC32(int i) { return _localFiles[i].CRC; }
public byte[] MD5(int i) { return _localFiles[i].md5; }
public byte[] SHA1(int i) { return _localFiles[i].sha1; }
~ZipFile()
{

View File

@@ -34,6 +34,7 @@ namespace ROMVault2.SupportedFiles
ZipErrorReadingFile,
ZipErrorTimeStamp,
ZipErrorRollBackFile,
ZipTryingToAccessADirectory,
ZipUntested
}

View File

@@ -19,6 +19,8 @@ namespace ROMVault2.Utils
return FileType.Dir;
case FileType.ZipFile:
return FileType.Zip;
case FileType.SevenZipFile:
return FileType.SevenZip;
}
return FileType.Zip;
}
@@ -31,13 +33,15 @@ namespace ROMVault2.Utils
return FileType.File;
case FileType.Zip:
return FileType.ZipFile;
case FileType.SevenZip:
return FileType.SevenZipFile;
}
return FileType.Zip;
}
public static bool isCompressedDir(FileType fileType)
{
return (fileType == FileType.Zip);
return (fileType == FileType.Zip || fileType==FileType.SevenZip);
}
public static RvBase GetRvType(FileType fileType)
@@ -46,9 +50,11 @@ namespace ROMVault2.Utils
{
case FileType.Dir:
case FileType.Zip:
case FileType.SevenZip:
return new RvDir(fileType);
case FileType.File:
case FileType.ZipFile:
case FileType.SevenZipFile:
return new RvFile(fileType);
default:
throw new Exception("Unknown file type");

View File

@@ -11,10 +11,6 @@ namespace ROMVault2
{
public static class rvImages
{
private static List<string> names;
private static List<Bitmap> images;
public static Bitmap GetBitmap(string bitmapName)
{
object bmObj = rvImages1.ResourceManager.GetObject(bitmapName);
@@ -25,32 +21,5 @@ namespace ROMVault2
return bm;
}
public static Bitmap TickBoxDisabled
{
get { return GetBitmap("TickBoxDisabled"); }
}
public static Bitmap TickBoxTicked
{
get { return GetBitmap("TickBoxTicked"); }
}
public static Bitmap TickBoxUnTicked
{
get { return GetBitmap("TickBoxUnTicked"); }
}
public static Bitmap ExpandBoxMinus
{
get { return GetBitmap("ExpandBoxMinus"); }
}
public static Bitmap ExpandBoxPlus
{
get { return GetBitmap("ExpandBoxPlus"); }
}
public static Bitmap romvaultTZ
{
get { return GetBitmap("romvaultTZ"); }
}
}
}

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34011
// Runtime Version:4.0.30319.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -60,6 +60,56 @@ namespace ROMVault2 {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap btnFindFixes_BackgroundImage {
get {
object obj = ResourceManager.GetObject("btnFindFixes_BackgroundImage", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap btnFixFiles_BackgroundImage {
get {
object obj = ResourceManager.GetObject("btnFixFiles_BackgroundImage", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap btnReport_BackgroundImage {
get {
object obj = ResourceManager.GetObject("btnReport_BackgroundImage", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap btnScanRoms_BackgroundImage {
get {
object obj = ResourceManager.GetObject("btnScanRoms_BackgroundImage", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap btnUpdateDats_BackgroundImage {
get {
object obj = ResourceManager.GetObject("btnUpdateDats_BackgroundImage", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -610,6 +660,56 @@ namespace ROMVault2 {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SevenZipDirCorrect {
get {
object obj = ResourceManager.GetObject("SevenZipDirCorrect", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SevenZipDirInToSort {
get {
object obj = ResourceManager.GetObject("SevenZipDirInToSort", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SevenZipDirMissing {
get {
object obj = ResourceManager.GetObject("SevenZipDirMissing", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SevenZipDirUnknown {
get {
object obj = ResourceManager.GetObject("SevenZipDirUnknown", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap SevenZipTZ {
get {
object obj = ResourceManager.GetObject("SevenZipTZ", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

File diff suppressed because it is too large Load Diff

View File

@@ -170,7 +170,7 @@ namespace ROMVault2
if (!pTree.Tree.RExpand.IsEmpty)
if (pTree.Tree.RExpand.IntersectsWith(t))
{
g.DrawImage(pTree.Tree.TreeExpanded ? rvImages.ExpandBoxMinus : rvImages.ExpandBoxPlus, RSub(pTree.Tree.RExpand, _hScroll, _vScroll));
g.DrawImage(pTree.Tree.TreeExpanded ? rvImages1.ExpandBoxMinus : rvImages1.ExpandBoxPlus, RSub(pTree.Tree.RExpand, _hScroll, _vScroll));
}
@@ -179,13 +179,13 @@ namespace ROMVault2
switch (pTree.Tree.Checked)
{
case RvTreeRow.TreeSelect.Disabled:
g.DrawImage(rvImages.TickBoxDisabled, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
g.DrawImage(rvImages1.TickBoxDisabled, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
break;
case RvTreeRow.TreeSelect.UnSelected:
g.DrawImage(rvImages.TickBoxUnTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
g.DrawImage(rvImages1.TickBoxUnTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
break;
case RvTreeRow.TreeSelect.Selected:
g.DrawImage(rvImages.TickBoxTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
g.DrawImage(rvImages1.TickBoxTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll));
break;
}
}