508 lines
17 KiB
C#
508 lines
17 KiB
C#
/******************************************************
|
|
* ROMVault2 is written by Gordon J. *
|
|
* Contact gordon@romvault.com *
|
|
* Copyright 2013 *
|
|
******************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using ROMVault2.RvDB;
|
|
using ROMVault2.Utils;
|
|
|
|
namespace ROMVault2
|
|
{
|
|
public enum EFile
|
|
{
|
|
Keep,
|
|
Delete
|
|
}
|
|
|
|
public static class DBHelper
|
|
{
|
|
|
|
|
|
private static readonly byte[] ZeroByteMD5;
|
|
private static readonly byte[] ZeroByteSHA1;
|
|
private static readonly byte[] ZeroByteCRC;
|
|
|
|
static DBHelper()
|
|
{
|
|
ZeroByteMD5 = VarFix.CleanMD5SHA1("d41d8cd98f00b204e9800998ecf8427e", 32);
|
|
ZeroByteSHA1 = VarFix.CleanMD5SHA1("da39a3ee5e6b4b0d3255bfef95601890afd80709", 40);
|
|
ZeroByteCRC = VarFix.CleanMD5SHA1("00000000", 8);
|
|
}
|
|
|
|
|
|
|
|
public static void GetSelectedDirList(ref List<RvDir> lstDir)
|
|
{
|
|
GetSelectedDirList(ref lstDir, DB.DirTree);
|
|
}
|
|
private static void GetSelectedDirList(ref List<RvDir> lstDir, RvDir thisDir)
|
|
{
|
|
for (int i = 0; i < thisDir.ChildCount; i++)
|
|
{
|
|
if (thisDir.DatStatus != DatStatus.InDatCollect) continue;
|
|
RvDir tDir = thisDir.Child(i) as RvDir;
|
|
if (tDir == null) continue;
|
|
if (tDir.Tree == null) continue;
|
|
if (tDir.Tree.Checked == RvTreeRow.TreeSelect.Selected)
|
|
lstDir.Add(tDir);
|
|
|
|
GetSelectedDirList(ref lstDir, tDir);
|
|
}
|
|
}
|
|
|
|
|
|
public static int CompareName(RvBase var1, RvBase var2)
|
|
{
|
|
int retv = TrrntZipStringCompare(var1.Name, var2.Name);
|
|
if (retv != 0) return retv;
|
|
|
|
FileType f1 = var1.FileType;
|
|
FileType f2 = var2.FileType;
|
|
|
|
if (f1 == FileType.ZipFile)
|
|
{
|
|
if (f2 != FileType.ZipFile)
|
|
ReportError.SendAndShow("Incompatible Compare type");
|
|
|
|
return Math.Sign(String.Compare(var1.Name, var2.Name, StringComparison.Ordinal));
|
|
}
|
|
return f1.CompareTo(f2);
|
|
}
|
|
|
|
private static int TrrntZipStringCompare(string string1, string string2)
|
|
{
|
|
char[] bytes1 = string1.ToCharArray();
|
|
char[] bytes2 = string2.ToCharArray();
|
|
|
|
int pos1 = 0;
|
|
int pos2 = 0;
|
|
|
|
for (; ; )
|
|
{
|
|
if (pos1 == bytes1.Length)
|
|
return ((pos2 == bytes2.Length) ? 0 : -1);
|
|
if (pos2 == bytes2.Length)
|
|
return 1;
|
|
|
|
int byte1 = bytes1[pos1++];
|
|
int byte2 = bytes2[pos2++];
|
|
|
|
if (byte1 >= 65 && byte1 <= 90) byte1 += 0x20;
|
|
if (byte2 >= 65 && byte2 <= 90) byte2 += 0x20;
|
|
|
|
if (byte1 < byte2)
|
|
return -1;
|
|
if (byte1 > byte2)
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int DatCompare(RvDat var1, RvDat var2)
|
|
{
|
|
int retv = Math.Sign(string.Compare(var1.GetData(RvDat.DatData.DatFullName), var2.GetData(RvDat.DatData.DatFullName), StringComparison.CurrentCultureIgnoreCase));
|
|
if (retv != 0) return retv;
|
|
|
|
|
|
retv = Math.Sign(var1.TimeStamp.CompareTo(var2.TimeStamp));
|
|
if (retv != 0) return retv;
|
|
|
|
retv = Math.Sign(var1.AutoAddDirectory.CompareTo(var2.AutoAddDirectory));
|
|
if (retv != 0) return retv;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static string GetRealPath(string rootPath)
|
|
{
|
|
string strFullPath = "";
|
|
int lenFound = 0;
|
|
foreach (DirMap dirPathMap in Settings.DirPathMap)
|
|
{
|
|
string dirKey = dirPathMap.DirKey;
|
|
int dirKeyLen = dirKey.Length;
|
|
|
|
if (rootPath.Length >= dirKeyLen)
|
|
if (String.Compare(rootPath.Substring(0, dirKeyLen), dirKey, StringComparison.Ordinal) == 0)
|
|
{
|
|
if (lenFound < dirKeyLen)
|
|
{
|
|
string dirPath = dirPathMap.DirPath;
|
|
lenFound = dirKeyLen;
|
|
strFullPath = rootPath == dirKey ? dirPath : IO.Path.Combine(dirPath, rootPath.Substring(dirKeyLen + 1));
|
|
}
|
|
}
|
|
}
|
|
return strFullPath;
|
|
}
|
|
|
|
public static string GetDatPath(string rootPath)
|
|
{
|
|
if (rootPath == "")
|
|
return Settings.DatRoot;
|
|
if (rootPath.Substring(0, 6) == "ToSort")
|
|
return "Error";
|
|
if (rootPath.Substring(0, 8) == "RomVault")
|
|
return Settings.DatRoot + rootPath.Substring(8);
|
|
|
|
return Settings.DatRoot;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static void GetSelectedFilesSortCRCSize(out List<RvFile> lstFiles)
|
|
{
|
|
lstFiles = new List<RvFile>();
|
|
GetSelectedFilesSortCRCSize(ref lstFiles, DB.DirTree, true);
|
|
RomSortCRCSize(lstFiles);
|
|
}
|
|
private static void GetSelectedFilesSortCRCSize(ref List<RvFile> lstFiles, RvBase val, bool selected)
|
|
{
|
|
if (selected)
|
|
{
|
|
RvFile rvFile = val as RvFile;
|
|
if (rvFile != null)
|
|
{
|
|
if ((rvFile.Size != null && rvFile.CRC != null) || rvFile.Size == 0)
|
|
lstFiles.Add(rvFile);
|
|
}
|
|
}
|
|
|
|
RvDir rvVal = val as RvDir;
|
|
if (rvVal == null) return;
|
|
|
|
for (int i = 0; i < rvVal.ChildCount; i++)
|
|
{
|
|
bool nextSelect = selected;
|
|
if (rvVal.Tree != null)
|
|
nextSelect = rvVal.Tree.Checked == RvTreeRow.TreeSelect.Selected;
|
|
GetSelectedFilesSortCRCSize(ref lstFiles, rvVal.Child(i), nextSelect);
|
|
}
|
|
}
|
|
|
|
private static void RomSortCRCSize(List<RvFile> lstFiles)
|
|
{
|
|
RomSortCRCSize(0, lstFiles.Count, lstFiles);
|
|
}
|
|
private static void RomSortCRCSize(int intBase, int intTop, List<RvFile> lstFiles)
|
|
{
|
|
if ((intTop - intBase) <= 1) return;
|
|
int intMiddle = (intTop + intBase) / 2;
|
|
|
|
if ((intMiddle - intBase) > 1)
|
|
RomSortCRCSize(intBase, intMiddle, lstFiles);
|
|
|
|
if ((intTop - intMiddle) > 1)
|
|
RomSortCRCSize(intMiddle, intTop, lstFiles);
|
|
|
|
int intBottomSize = intMiddle - intBase;
|
|
int intTopSize = intTop - intMiddle;
|
|
|
|
RvFile[] lstBottom = new RvFile[intBottomSize];
|
|
RvFile[] lstTop = new RvFile[intTopSize];
|
|
|
|
for (int intloop = 0; intloop < intBottomSize; intloop++)
|
|
lstBottom[intloop] = lstFiles[intBase + intloop];
|
|
|
|
for (int intloop = 0; intloop < intTopSize; intloop++)
|
|
lstTop[intloop] = lstFiles[intMiddle + intloop];
|
|
|
|
int intBottomCount = 0;
|
|
int intTopCount = 0;
|
|
int intCount = intBase;
|
|
|
|
while (intBottomCount < intBottomSize && intTopCount < intTopSize)
|
|
{
|
|
if (RomSortCRCSizeFunc(lstBottom[intBottomCount], lstTop[intTopCount]) < 1)
|
|
{
|
|
lstFiles[intCount] = lstBottom[intBottomCount];
|
|
intCount++;
|
|
intBottomCount++;
|
|
}
|
|
else
|
|
{
|
|
lstFiles[intCount] = lstTop[intTopCount];
|
|
intCount++;
|
|
intTopCount++;
|
|
}
|
|
}
|
|
|
|
while (intBottomCount < intBottomSize)
|
|
{
|
|
lstFiles[intCount] = lstBottom[intBottomCount];
|
|
intCount++;
|
|
intBottomCount++;
|
|
}
|
|
while (intTopCount < intTopSize)
|
|
{
|
|
lstFiles[intCount] = lstTop[intTopCount];
|
|
intCount++;
|
|
intTopCount++;
|
|
}
|
|
}
|
|
private static int RomSortCRCSizeFunc(RvFile a, RvFile b)
|
|
{
|
|
int retv = ArrByte.iCompare(a.CRC, b.CRC);
|
|
|
|
if (retv == 0)
|
|
retv = ULong.iCompare(a.Size, b.Size);
|
|
|
|
return retv;
|
|
}
|
|
|
|
public static int RomSearchCRCSize(RvFile tRom, List<RvFile> lstFiles, out int index)
|
|
{
|
|
if (lstFiles.Count == 0)
|
|
{
|
|
index = 0;
|
|
return -1;
|
|
}
|
|
|
|
// this one below method will always return the first item in a list if there is more than one matching result.
|
|
int intBottom = -1;
|
|
int intTop = lstFiles.Count - 1;
|
|
|
|
while (intBottom + 1 < intTop)
|
|
{
|
|
int intMid = (intBottom + intTop + 1) / 2;
|
|
|
|
int intRes = RomSortCRCSizeFunc(lstFiles[intMid], tRom);
|
|
if (intRes >= 0)
|
|
intTop = intMid;
|
|
else
|
|
intBottom = intMid;
|
|
|
|
}
|
|
intBottom++;
|
|
index = intBottom;
|
|
return RomSortCRCSizeFunc(lstFiles[intBottom], tRom);
|
|
}
|
|
|
|
// find all of the files that we think we have that match the needed CRC and Size.
|
|
public static void RomSearchFindFixes(RvFile tRom, List<RvFile> lstFiles, out List<RvFile> lstFilesOut)
|
|
{
|
|
lstFilesOut = new List<RvFile>();
|
|
if (tRom.CRC == null || tRom.Size == null)
|
|
return;
|
|
|
|
int intIndex;
|
|
int intRes = RomSearchCRCSize(tRom, lstFiles, out intIndex);
|
|
|
|
while (intRes == 0)
|
|
{
|
|
if (lstFiles[intIndex].GotStatus == GotStatus.Got && FindFixes.CheckIfMissingFileCanBeFixedByGotFile(tRom, lstFiles[intIndex]))
|
|
lstFilesOut.Add(lstFiles[intIndex]);
|
|
|
|
intIndex++;
|
|
intRes = intIndex < lstFiles.Count ? RomSortCRCSizeFunc(lstFiles[intIndex], tRom) : 1;
|
|
}
|
|
}
|
|
|
|
// find all of the files that we think we have that match the needed CRC and Size.
|
|
public static void RomSearchFindMatchingFiles(RvFile tRom, List<RvFile> lstFiles, out int startIndex, out int length)
|
|
{
|
|
int intIndex;
|
|
int intRes = RomSearchCRCSize(tRom, lstFiles, out intIndex);
|
|
startIndex = intIndex;
|
|
|
|
while (intRes == 0)
|
|
{
|
|
intIndex++;
|
|
intRes = intIndex < lstFiles.Count ? RomSortCRCSizeFunc(lstFiles[intIndex], tRom) : 1;
|
|
}
|
|
length = intIndex - startIndex;
|
|
}
|
|
|
|
|
|
public static bool IsZeroLengthFile(RvFile tFile)
|
|
{
|
|
if (tFile.MD5 != null)
|
|
{
|
|
if (!ArrByte.bCompare(tFile.MD5, ZeroByteMD5))
|
|
return false;
|
|
}
|
|
|
|
if (tFile.SHA1 != null)
|
|
{
|
|
if (!ArrByte.bCompare(tFile.SHA1, ZeroByteSHA1))
|
|
return false;
|
|
}
|
|
|
|
if (tFile.CRC != null)
|
|
if (!ArrByte.bCompare(tFile.CRC, ZeroByteCRC))
|
|
return false;
|
|
|
|
return tFile.Size == 0;
|
|
}
|
|
|
|
public static bool RomFromSameGame(RvFile a, RvFile b)
|
|
{
|
|
if (a.Parent == null)
|
|
return false;
|
|
if (b.Parent == null)
|
|
return false;
|
|
|
|
return a.Parent == b.Parent;
|
|
}
|
|
|
|
|
|
|
|
public static void GetSelectedFilesSortSHA1CHD(out List<RvFile> lstFiles)
|
|
{
|
|
lstFiles = new List<RvFile>();
|
|
GetSelectedFilesSortSHA1CHD(ref lstFiles, DB.DirTree, true);
|
|
RomSortSHA1CHD(lstFiles);
|
|
}
|
|
private static void GetSelectedFilesSortSHA1CHD(ref List<RvFile> lstFiles, RvBase val, bool selected)
|
|
{
|
|
if (selected)
|
|
{
|
|
RvFile rvFile = val as RvFile;
|
|
if (rvFile != null)
|
|
{
|
|
if (rvFile.SHA1CHD != null)
|
|
lstFiles.Add(rvFile);
|
|
}
|
|
}
|
|
|
|
RvDir rvVal = val as RvDir;
|
|
if (rvVal == null) return;
|
|
|
|
for (int i = 0; i < rvVal.ChildCount; i++)
|
|
{
|
|
bool nextSelect = selected;
|
|
if (rvVal.Tree != null)
|
|
nextSelect = rvVal.Tree.Checked == RvTreeRow.TreeSelect.Selected;
|
|
GetSelectedFilesSortSHA1CHD(ref lstFiles, rvVal.Child(i), nextSelect);
|
|
}
|
|
}
|
|
|
|
private static void RomSortSHA1CHD(List<RvFile> lstFiles)
|
|
{
|
|
RomSortSHA1CHD(0, lstFiles.Count, lstFiles);
|
|
}
|
|
private static void RomSortSHA1CHD(int intBase, int intTop, List<RvFile> lstFiles)
|
|
{
|
|
if ((intTop - intBase) <= 1) return;
|
|
int intMiddle = (intTop + intBase) / 2;
|
|
|
|
if ((intMiddle - intBase) > 1)
|
|
RomSortSHA1CHD(intBase, intMiddle, lstFiles);
|
|
|
|
if ((intTop - intMiddle) > 1)
|
|
RomSortSHA1CHD(intMiddle, intTop, lstFiles);
|
|
|
|
int intBottomSize = intMiddle - intBase;
|
|
int intTopSize = intTop - intMiddle;
|
|
|
|
RvFile[] lstBottom = new RvFile[intBottomSize];
|
|
RvFile[] lstTop = new RvFile[intTopSize];
|
|
|
|
for (int intloop = 0; intloop < intBottomSize; intloop++)
|
|
lstBottom[intloop] = lstFiles[intBase + intloop];
|
|
|
|
for (int intloop = 0; intloop < intTopSize; intloop++)
|
|
lstTop[intloop] = lstFiles[intMiddle + intloop];
|
|
|
|
int intBottomCount = 0;
|
|
int intTopCount = 0;
|
|
int intCount = intBase;
|
|
|
|
while (intBottomCount < intBottomSize && intTopCount < intTopSize)
|
|
{
|
|
if (RomSortSHA1CHDFunc(lstBottom[intBottomCount], lstTop[intTopCount]) < 1)
|
|
{
|
|
lstFiles[intCount] = lstBottom[intBottomCount];
|
|
intCount++;
|
|
intBottomCount++;
|
|
}
|
|
else
|
|
{
|
|
lstFiles[intCount] = lstTop[intTopCount];
|
|
intCount++;
|
|
intTopCount++;
|
|
}
|
|
}
|
|
|
|
while (intBottomCount < intBottomSize)
|
|
{
|
|
lstFiles[intCount] = lstBottom[intBottomCount];
|
|
intCount++;
|
|
intBottomCount++;
|
|
}
|
|
while (intTopCount < intTopSize)
|
|
{
|
|
lstFiles[intCount] = lstTop[intTopCount];
|
|
intCount++;
|
|
intTopCount++;
|
|
}
|
|
}
|
|
private static int RomSortSHA1CHDFunc(RvFile a, RvFile b)
|
|
{
|
|
int retv = ArrByte.iCompare(a.SHA1CHD, b.SHA1CHD);
|
|
|
|
return retv;
|
|
}
|
|
|
|
|
|
private static int RomSearchSHA1CHD(RvFile tRom, List<RvFile> lstFiles, out int index)
|
|
{
|
|
if (lstFiles.Count == 0)
|
|
{
|
|
index = 0;
|
|
return -1;
|
|
}
|
|
|
|
// this one below method will always return the first item in a list if there is more than one matching result.
|
|
int intBottom = -1;
|
|
int intTop = lstFiles.Count - 1;
|
|
|
|
while (intBottom + 1 < intTop)
|
|
{
|
|
int intMid = (intBottom + intTop + 1) / 2;
|
|
|
|
int intRes = RomSortSHA1CHDFunc(lstFiles[intMid], tRom);
|
|
if (intRes >= 0)
|
|
intTop = intMid;
|
|
else
|
|
intBottom = intMid;
|
|
|
|
}
|
|
intBottom++;
|
|
index = intBottom;
|
|
return RomSortSHA1CHDFunc(lstFiles[intBottom], tRom);
|
|
}
|
|
|
|
|
|
// find all of the files that we have that match the needed SHA1 CHD.
|
|
public static void RomSearchFindFixesSHA1CHD(RvFile tRom, List<RvFile> lstFiles, out List<RvFile> lstFilesOut)
|
|
{
|
|
lstFilesOut = new List<RvFile>();
|
|
if (tRom.SHA1CHD == null)
|
|
return;
|
|
|
|
int intIndex;
|
|
int intRes = RomSearchSHA1CHD(tRom, lstFiles, out intIndex);
|
|
|
|
while (intRes == 0)
|
|
{
|
|
if (lstFiles[intIndex].GotStatus == GotStatus.Got)
|
|
lstFilesOut.Add(lstFiles[intIndex]);
|
|
|
|
intIndex++;
|
|
intRes = intIndex < lstFiles.Count ? RomSortSHA1CHDFunc(lstFiles[intIndex], tRom) : 1;
|
|
}
|
|
}
|
|
}
|
|
}
|