static bool VerifyFile(Stream ms, string infilepath = "") { var c = new CR2WFile();// { FileName = fileEntry.NameOrHash }; var originalbytes = StreamExtensions.ToByteArray(ms); ms.Seek(0, SeekOrigin.Begin); var readResult = c.Read(ms); switch (readResult) { case EFileReadErrorCodes.NoCr2w: case EFileReadErrorCodes.UnsupportedVersion: break; case EFileReadErrorCodes.NoError: var hasAdditionalBytes = c.AdditionalCr2WFileBytes != null && c.AdditionalCr2WFileBytes.Any(); var oldst = c.StringDictionary.Values.ToList(); var newst = c.GenerateStringtable().Item1.Values.ToList(); var compstr = "OLD,NEW"; var correctStringTable = oldst.Count == newst.Count; // Stringtable test for (int i = 0; i < Math.Max(oldst.Count, newst.Count); i++) { string str1 = ""; string str2 = ""; if (i < oldst.Count) { compstr += oldst[i]; } compstr += ","; if (i < newst.Count) { compstr += newst[i]; } compstr += "\n"; if (str1 != str2) { correctStringTable = false; } } // Binary Equal Test var isBinaryEqual = true; using (var wms = new MemoryStream()) using (var bw = new BinaryWriter(wms)) { c.Write(bw); var newbytes = StreamExtensions.ToByteArray(wms); isBinaryEqual = originalbytes.SequenceEqual(newbytes); if (!isBinaryEqual && !string.IsNullOrEmpty(infilepath)) { File.WriteAllBytes($"{infilepath}.n.bin", newbytes); return(false); } } if (!correctStringTable) { return(false); } return(true); default: throw new ArgumentOutOfRangeException(); } return(false); }
private static int StressTestFile(BundleItem f, ref ConcurrentDictionary <string, string> unknownclasses, ref long totalbytes, ref long unknownbytes, ref Dictionary <string, Tuple <long, long> > chunkstate) { var crw = new CR2WFile(); using (var ms = new MemoryStream()) using (var br = new BinaryReader(ms)) { f.ExtractExistingMMF(ms); ms.Seek(0, SeekOrigin.Begin); #region Reading Test A // reading test crw.Read(br); #endregion #region StringTableTest A.1 // additional tests (var dict, var strings, var nameslist, var importslist) = crw.GenerateStringtable(); var newdictvalues = dict.Values.ToList(); var dictvalues = crw.StringDictionary.Values.ToList(); var diffDictList = dictvalues.Except(newdictvalues).ToList(); bool isclassicalinconsistentw2anims = false; bool isclassicalinconsistentw2phase = false; if (diffDictList.Count != 0) { //w2anims inconsistencies foreach (string str in diffDictList) { if (str == "extAnimEvents" || str == "array:2,0,handle:CExtAnimEventsFile" || str == "CExtAnimEventsFile" || str.Contains("sounds\\") || str.Contains("sound\\")) { isclassicalinconsistentw2anims = true; break; } else { continue; } } //w2phase inconsistencies foreach (string str in diffDictList) { if (str == "@SItem" || str == "SItem" || str == "#CEnvironmentDefinition" || str == "CEnvironmentDefinition") { isclassicalinconsistentw2phase = true; break; } else { continue; } } if (isclassicalinconsistentw2anims) { //throw new InvalidBundleException("Classical inconsistent .w2anims - " + // ".w2animev sound handles left behind in string lists, but actual data is empty"); } else if (isclassicalinconsistentw2phase) { //throw new InvalidBundleException("Inconsistent .w2phase - " + // "secret e3 files"); // skip test B } else { throw new InvalidBundleException(" Generated dictionary not equal actual dictionary."); } } #endregion #region Writing Test B if (isclassicalinconsistentw2phase || isclassicalinconsistentw2anims) { // skip test // add additional fail-safe test? } else { byte[] buffer_testB; byte[] buffer_testB_original; using (var ms_testB = new MemoryStream()) using (var bw_testB = new BinaryWriter(ms_testB)) { crw.Write(bw_testB); buffer_testB = ms_testB.ToArray(); } // compare ms.Seek(0, SeekOrigin.Begin); buffer_testB_original = ms.ToArray(); if (!Enumerable.SequenceEqual(buffer_testB_original, buffer_testB)) { throw new InvalidBundleException(" Generated cr2w file not equal to original file."); } } #endregion } foreach (var ut in crw.UnknownTypes) { unknownclasses.TryAdd(ut, ut); } foreach (var c in crw.Chunks) { var ubsl = c.unknownBytes?.Bytes != null ? c.unknownBytes.Bytes.Length : 0; lock (chunkstate) { if (!chunkstate.ContainsKey(c.REDType)) { chunkstate.Add(c.REDType, new Tuple <long, long>(0, 0)); } var already = chunkstate[c.REDType]; chunkstate[c.REDType] = new Tuple <long, long>( already.Item1 + c.Export.dataSize, already.Item2 + ubsl ); } Interlocked.Add(ref totalbytes, c.Export.dataSize); Interlocked.Add(ref unknownbytes, ubsl); } return(0); }
public static int VerifyTask(string[] path, ulong[] hashes) { var hashService = ServiceLocator.Default.ResolveType <IHashService>(); var CP77_DIR = System.Environment.GetEnvironmentVariable("CP77_DIR", EnvironmentVariableTarget.User); var gameDirectory = new DirectoryInfo(CP77_DIR); var gameArchiveDir = new DirectoryInfo(Path.Combine(gameDirectory.FullName, "archive", "pc", "content")); var bm = new ArchiveManager(gameArchiveDir); if (path != null) { foreach (var s in path) { var hash = FNV1A64HashAlgorithm.HashString(s); if (!hashService.Hashdict.ContainsKey(hash)) { continue; } var file = bm.Files[hash]; foreach (var fileEntry in file) { VerifyFile(fileEntry); } } } if (hashes != null) { foreach (var hash in hashes) { if (!hashService.Hashdict.ContainsKey(hash)) { continue; } var file = bm.Files[hash]; foreach (var fileEntry in file) { VerifyFile(fileEntry); } } } void VerifyFile(FileEntry fileEntry) { if (fileEntry.Archive is not Archive ar) { return; } using var ms = new MemoryStream(); ar.CopyFileToStream(ms, fileEntry.NameHash64, false); var c = new CR2WFile { FileName = fileEntry.NameOrHash }; ms.Seek(0, SeekOrigin.Begin); var readResult = c.Read(ms); switch (readResult) { case EFileReadErrorCodes.NoCr2w: case EFileReadErrorCodes.UnsupportedVersion: break; case EFileReadErrorCodes.NoError: var hasAdditionalBytes = c.AdditionalCr2WFileBytes != null && c.AdditionalCr2WFileBytes.Any(); var oldst = c.StringDictionary.Values.ToList(); var newst = c.GenerateStringtable().Item1.Values.ToList(); var compstr = "OLD,NEW"; var correctStringTable = oldst.Count == newst.Count; // Stringtable test for (int i = 0; i < Math.Max(oldst.Count, newst.Count); i++) { string str1 = ""; string str2 = ""; if (i < oldst.Count) { compstr += oldst[i]; } compstr += ","; if (i < newst.Count) { compstr += newst[i]; } compstr += "\n"; if (str1 != str2) { correctStringTable = false; } } if (!correctStringTable) { Debugger.Break(); } break; default: throw new ArgumentOutOfRangeException(); } } return(1); }