//[DataRow("lang_ar_text.archive")] //[DataRow("lang_cs_text.archive")] //[DataRow("lang_de_text.archive")] //[DataRow("lang_en_text.archive")] //[DataRow("lang_en_voice.archive")] //[DataRow("lang_es-es_text.archive")] //[DataRow("lang_es-mx_text.archive")] //[DataRow("lang_fr_text.archive")] //[DataRow("lang_hu_text.archive")] //[DataRow("lang_it_text.archive")] //[DataRow("lang_ja_text.archive")] //[DataRow("lang_ko_text.archive")] //[DataRow("lang_pl_text.archive")] //[DataRow("lang_pt_text.archive")] //[DataRow("lang_ru_text.archive")] //[DataRow("lang_th_text.archive")] //[DataRow("lang_tr_text.archive")] //[DataRow("lang_zh-cn_text.archive")] //[DataRow("lang_zh-tw_text.archive")] public void Test_Unbundle(string archivename) { var resultDir = Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory); Directory.CreateDirectory(resultDir); var results = new ConcurrentBag <ArchiveTestResult>(); var archiveFullName = Path.Combine(s_gameDirectoryPath, "archive", "pc", "content", archivename); var archive = s_bm.Archives.Lookup(archiveFullName).Value as Archive; Parallel.ForEach(archive.Files, keyvalue => { var(hash, _) = keyvalue; try { using (var ms = new MemoryStream()) { ModTools.ExtractSingleToStream(archive, hash, ms); } results.Add(new ArchiveTestResult() { ArchiveName = archivename, Hash = hash.ToString(), Success = true }); } catch (Exception e) { results.Add(new ArchiveTestResult() { ArchiveName = archivename, Hash = hash.ToString(), Success = false, ExceptionType = e.GetType(), Message = $"{e.Message}" }); } }); var totalCount = archive.Files.Count; // Check success var successCount = results.Count(r => r.Success); var sb = new StringBuilder(); sb.AppendLine($"Successfully unbundled: {successCount} / {totalCount} ({(int)(successCount / (double)totalCount * 100)}%)"); var success = results.All(r => r.Success); if (success) { return; } var msg = $"Successful Writes: {successCount} / {totalCount}. "; Assert.Fail(msg); }
public void DumpExtensionInfo() { var parser = ServiceLocator.Default.ResolveType <Red4ParserService>(); var results = new Dictionary <string, ConcurrentDictionary <string, ulong> >(); foreach (var e in s_groupedFiles) { results.Add(e.Key, new ConcurrentDictionary <string, ulong>()); } var excludedExtensions = new List <string>() { ".wem", ".bin", ".bnk", ".opuspak", ".opusinfo", ".bk2", ".dat" }; // Run Test foreach (var item in s_groupedFiles.Where(_ => !excludedExtensions.Contains(_.Key))) { var ext = item.Key; var files = item.Value; Parallel.ForEach(files, file => { var hash = file.Key; var archive = file.Archive as Archive; try { using var originalMemoryStream = new MemoryStream(); ModTools.ExtractSingleToStream(archive, hash, originalMemoryStream); var originalFile = parser.TryReadRED4FileHeaders(originalMemoryStream); if (originalFile != null) { var c = originalFile.StringDictionary[1]; results[ext].TryAdd(c, 0); } else { } } catch (Exception) { } }); } var resultDir = Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory); Directory.CreateDirectory(resultDir); using var sw = new StringWriter(); foreach (var(key, classes) in results) { sw.WriteLine($"{key}: {string.Join(",", classes.Keys.ToList())}"); } File.WriteAllText(Path.Combine(resultDir, "classes.txt"), sw.ToString()); }
public OpusTools(Archive soundbanks, string modFolder, string rawFolder, bool useMod = false) //audio_2_soundbanks.archive { _soundBanks = soundbanks; _modFolder = new DirectoryInfo(modFolder); _rawFolder = new DirectoryInfo(rawFolder); _isModded = useMod; if (!Directory.Exists(Path.Combine(_modFolder.FullName, "base\\sound\\soundbanks"))) { Directory.CreateDirectory(Path.Combine(_modFolder.FullName, "base\\sound\\soundbanks")); } if (!Directory.Exists(_rawFolder.FullName)) { Directory.CreateDirectory(_rawFolder.FullName); } if (_isModded) { var infoFile = Path.Combine(_modFolder.FullName, "base\\sound\\soundbanks\\sfx_container.opusinfo"); if (File.Exists(infoFile)) { var ms = new MemoryStream(File.ReadAllBytes(infoFile)); var br = new BinaryReader(ms); ms.Position = 0; if (BitConverter.ToString(br.ReadBytes(3)) != "53-4E-44") { _isModded = false; } else { Info = new OpusInfo(ms); } } else { _isModded = false; } } if (!_isModded) { var hash = FNV1A64HashAlgorithm.HashString("base\\sound\\soundbanks\\sfx_container.opusinfo"); var ms = new MemoryStream(); if (_soundBanks.Files.ContainsKey(hash)) { ModTools.ExtractSingleToStream(_soundBanks, hash, ms); Info = new OpusInfo(ms); } else { Info = new OpusInfo(); } } }
public bool ExportOpusUsingHash(uint opusHash) { if (!_isModded) { for (uint i = 0; i < Info.OpusCount; i++) { if (Info.OpusHashes[i] == opusHash) { var containerHash = FNV1A64HashAlgorithm.HashString("base\\sound\\soundbanks\\sfx_container_" + Info.PackIndices[i] + ".opuspak"); var ms = new MemoryStream(); ModTools.ExtractSingleToStream(_soundBanks, containerHash, ms); Info.WriteOpusFromPak(ms, _rawFolder, i); return(true); } if (Info.OpusCount == i + 1) { return(false); } } } else { for (uint i = 0; i < Info.OpusCount; i++) { if (Info.OpusHashes[i] == opusHash) { var pakFile = Path.Combine(_modFolder.FullName, "base\\sound\\soundbanks\\sfx_container_" + Info.PackIndices[i] + ".opuspak"); if (File.Exists(pakFile)) { var ms = new MemoryStream(File.ReadAllBytes(pakFile)); Info.WriteOpusFromPak(ms, _rawFolder, i); return(true); } else { return(false); } } if (Info.OpusCount == i + 1) { return(false); } } } return(false); }
private RawMaterial ContainRawMaterial(CMaterialInstance cMaterialInstance, string Name, List <Archive> archives) { RawMaterial rawMaterial = new RawMaterial(); rawMaterial.Name = Name; rawMaterial.BaseMaterial = cMaterialInstance.BaseMaterial.DepotPath; List <CMaterialInstance> BaseMaterials = new List <CMaterialInstance>(); string path = cMaterialInstance.BaseMaterial.DepotPath; while (!Path.GetExtension(path).Contains("mt")) { ulong hash = FNV1A64HashAlgorithm.HashString(path); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var mi = _wolvenkitFileService.TryReadCr2WFile(ms); BaseMaterials.Add(mi.Chunks[0].Data as CMaterialInstance); path = (mi.Chunks[0].Data as CMaterialInstance).BaseMaterial.DepotPath; break; } } } string type = Path.GetFileName(path); BaseMaterials.Reverse(); for (int i = 0; i < BaseMaterials.Count; i++) { MATERIAL.ContainRawMaterialEnum(ref rawMaterial, BaseMaterials[i], type); } MATERIAL.ContainRawMaterialEnum(ref rawMaterial, cMaterialInstance, type); return(rawMaterial); }
private void GetMateriaEntries(CR2WFile cr2w, Stream meshStream, ref List <string> primaryDependencies, ref List <string> materialEntryNames, ref List <CMaterialInstance> materialEntries, List <Archive> archives) { var cmesh = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First(); List <CMaterialInstance> ExternalMaterial = new List <CMaterialInstance>(); for (int i = 0; i < cmesh.ExternalMaterials.Count; i++) { string path = cmesh.ExternalMaterials[i].DepotPath; ulong hash = FNV1A64HashAlgorithm.HashString(path); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var mi = _wolvenkitFileService.TryReadCr2WFile(ms); ExternalMaterial.Add(mi.Chunks[0].Data as CMaterialInstance); for (int t = 0; t < mi.Imports.Count; t++) { if (!primaryDependencies.Contains(mi.Imports[t].DepotPathStr)) { primaryDependencies.Add(mi.Imports[t].DepotPathStr); } } break; } } } for (int i = 0; i < cmesh.PreloadExternalMaterials.Count; i++) { string path = cmesh.PreloadExternalMaterials[i].DepotPath; ulong hash = FNV1A64HashAlgorithm.HashString(path); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var mi = _wolvenkitFileService.TryReadCr2WFile(ms); ExternalMaterial.Add(mi.Chunks[0].Data as CMaterialInstance); for (int t = 0; t < mi.Imports.Count; t++) { if (!primaryDependencies.Contains(mi.Imports[t].DepotPathStr)) { primaryDependencies.Add(mi.Imports[t].DepotPathStr); } } break; } } } List <CMaterialInstance> LocalMaterial = new List <CMaterialInstance>(); bool isbuffered = true; if (cmesh.LocalMaterialBuffer.RawDataHeaders.Count == 0) { isbuffered = false; } if (isbuffered) { MemoryStream materialStream = GetMaterialStream(meshStream, cr2w); byte[] bytes = materialStream.ToArray(); for (int i = 0; i < cmesh.LocalMaterialBuffer.RawDataHeaders.Count; i++) { UInt32 offset = cmesh.LocalMaterialBuffer.RawDataHeaders[i].Offset.Value; UInt32 size = cmesh.LocalMaterialBuffer.RawDataHeaders[i].Size.Value; MemoryStream ms = new MemoryStream(bytes, (int)offset, (int)size); var mi = _wolvenkitFileService.TryReadCr2WFile(ms); for (int e = 0; e < mi.Imports.Count; e++) { if (!primaryDependencies.Contains(mi.Imports[e].DepotPathStr)) { primaryDependencies.Add(mi.Imports[e].DepotPathStr); } } LocalMaterial.Add(mi.Chunks[0].Data as CMaterialInstance); } } else { for (int i = 0; i < cr2w.Chunks.Count; i++) { if (cr2w.Chunks[i].REDType == "CMaterialInstance") { LocalMaterial.Add(cr2w.Chunks[i].Data as CMaterialInstance); } } for (int i = 0; i < cr2w.Imports.Count; i++) { if (!primaryDependencies.Contains(cr2w.Imports[i].DepotPathStr)) { primaryDependencies.Add(cr2w.Imports[i].DepotPathStr); } } } int Count = cmesh.MaterialEntries.Count; for (int i = 0; i < Count; i++) { var Entry = cmesh.MaterialEntries[i]; materialEntryNames.Add(Entry.Name.Value); if (Entry.IsLocalInstance.Value) { materialEntries.Add(LocalMaterial[Entry.Index.Value]); } else { materialEntries.Add(ExternalMaterial[Entry.Index.Value]); } } foreach (var m in materialEntries) { string path = m.BaseMaterial.DepotPath; while (!Path.GetExtension(path).Contains("mt")) { ulong hash = FNV1A64HashAlgorithm.HashString(path); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var mi = _wolvenkitFileService.TryReadCr2WFile(ms); path = (mi.Chunks[0].Data as CMaterialInstance).BaseMaterial.DepotPath; for (int t = 0; t < mi.Imports.Count; t++) { if (!primaryDependencies.Contains(mi.Imports[t].DepotPathStr)) { primaryDependencies.Add(mi.Imports[t].DepotPathStr); } } break; } } } ulong mt = FNV1A64HashAlgorithm.HashString(path); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(mt)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, mt, ms); var mi = _wolvenkitFileService.TryReadCr2WFile(ms); for (int t = 0; t < mi.Imports.Count; t++) { if (!primaryDependencies.Contains(mi.Imports[t].DepotPathStr)) { primaryDependencies.Add(mi.Imports[t].DepotPathStr); } } break; } } } }
public bool WriteMatToMesh(ref CR2WFile cr2w, string _matData, Archive ar) { if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any() || cr2w.Buffers.Count < 1) { return(false); } ulong hash = FNV1A64HashAlgorithm.HashString("base\\characters\\common\\skin\\old_mat_instances\\skin_ma_a__head.mi"); if (!ar.Files.ContainsKey(hash)) { return(false); } var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); _wolvenkitFileService.TryReadRED4File(ms); ms.Seek(0, SeekOrigin.Begin); var obj = JsonConvert.DeserializeObject <MatData>(_matData); var materialbuffer = new MemoryStream(); List <UInt32> offsets = new List <UInt32>(); List <UInt32> sizes = new List <UInt32>(); List <string> names = new List <string>(); if (obj.Materials.Count < 1) { return(false); } for (int i = 0; i < obj.Materials.Count; i++) { var mat = obj.Materials[i]; names.Add(mat.Name); var mi = _wolvenkitFileService.TryReadRED4File(ms); ms.Seek(0, SeekOrigin.Begin); MATERIAL.WriteMatToMeshEnum(ref mi, ref mat); (mi.Chunks[0].Data as CMaterialInstance).BaseMaterial.DepotPath = mat.BaseMaterial; offsets.Add((UInt32)materialbuffer.Position); var m = new MemoryStream(); var b = new BinaryWriter(m); mi.Write(b); materialbuffer.Write(m.ToArray(), 0, (int)m.Length); sizes.Add((UInt32)m.Length); } var blob = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First(); // remove existing data while (blob.MaterialEntries.Count != 0) { blob.MaterialEntries.Remove(blob.MaterialEntries[blob.MaterialEntries.Count - 1]); } while (blob.LocalMaterialBuffer.RawDataHeaders.Count != 0) { blob.LocalMaterialBuffer.RawDataHeaders.Remove(blob.LocalMaterialBuffer.RawDataHeaders[blob.LocalMaterialBuffer.RawDataHeaders.Count - 1]); } while (blob.PreloadLocalMaterialInstances.Count != 0) { blob.PreloadLocalMaterialInstances.Remove(blob.PreloadLocalMaterialInstances[blob.PreloadLocalMaterialInstances.Count - 1]); } while (blob.PreloadExternalMaterials.Count != 0) { blob.PreloadExternalMaterials.Remove(blob.PreloadExternalMaterials[blob.PreloadExternalMaterials.Count - 1]); } while (blob.ExternalMaterials.Count != 0) { blob.ExternalMaterials.Remove(blob.ExternalMaterials[blob.ExternalMaterials.Count - 1]); } while (blob.LocalMaterialInstances.Count != 0) { blob.LocalMaterialInstances.Remove(blob.LocalMaterialInstances[blob.LocalMaterialInstances.Count - 1]); } // for (int i = 0; i < names.Count; i++) { var c = new CMeshMaterialEntry(cr2w, blob.MaterialEntries, Convert.ToString(i)) { IsSerialized = true, }; c.IsLocalInstance = new CBool(cr2w, c, "isLocalInstance") { Value = true, IsSerialized = true }; c.Name = new CName(cr2w, c, "name") { Value = names[i], IsSerialized = true }; c.Index = new CUInt16(cr2w, c, "index") { Value = (UInt16)i, IsSerialized = true }; blob.MaterialEntries.Add(c); var m = new meshLocalMaterialHeader(cr2w, blob.LocalMaterialBuffer.RawDataHeaders, Convert.ToString(i)) { IsSerialized = true }; m.Offset = new CUInt32(cr2w, m, "offset") { Value = offsets[i], IsSerialized = true }; m.Size = new CUInt32(cr2w, m, "size") { Value = sizes[i], IsSerialized = true }; blob.LocalMaterialBuffer.RawDataHeaders.Add(m); } var compressed = new MemoryStream(); using var buff = new BinaryWriter(compressed); var(zsize, crc) = buff.CompressAndWrite(materialbuffer.ToArray()); bool check = false; check = blob.LocalMaterialBuffer.RawData.IsSerialized; if (!check) { blob.LocalMaterialBuffer.RawData = new DataBuffer(cr2w, blob.LocalMaterialBuffer, "rawData") { IsSerialized = true }; blob.LocalMaterialBuffer.RawData.Buffer = new CUInt16(cr2w, blob.LocalMaterialBuffer.RawData, "Buffer") { Value = (UInt16)(cr2w.Buffers.Count + 1), IsSerialized = true }; uint idx = (uint)cr2w.Buffers.Count; cr2w.Buffers.Add(new CR2WBufferWrapper(new CR2WBuffer() { flags = 0, index = idx, offset = 0, diskSize = zsize, memSize = (UInt32)materialbuffer.Length, crc32 = crc })); cr2w.Buffers[(int)idx].ReadData(new BinaryReader(compressed)); cr2w.Buffers[(int)idx].Offset = cr2w.Buffers[(int)idx - 1].Offset + cr2w.Buffers[(int)idx - 1].DiskSize; } else { UInt16 p = (blob.LocalMaterialBuffer.RawData.Buffer.Value); cr2w.Buffers[p - 1].DiskSize = zsize; cr2w.Buffers[p - 1].Crc32 = crc; cr2w.Buffers[p - 1].MemSize = (UInt32)materialbuffer.Length; var off = cr2w.Buffers[p - 1].Offset; cr2w.Buffers[p - 1].Offset = 0; cr2w.Buffers[p - 1].ReadData(new BinaryReader(compressed)); cr2w.Buffers[p - 1].Offset = off; } return(true); }
private void ParseMaterials(CR2WFile cr2w, Stream meshStream, DirectoryInfo outDir, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds) { List <string> primaryDependencies = new List <string>(); List <string> materialEntryNames = new List <string>(); List <CMaterialInstance> materialEntries = new List <CMaterialInstance>(); GetMateriaEntries(cr2w, meshStream, ref primaryDependencies, ref materialEntryNames, ref materialEntries, archives); List <string> mlSetupNames = new List <string>(); List <Multilayer_Setup> mlSetups = new List <Multilayer_Setup>(); List <string> mlTemplateNames = new List <string>(); List <Multilayer_LayerTemplate> mlTemplates = new List <Multilayer_LayerTemplate>(); List <HairProfile> HairProfiles = new List <HairProfile>(); List <string> HairProfileNames = new List <string>(); List <string> TexturesList = new List <string>(); var exportArgs = new GlobalExportArgs().Register( new XbmExportArgs() { UncookExtension = eUncookExtension }, new MlmaskExportArgs() { UncookExtension = eUncookExtension } ); for (int i = 0; i < primaryDependencies.Count; i++) { if (Path.GetExtension(primaryDependencies[i]) == ".xbm") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace("xbm", exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlmask") { if (!TexturesList.Contains(primaryDependencies[i])) { TexturesList.Add(primaryDependencies[i]); } ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { if (!File.Exists(Path.Combine(matRepo, primaryDependencies[i].Replace(".mlmask", $"_0.{exportArgs.Get<XbmExportArgs>().UncookExtension.ToString()}")))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(ar, hash, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(primaryDependencies[i]) == ".hp") { if (!HairProfileNames.Contains(Path.GetFileName(primaryDependencies[i]))) { HairProfileNames.Add(Path.GetFileName(primaryDependencies[i])); ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var hp = _wolvenkitFileService.TryReadCr2WFile(ms); HairProfiles.Add(new HairProfile(hp.Chunks[0].Data as CHairProfile, Path.GetFileName(primaryDependencies[i]))); break; } } } } if (Path.GetExtension(primaryDependencies[i]) == ".mlsetup") { ulong hash = FNV1A64HashAlgorithm.HashString(primaryDependencies[i]); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); var mls = _wolvenkitFileService.TryReadCr2WFile(ms); mlSetupNames.Add(Path.GetFileName(primaryDependencies[i])); mlSetups.Add(mls.Chunks[0].Data as Multilayer_Setup); for (int e = 0; e < mls.Imports.Count; e++) { if (Path.GetExtension(mls.Imports[e].DepotPathStr) == ".xbm") { if (!TexturesList.Contains(mls.Imports[e].DepotPathStr)) { TexturesList.Add(mls.Imports[e].DepotPathStr); } ulong hash1 = FNV1A64HashAlgorithm.HashString(mls.Imports[e].DepotPathStr); foreach (Archive arr in archives) { if (arr.Files.ContainsKey(hash1)) { if (!File.Exists(Path.Combine(matRepo, mls.Imports[e].DepotPathStr.Replace("xbm", exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(arr, hash1, new DirectoryInfo(matRepo), exportArgs); } } break; } } } if (Path.GetExtension(mls.Imports[e].DepotPathStr) == ".mltemplate") { ulong hash2 = FNV1A64HashAlgorithm.HashString(mls.Imports[e].DepotPathStr); foreach (Archive arr in archives) { if (arr.Files.ContainsKey(hash2)) { var mss = new MemoryStream(); ModTools.ExtractSingleToStream(arr, hash2, mss); var mlt = _wolvenkitFileService.TryReadCr2WFile(mss); mlTemplateNames.Add(Path.GetFileName(mls.Imports[e].DepotPathStr)); mlTemplates.Add(mlt.Chunks[0].Data as Multilayer_LayerTemplate); for (int eye = 0; eye < mlt.Imports.Count; eye++) { if (!TexturesList.Contains(mlt.Imports[eye].DepotPathStr)) { TexturesList.Add(mlt.Imports[eye].DepotPathStr); } ulong hash3 = FNV1A64HashAlgorithm.HashString(mlt.Imports[eye].DepotPathStr); foreach (Archive arrr in archives) { if (arrr.Files.ContainsKey(hash3)) { if (!File.Exists(Path.Combine(matRepo, mlt.Imports[eye].DepotPathStr.Replace("xbm", exportArgs.Get <XbmExportArgs>().UncookExtension.ToString())))) { if (Directory.Exists(matRepo)) { _modTools.UncookSingle(arrr, hash3, new DirectoryInfo(matRepo), exportArgs); } } break; } } } break; } } } } break; } } } } List <RawMaterial> RawMaterials = new List <RawMaterial>(); for (int i = 0; i < materialEntries.Count; i++) { RawMaterials.Add(ContainRawMaterial(materialEntries[i], materialEntryNames[i], archives)); } List <Setup> MaterialSetups = new List <Setup>(); for (int i = 0; i < mlSetups.Count; i++) { MaterialSetups.Add(new Setup(mlSetups[i], mlSetupNames[i])); } List <Template> MaterialTemplates = new List <Template>(); for (int i = 0; i < mlTemplates.Count; i++) { MaterialTemplates.Add(new Template(mlTemplates[i], mlTemplateNames[i])); } var obj = new { MaterialRepo = matRepo, Materials = RawMaterials, HairProfiles = HairProfiles, MaterialSetups = MaterialSetups, MaterialTemplates = MaterialTemplates }; var settings = new JsonSerializerSettings(); settings.NullValueHandling = NullValueHandling.Ignore; settings.Formatting = Formatting.Indented; string str = JsonConvert.SerializeObject(obj, settings); File.WriteAllLines(Path.Combine(outDir.FullName, "Textures.txt"), TexturesList); File.WriteAllText(Path.Combine(outDir.FullName, "Material.json"), str); }
private static void Test_Extension(string extension) { var parsers = _host.Services.GetRequiredService <Red4ParserService>(); var resultDir = Path.Combine(Environment.CurrentDirectory, s_testResultsDirectory); Directory.CreateDirectory(resultDir); foreach (var file in Directory.GetFiles(resultDir)) { File.Delete(file); } var results = new ConcurrentBag <ArchiveTestResult>(); var files = s_groupedFiles[extension].ToList(); #if IS_PARALLEL Parallel.ForEach(files, file => #else foreach (var file in files) #endif { var hash = file.Key; var archive = file.Archive as Archive; ArgumentNullException.ThrowIfNull(archive); try { #region convert to json using var originalMemoryStream = new MemoryStream(); ModTools.ExtractSingleToStream(archive, hash, originalMemoryStream); if (!parsers.TryReadRed4File(originalMemoryStream, out var originalFile)) { #if IS_PARALLEL return; #else continue; #endif } var dto = new RedFileDto(originalFile); var json = RedJsonSerializer.Serialize(dto); if (string.IsNullOrEmpty(json)) { throw new SerializationException(); } #endregion #region convert back from json var newdto = RedJsonSerializer.Deserialize <RedFileDto>(json); if (newdto == null) { throw new SerializationException(); } var newFile = newdto.Data; #endregion #region compare // old file var header = originalFile.MetaData; var objectsend = (int)header.ObjectsEnd; var originalBytes = originalMemoryStream.ToByteArray().Take(objectsend); // write the new file using var newMemoryStream = new MemoryStream(); using var writer = new CR2WWriter(newMemoryStream); writer.WriteFile(newFile); // hack to compare buffers var newBytes = newMemoryStream.ToByteArray(); newMemoryStream.Seek(0, SeekOrigin.Begin); var dbg = parsers.ReadRed4File(newMemoryStream); //var newExportStartOffset = (int)dbg.Chunks.FirstOrDefault().GetOffset(); // var originalExportStartOffset = (int)originalFile.Chunks.FirstOrDefault().GetOffset(); // if (!originalBytes.Skip(160).SequenceEqual(newBytes.Skip(160))) // { // // check again skipping the tables // if (originalExportStartOffset == newExportStartOffset) // { // if (!originalBytes.Skip(originalExportStartOffset).SequenceEqual(newBytes.Skip(newExportStartOffset))) // { //#if WRITE // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.o.bin"), originalBytes.ToArray()); // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.bin"), newBytes.ToArray()); //#endif // throw new SerializationException("Exports not equal"); // } // else // { // } // } // else // { //#if WRITE // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.o.bin"), originalBytes.ToArray()); // File.WriteAllBytes(Path.Combine(resultDir, $"{file.Key}.bin"), newBytes.ToArray()); //#endif // throw new SerializationException("Header not equal"); // } // } // else // { // } #endregion results.Add(new ArchiveTestResult() { ArchiveName = archive.Name, Hash = hash.ToString(), Success = true }); } catch (Exception e) { Console.WriteLine($"{hash} - {e.Message} - {e.StackTrace}"); results.Add(new ArchiveTestResult() { ArchiveName = archive.Name, Hash = hash.ToString(), Success = false, ExceptionType = e.GetType(), Message = $"{e.Message}" }); } #if IS_PARALLEL });
public bool ExportAnim(Stream animStream, List <Archive> archives, FileInfo outfile, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.TryReadRED4File(animStream); if (!cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().Any()) { return(false); } var blob = cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().First(); List <MemoryStream> animDataBuffers = new List <MemoryStream>(); foreach (var chk in blob.AnimationDataChunks) { UInt16 bufferIdx = chk.Buffer.Buffer.Value; var b = cr2w.Buffers[bufferIdx - 1]; animStream.Seek(b.Offset, SeekOrigin.Begin); var ms = new MemoryStream(); animStream.DecompressAndCopySegment(ms, b.DiskSize, b.MemSize); animDataBuffers.Add(ms); } RawArmature Rig = null; { ulong hash = FNV1A64HashAlgorithm.HashString(blob.Rig.DepotPath); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); Rig = new RIG(_wolvenkitFileService).ProcessRig(ms); break; } } } if (Rig.BoneCount < 1) { return(false); } var model = ModelRoot.CreateModel(); var skin = model.CreateSkin(); skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray()); for (int i = 0; i < blob.Animations.Count; i++) { var setEntry = (blob.Animations[i].GetReference().Data as animAnimSetEntry); var animAnimDes = (setEntry.Animation.GetReference().Data as animAnimation); if (animAnimDes.AnimationType.Value != Enums.animAnimationType.Normal) { continue; } switch (animAnimDes.AnimBuffer.GetReference().REDType) { case "animAnimationBufferSimd": { var animBuff = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferSimd); var bufferIdx = animBuff.DefferedBuffer.Buffer.Value; var b = cr2w.Buffers[bufferIdx - 1]; animStream.Seek(b.Offset, SeekOrigin.Begin); var defferedBuffer = new MemoryStream(); animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize); SIMD.AddAnimationSIMD(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer); } break; case "animAnimationBufferCompressed": { var animBuff = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferCompressed); var dataAddr = animBuff.DataAddress; Byte[] bytes = new Byte[dataAddr.ZeInBytes.Value]; animDataBuffers[(int)dataAddr.UnkIndex.Value].Seek(dataAddr.FsetInBytes.Value, SeekOrigin.Begin); animDataBuffers[(int)dataAddr.UnkIndex.Value].Read(bytes, 0, (int)dataAddr.ZeInBytes.Value); var defferedBuffer = new MemoryStream(bytes); SPLINE.AddAnimationSpline(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer); } break; default: break; } } if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } return(true); }
public bool ImportWavs(params string[] wavFiles) { if (wavFiles.Length < 1) { return(false); } var foundids = new List <uint>(); foreach (var wav in wavFiles) { try { var idddd = Convert.ToUInt32(Path.GetFileNameWithoutExtension(wav)); foundids.Add(idddd); } catch { } } var validids = new List <uint>(); for (var i = 0; i < foundids.Count; i++) { for (var e = 0; e < Info.OpusCount; e++) { if (Info.OpusHashes[e] == foundids[i]) { validids.Add(foundids[i]); break; } } } if (validids.Count < 1) { return(false); } var modStreams = new Stream[Info.PackIndices[Info.OpusCount - 1] + 1]; for (var i = 0; i < validids.Count; i++) { var name = Path.Combine(_rawFolder.FullName, Convert.ToString(validids[i]) + ".opus"); var proc = new ProcessStartInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "opus-tools\\opusenc.exe")) { WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory, Arguments = $" \"{name.Replace("opus", "wav")}\" \"{name}\" --serial 42 --quiet --padding 0 --vbr --comp 10 --framesize 20 ", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(proc)) { p.WaitForExit(); } var procnew = new ProcessStartInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "opus-tools\\opusdec.exe")) { WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory, Arguments = $" \"{name}\" \"{name.Replace("opus", "wav")}\"", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(procnew)) { p.WaitForExit(); } var procn = new ProcessStartInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "opus-tools\\opusenc.exe")) { WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory, Arguments = $" \"{name.Replace("opus", "wav")}\" \"{name}\" --serial 42 --quiet --padding 0 --vbr --comp 10 --framesize 20 ", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, }; using (var p = Process.Start(procn)) { p.WaitForExit(); } if (File.Exists(name)) { for (var e = 0; e < Info.OpusCount; e++) { if (validids[i] == Info.OpusHashes[e]) { int pakIdx = Info.PackIndices[e]; if (modStreams[pakIdx] == null) { var pakName = "base\\sound\\soundbanks\\sfx_container_" + pakIdx + ".opuspak"; if (_isModded && File.Exists(Path.Combine(_modFolder.FullName, pakName))) { modStreams[pakIdx] = new MemoryStream(File.ReadAllBytes(Path.Combine(_modFolder.FullName, pakName))); } else { var containerHash = FNV1A64HashAlgorithm.HashString(pakName); modStreams[pakIdx] = new MemoryStream(); ModTools.ExtractSingleToStream(_soundBanks, containerHash, modStreams[pakIdx]); } } Info.WriteOpusToPak(new MemoryStream(File.ReadAllBytes(name)), ref modStreams[pakIdx], validids[i], new MemoryStream(File.ReadAllBytes(name.Replace("opus", "wav")))); } } } } var writeinfo = false; for (var i = 0; i < modStreams.Length; i++) { if (modStreams[i] != null) { var pakName = "base\\sound\\soundbanks\\sfx_container_" + i + ".opuspak"; var temp = modStreams[i]; temp.Position = 0; var bytes = new byte[temp.Length]; temp.Read(bytes, 0, Convert.ToInt32(temp.Length)); File.WriteAllBytes(Path.Combine(_modFolder.FullName, pakName), bytes); writeinfo = true; } } if (writeinfo) { Info.WriteOpusInfo(new DirectoryInfo(Path.Combine(_modFolder.FullName, "base\\sound\\soundbanks"))); return(true); } return(false); }
public bool ExportMorphTargets(Stream targetStream, FileInfo outfile, List <Archive> archives, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.TryReadRED4File(targetStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } RawArmature Rig = null; MemoryStream meshbuffer = MESH.GetMeshBufferStream(targetStream, cr2w); MeshesInfo meshinfo = MESH.GetMeshesinfo(cr2w); List <RawMeshContainer> expMeshes = MESH.ContainRawMesh(meshbuffer, meshinfo, true); int subMeshC = expMeshes.Count; var buffers = cr2w.Buffers; var blob = cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMorphTargetMeshBlob>().First(); string baseMeshPath = cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().First().BaseMesh.DepotPath; ulong hash = FNV1A64HashAlgorithm.HashString(baseMeshPath); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var meshStream = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, meshStream); var meshCr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (meshCr2w == null || !meshCr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !meshCr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { break; } MESH.MeshBones meshBones = new MESH.MeshBones(); meshBones.boneCount = meshCr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First().BoneNames.Count; if (meshBones.boneCount != 0) // for rigid meshes { meshBones.Names = RIG.GetboneNames(meshCr2w); meshBones.WorldPosn = MESH.GetMeshBonesPosn(meshCr2w); } Rig = MESH.GetNonParentedRig(meshBones); MemoryStream ms = MESH.GetMeshBufferStream(meshStream, meshCr2w); meshinfo = MESH.GetMeshesinfo(meshCr2w); expMeshes = MESH.ContainRawMesh(ms, meshinfo, true); subMeshC = expMeshes.Count; if (meshBones.boneCount == 0) // for rigid meshes { for (int i = 0; i < expMeshes.Count; i++) { expMeshes[i].weightcount = 0; } } MESH.UpdateMeshJoints(ref expMeshes, Rig, meshBones); break; } } MemoryStream diffsbuffer = new MemoryStream(); MemoryStream mappingbuffer = new MemoryStream(); MemoryStream texbuffer = new MemoryStream(); if (blob.DiffsBuffer.IsSerialized) { targetStream.Seek(cr2w.Buffers[blob.DiffsBuffer.Buffer.Value - 1].Offset, SeekOrigin.Begin); targetStream.DecompressAndCopySegment(diffsbuffer, buffers[blob.DiffsBuffer.Buffer.Value - 1].DiskSize, buffers[blob.DiffsBuffer.Buffer.Value - 1].MemSize); } if (blob.MappingBuffer.IsSerialized) { targetStream.Seek(cr2w.Buffers[blob.MappingBuffer.Buffer.Value - 1].Offset, SeekOrigin.Begin); targetStream.DecompressAndCopySegment(mappingbuffer, buffers[blob.MappingBuffer.Buffer.Value - 1].DiskSize, buffers[blob.MappingBuffer.Buffer.Value - 1].MemSize); } if (blob.TextureDiffsBuffer.IsSerialized) { targetStream.Seek(cr2w.Buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].Offset, SeekOrigin.Begin); targetStream.DecompressAndCopySegment(texbuffer, buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].DiskSize, buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].MemSize); } TargetsInfo targetsInfo = GetTargetInfos(cr2w, subMeshC); List <RawTargetContainer[]> expTargets = new List <RawTargetContainer[]>(); for (int i = 0; i < targetsInfo.NumTargets; i++) { UInt32[] temp_NumVertexDiffsInEachChunk = new UInt32[subMeshC]; UInt32[] temp_NumVertexDiffsMappingInEachChunk = new UInt32[subMeshC]; for (int e = 0; e < subMeshC; e++) { temp_NumVertexDiffsInEachChunk[e] = targetsInfo.NumVertexDiffsInEachChunk[i, e]; temp_NumVertexDiffsMappingInEachChunk[e] = targetsInfo.NumVertexDiffsMappingInEachChunk[i, e]; } expTargets.Add(ContainRawTargets(diffsbuffer, mappingbuffer, temp_NumVertexDiffsInEachChunk, temp_NumVertexDiffsMappingInEachChunk, targetsInfo.TargetStartsInVertexDiffs[i], targetsInfo.TargetStartsInVertexDiffsMapping[i], targetsInfo.TargetPositionDiffOffset[i], targetsInfo.TargetPositionDiffScale[i], subMeshC)); } string[] names = new string[targetsInfo.NumTargets]; for (int i = 0; i < targetsInfo.NumTargets; i++) { names[i] = targetsInfo.Names[i] + "_" + targetsInfo.RegionNames[i]; } List <MemoryStream> textureStreams = ContainTextureStreams(cr2w, texbuffer); ModelRoot model = RawTargetsToGLTF(expMeshes, expTargets, names, Rig); if (WolvenTesting.IsTesting) { return(true); } model.Extras = SharpGLTF.IO.JsonContent.Serialize(new { BaseMesh = targetsInfo.BaseMesh }); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } var dir = new DirectoryInfo(outfile.FullName.Replace(Path.GetExtension(outfile.FullName), string.Empty) + "_Textures"); if (textureStreams.Count > 0) { Directory.CreateDirectory(dir.FullName); } for (int i = 0; i < textureStreams.Count; i++) { File.WriteAllBytes(dir.FullName + "\\" + Path.GetFileNameWithoutExtension(outfile.FullName) + i + ".dds", textureStreams[i].ToArray()); } targetStream.Dispose(); targetStream.Close(); return(true); }