/****************************************************** * 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 lstDir) { GetSelectedDirList(ref lstDir, DB.DirTree); } private static void GetSelectedDirList(ref List 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 lstFiles) { lstFiles = new List(); GetSelectedFilesSortCRCSize(ref lstFiles, DB.DirTree, true); RomSortCRCSize(lstFiles); } private static void GetSelectedFilesSortCRCSize(ref List 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 lstFiles) { RomSortCRCSize(0, lstFiles.Count, lstFiles); } private static void RomSortCRCSize(int intBase, int intTop, List 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 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 lstFiles, out List lstFilesOut) { lstFilesOut = new List(); 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 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 lstFiles) { lstFiles = new List(); GetSelectedFilesSortSHA1CHD(ref lstFiles, DB.DirTree, true); RomSortSHA1CHD(lstFiles); } private static void GetSelectedFilesSortSHA1CHD(ref List 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 lstFiles) { RomSortSHA1CHD(0, lstFiles.Count, lstFiles); } private static void RomSortSHA1CHD(int intBase, int intTop, List 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 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 lstFiles, out List lstFilesOut) { lstFilesOut = new List(); 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; } } } }