public static void ReloadMtds() { IBinder mtdBinder = null; if (AssetLocator.Type == GameType.DarkSoulsIII || AssetLocator.Type == GameType.Sekiro) { mtdBinder = BND4.Read(AssetLocator.GetAssetPath($@"mtd\allmaterialbnd.mtdbnd.dcx")); } if (mtdBinder == null) { return; } _mtds = new Dictionary <string, MTD>(); foreach (var f in mtdBinder.Files) { var mtdname = Path.GetFileNameWithoutExtension(f.Name); // Because *certain* mods contain duplicate entries for the same material if (!_mtds.ContainsKey(mtdname)) { _mtds.Add(mtdname, MTD.Read(f.Bytes)); } } }
// Reads bnd private IBinder ReadBnd(string path) { try { if (BND3.Is(path)) { return(BND3.Read(path)); } else if (BND4.Is(path)) { return(BND4.Read(path)); } else if (Spec.Game == FromGame.DS3 && path.EndsWith("Data0.bdt")) { return(SFUtil.DecryptDS3Regulation(path)); } else { throw new Exception($"Unrecognized bnd format for game {Spec.Game}: {path}"); } } catch (Exception ex) { throw new Exception($"Failed to load {path}: {ex}"); } }
private static void LoadParamsDS3() { var dir = AssetLocator.GameRootDirectory; var mod = AssetLocator.GameModDirectory; if (!File.Exists($@"{dir}\Data0.bdt")) { MessageBox.Show("Could not find DS3 regulation file. Functionality will be limited.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Load loose params if they exist if (File.Exists($@"{mod}\\param\gameparam\gameparam_dlc2.parambnd.dcx")) { // Load params var lparam = $@"{mod}\param\gameparam\gameparam_dlc2.parambnd.dcx"; BND4 lparamBnd = BND4.Read(lparam); LoadParamFromBinder(lparamBnd); return; } // Load params var param = $@"{mod}\Data0.bdt"; if (!File.Exists(param)) { param = $@"{dir}\Data0.bdt"; } BND4 paramBnd = SFUtil.DecryptDS3Regulation(param); LoadParamFromBinder(paramBnd); }
private static void SaveParamsBBSekiro() { var dir = AssetLocator.GameRootDirectory; var mod = AssetLocator.GameModDirectory; if (!File.Exists($@"{dir}\\param\gameparam\gameparam.parambnd.dcx")) { MessageBox.Show("Could not find param file. Cannot save.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Load params var param = $@"{mod}\param\gameparam\gameparam.parambnd.dcx"; if (!File.Exists(param)) { param = $@"{dir}\param\gameparam\gameparam.parambnd.dcx"; } BND4 paramBnd = BND4.Read(param); // Replace params with edited ones foreach (var p in paramBnd.Files) { if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name))) { p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write(); } } Utils.WriteWithBackup(dir, mod, @"param\gameparam\gameparam.parambnd.dcx", paramBnd); }
public static Model LoadObject(string id) { Model obj = null; LoadingTaskMan.DoLoadingTaskSynchronous($"LOAD_OBJ_{id}", $"Loading object {id}...", progress => { if (GameType == GameTypes.DS3) { var chrbnd = BND4.Read($@"{InterrootPath}\obj\{id}.objbnd.dcx"); obj = new Model(progress, id, chrbnd, 0, null, null); } else if (GameType == GameTypes.DS1) { var chrbnd = BND3.Read($@"{InterrootPath}\obj\{id}.objbnd"); obj = new Model(progress, id, chrbnd, 0, null, null); } else if (GameType == GameTypes.DS1R) { var chrbnd = BND4.Read($@"{InterrootPath}\obj\{id}.objbnd.dcx"); obj = new Model(progress, id, chrbnd, 0, null, null); } else if (GameType == GameTypes.BB) { var chrbnd = BND4.Read($@"{InterrootPath}\obj\{id}.objbnd.dcx"); obj = new Model(progress, id, chrbnd, 0, null, null); } Scene.AddModel(obj); var texturesToLoad = obj.MainMesh.GetAllTexNamesToLoad(); LoadingTaskMan.DoLoadingTask($"LOAD_OBJ_{id}_TEX", "Loading additional object textures...", innerProgress => { if (GameType == GameTypes.DS1) { foreach (var tex in texturesToLoad) { TexturePool.AddTpfFromPath($@"{InterrootPath}\map\tx\{tex}.tpf"); } } else if (GameType == GameTypes.DS3) { int objGroup = int.Parse(id.Substring(1)) / 1_0000; var tpfBnds = System.IO.Directory.GetFiles($@"{InterrootPath}\map\m{objGroup:D2}", "*.tpfbhd"); foreach (var t in tpfBnds) { TexturePool.AddSpecificTexturesFromBinder(t, texturesToLoad, directEntryNameMatch: true); } } obj.MainMesh.TextureReloadQueued = true; }); }); return(obj); }
public static void ReloadFMGs() { if (AssetLocator.Type == GameType.Undefined) { return; } if (AssetLocator.Type == GameType.DarkSoulsIISOTFS) { ReloadFMGsDS2(); IsLoaded = true; return; } IBinder fmgBinder; var desc = AssetLocator.GetEnglishItemMsgbnd(); if (AssetLocator.Type == GameType.DemonsSouls || AssetLocator.Type == GameType.DarkSoulsPTDE || AssetLocator.Type == GameType.DarkSoulsRemastered) { fmgBinder = BND3.Read(desc.AssetPath); } else { fmgBinder = BND4.Read(desc.AssetPath); } _fmgs = new Dictionary <ItemFMGTypes, FMG>(); foreach (var file in fmgBinder.Files) { _fmgs.Add((ItemFMGTypes)file.ID, FMG.Read(file.Bytes)); } IsLoaded = true; }
public static void ReloadParams() { if (!File.Exists(ParamPath)) { Debug.Log("DS2 enc_regulation.bnd.dcx not found"); return; } if (!BND4.Is(DarkSoulsTools.GetOverridenPath(ParamPath))) { Debug.Log("Decrypt your regulation by saving in Yapped"); return; } BND4 paramBnd = BND4.Read(DarkSoulsTools.GetOverridenPath(ParamPath)); EnemyParam = PARAM.Read(paramBnd.Files.Find(x => Path.GetFileName(x.Name) == "EnemyParam.param").Bytes); PARAM.Layout layout = PARAM.Layout.ReadXMLFile($@"{Application.dataPath.Replace('/', '\\')}\dstools\ParamLayouts\DS2SOTFS\{EnemyParam.ID}.xml"); EnemyParam.SetLayout(layout); // Build and cache the enemy param dictionary ParamDictionary = new Dictionary <long, PARAM.Row>(); foreach (var row in EnemyParam.Rows) { ParamDictionary.Add(row.ID, row); } }
public void LoadArmorPartsbnd(string partsbndPath, EquipSlot slot) { if (System.IO.File.Exists(partsbndPath)) { if (BND3.Is(partsbndPath)) { LoadArmorPartsbnd(BND3.Read(partsbndPath), slot); } else { LoadArmorPartsbnd(BND4.Read(partsbndPath), slot); } } else { if (slot == EquipSlot.Head) { HeadMesh?.Dispose(); } else if (slot == EquipSlot.Body) { BodyMesh?.Dispose(); } else if (slot == EquipSlot.Arms) { ArmsMesh?.Dispose(); } else if (slot == EquipSlot.Legs) { LegsMesh?.Dispose(); } } }
public static BND4 Load(FileInfo path) { return(path.Extension switch { ".bdt" => RegulationFile.DecryptDS3Regulation(path.FullName), ".dcx" => BND4.Read(path.FullName), _ => throw new InvalidOperationException($"{path.Name} is not a valid parambnd or regulation file") });
public static void WriteFile <TFormat>(TFormat file, string path, bool makeBackup = true) where TFormat : SoulsFile <TFormat>, new() { if (path.Contains("|")) { var splitPath = path.Split('|'); if (splitPath.Length != 2) { throw new Exception("Invalid internal BND path format. Expected 'C:\\Path\\To\\BND|Internal_File_Name.Extension'."); } var bndPath = splitPath[0]; var internalPath = splitPath[1]; if (BND3.Is(bndPath)) { var bnd3 = BND3.Read(bndPath); var internalFile = bnd3.Files.LastOrDefault(f => GetFileNameWithoutDirectoryOrExtension(f.Name) == internalPath); if (internalFile == null) { throw new Exception($"Internal BND file path '{internalPath}' not found in BND '{bndPath}'."); } internalFile.Bytes = file.Write(); if (makeBackup) { BackupFile(bndPath); } bnd3.Write(bndPath); } else if (BND4.Is(bndPath)) { var bnd4 = BND4.Read(bndPath); var internalFile = bnd4.Files.LastOrDefault(f => GetFileNameWithoutDirectoryOrExtension(f.Name) == internalPath); if (internalFile == null) { throw new Exception($"Internal BND file path '{internalPath}' not found in BND '{bndPath}'."); } internalFile.Bytes = file.Write(); if (makeBackup) { BackupFile(bndPath); } bnd4.Write(bndPath); } else { throw new Exception("Internal BND path specified but file is not a BND file!"); } } else { if (makeBackup) { BackupFile(path); } file.Write(path); } }
static IBinder ReadIBinder(string name) { if (BND4.Is(name)) { return(BND4.Read(name)); } else { return(BND3.Read(name)); } }
private static void PatchBND(string sourceLangDir, string refLangDir, string[] destFilePath) { foreach (var file in destFilePath)//Patch each file in files Array { if (BND3.IsRead(file, out BND3 destBND3)) { //Set source BND files string sourceLangFiles = $@"{ sourceLangDir }\{ Path.GetFileName(file) }"; BND3 sourceBND = BND3.Read(sourceLangFiles); string refLangFiles = $@"{refLangDir}\{Path.GetFileName(file)}"; //Make null ref BND, and make an actual BND read if it exists BND3 refBND = null; if (File.Exists(refLangFiles)) { refBND = BND3.Read(refLangFiles); } #region Debug Stuff //ConsoleLog(sourceBND.Files.Count); //Debug.WriteLine(Path.GetFileName(sourceBND.Files[0].Name)); //ConsoleLog(destFMG.Entries.Count + " & " + sourceFMG.Entries.Count); #endregion //Patch BND file PatchFMG(sourceBND, destBND3, refBND, file); //Write new BND destBND3.Write(file); } else if (BND4.IsRead(file, out BND4 destBND4)) { //Set source BND files string sourceLangFiles = $@"{sourceLangDir}\{Path.GetFileName(file)}"; BND4 sourceBND = BND4.Read(sourceLangFiles); string refLangFiles = $@"{refLangDir}\{Path.GetFileName(file)}"; //Make null ref BND, and make an actual BND read if it exists BND4 refBND = null; if (File.Exists(refLangFiles)) { refBND = BND4.Read(refLangFiles); } #region Debug Stuff //ConsoleLog(sourceBND.Files.Count); //Debug.WriteLine(Path.GetFileName(sourceBND.Files[0].Name)); //ConsoleLog(destFMG.Entries.Count + " & " + sourceFMG.Entries.Count); #endregion //Patch BND file PatchFMG(sourceBND, destBND4, refBND, file); //Write new BND destBND4.Write(file); } } }
public void LoadFromPath(string file) { ReloadType = TaeFileContainerReloadType.None; containerBND3 = null; containerBND4 = null; taeInBND.Clear(); hkxInBND.Clear(); if (BND3.Is(file)) { ContainerType = TaeFileContainerType.BND3; containerBND3 = BND3.Read(file); foreach (var f in containerBND3.Files) { if (TAE.Is(f.Bytes)) { taeInBND.Add(f.Name, TAE.Read(f.Bytes)); } else if (f.Name.ToUpper().EndsWith(".HKX")) { hkxInBND.Add(f.Name, f.Bytes); } } } else if (BND4.Is(file)) { ContainerType = TaeFileContainerType.BND4; containerBND4 = BND4.Read(file); foreach (var f in containerBND4.Files) { if (TAE.Is(f.Bytes)) { taeInBND.Add(f.Name, TAE.Read(f.Bytes)); } else if (f.Name.ToUpper().EndsWith(".HKX")) { hkxInBND.Add(f.Name, f.Bytes); } } } else if (TAE.Is(file)) { ContainerType = TaeFileContainerType.TAE; taeInBND.Add(file, TAE.Read(file)); } filePath = file; //SFTODO ReloadType = TaeFileContainerReloadType.None; }
private static void SaveParamsDS2(bool loose) { var dir = AssetLocator.GameRootDirectory; var mod = AssetLocator.GameModDirectory; if (!File.Exists($@"{dir}\enc_regulation.bnd.dcx")) { MessageBox.Show("Could not find DS2 regulation file. Cannot save.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Load params var param = $@"{mod}\enc_regulation.bnd.dcx"; if (!File.Exists(param)) { param = $@"{dir}\enc_regulation.bnd.dcx"; } BND4 paramBnd = BND4.Read(param); // If params aren't loose, replace params with edited ones if (!loose) { foreach (var p in paramBnd.Files) { if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name))) { p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write(); } } } else { // strip all the params from the regulation List <BinderFile> newFiles = new List <BinderFile>(); foreach (var p in paramBnd.Files) { if (!p.Name.ToUpper().Contains(".PARAM")) { newFiles.Add(p); } } paramBnd.Files = newFiles; // Write all the params out loose foreach (var p in _params) { Utils.WriteWithBackup(dir, mod, $@"Param\{p.Key}.param", p.Value); } } Utils.WriteWithBackup(dir, mod, @"enc_regulation.bnd.dcx", paramBnd); }
private void Browse_Click(object sender, RoutedEventArgs e) { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.DefaultExt = ".anibnd.dcx"; fileDialog.Filter = "ANIBND.DCX Files (*.anibnd.dcx)|*.anibnd.dcx"; fileDialog.Title = "Select a .animbnd.dcx file"; fileDialog.CheckFileExists = true; fileDialog.CheckPathExists = true; bool?result = fileDialog.ShowDialog(); if (result == true) { StackPanel.Children.Clear(); Canvas.Children.Clear(); string filePath = fileDialog.FileName; Console.WriteLine(filePath); if (!File.Exists(filePath)) { return; } if (!BND4.Is(DCX.Decompress(filePath))) { return; } anibnd = BND4.Read(filePath); OpenFile.bndPath = filePath; dropdownOptions = new Dictionary <string, Dictionary <string, int> >(); foreach (BND4.File f in anibnd.Files) { if (System.IO.Path.GetExtension(f.Name).Equals(".hkx")) { Console.WriteLine(f.ToString()); string moveset = new DirectoryInfo(f.Name).Parent.Name; string fileName = System.IO.Path.GetFileNameWithoutExtension(f.Name); if (!dropdownOptions.ContainsKey(moveset)) { dropdownOptions[moveset] = new Dictionary <string, int>(); } dropdownOptions[moveset][fileName] = f.ID; } } lbl_anibnd.Content = System.IO.Path.GetFileNameWithoutExtension(filePath); cmb_moveset.ItemsSource = dropdownOptions.Keys.Count > 0 ? dropdownOptions.Keys : Enumerable.Empty <string>(); cmb_animation.ItemsSource = Enumerable.Empty <string>(); } }
public static void AddSpecificTexturesFromBinder(string name, List <string> textures, bool directEntryNameMatch = false) { if (!File.Exists(name)) { return; } IBinder bnd = null; if (BXF4.IsBHD(name)) { bnd = BXF4.Read(name, name.Substring(0, name.Length - 7) + ".tpfbdt"); } else if (BXF4.IsBDT(name)) { bnd = BXF4.Read(name.Substring(0, name.Length - 7) + ".tpfbhd", name); } else if (BXF3.IsBHD(name)) { bnd = BXF3.Read(name, name.Substring(0, name.Length - 7) + ".tpfbdt"); } else if (BXF3.IsBDT(name)) { bnd = BXF3.Read(name.Substring(0, name.Length - 7) + ".tpfbhd", name); } else if (BND4.Is(name)) { bnd = BND4.Read(name); } else if (BND3.Is(name)) { bnd = BND3.Read(name); } foreach (var f in bnd.Files) { if (directEntryNameMatch ? textures.Contains(Utils.GetShortIngameFileName(f.Name).ToLower()) : TPF.Is(f.Bytes)) { var tpf = TPF.Read(f.Bytes); foreach (var tx in tpf.Textures) { var shortTexName = Utils.GetShortIngameFileName(tx.Name).ToLower(); if (textures.Contains(shortTexName)) { AddFetchTPF(tpf, tx.Name.ToLower()); textures.Remove(shortTexName); } } } } }
public static bool CombineSFX(List <string> maps, string outDir) { string inDir = new DirectoryInfo($@"{outDir}\..\sfx").FullName; string commonPath = $@"{inDir}\sfxbnd_commoneffects.ffxbnd.dcx"; if (!File.Exists(commonPath)) { return(false); } Console.WriteLine(commonPath); Console.WriteLine(new FileInfo(commonPath).FullName); BND4 sfxCommon = BND4.Read(commonPath); HashSet <string> sfxFiles = new HashSet <string>(sfxCommon.Files.Select(f => f.Name)); Console.WriteLine(string.Join(",", maps)); foreach (string map in maps.Select(m => m.Substring(0, 3)).Distinct()) { string path = $@"{inDir}\sfxbnd_{map}.ffxbnd.dcx"; if (!File.Exists(path)) { continue; } BND4 sfx = BND4.Read(path); sfx.Files = sfx.Files.Where(file => { if (!sfxFiles.Contains(file.Name)) { sfxCommon.Files.Add(file); sfxFiles.Add(file.Name); return(false); } else { return(false); } }).ToList(); sfx.Write($@"{outDir}\sfx\sfxbnd_{map}.ffxbnd.dcx"); } int startId = 0; foreach (BinderFile file in sfxCommon.Files) { // Ignore prefixes here file.ID = startId++; } sfxCommon.Files.Sort((a, b) => a.ID.CompareTo(b.ID)); sfxCommon.Write($@"{outDir}\sfx\sfxbnd_commoneffects.ffxbnd.dcx"); return(true); }
public static BND4 DecryptDS2Regulation(string path) { byte[] bytes = File.ReadAllBytes(path); byte[] iv = new byte[16]; iv[0] = 0x80; Array.Copy(bytes, 0, iv, 1, 11); iv[15] = 1; byte[] input = new byte[bytes.Length - 32]; Array.Copy(bytes, 32, input, 0, bytes.Length - 32); using (var ms = new MemoryStream(input)) { byte[] decrypted = CryptographyUtility.DecryptAesCtr(ms, ds2RegulationKey, iv); return(BND4.Read(decrypted)); } }
public static void ReloadFmgs() { try { BND4 fmgBnd = BND4.Read(FMGBndPath); ItemFMG = FMG.Read(fmgBnd.Files.Find(x => Path.GetFileName(x.Name) == "アイテム名.fmg").Bytes); } catch (Exception e) { if (!Failwarn) { Debug.Log("Failed to load item fmg file. Item names will not be shown."); Failwarn = true; } } }
public static void SaveFMGs() { if (AssetLocator.Type == GameType.Undefined) { return; } if (AssetLocator.Type == GameType.DarkSoulsIISOTFS) { SaveFMGsDS2(); return; } // Load the fmg bnd, replace fmgs, and save IBinder fmgBinder; var desc = AssetLocator.GetEnglishItemMsgbnd(); if (AssetLocator.Type == GameType.DemonsSouls || AssetLocator.Type == GameType.DarkSoulsPTDE || AssetLocator.Type == GameType.DarkSoulsRemastered) { fmgBinder = BND3.Read(desc.AssetPath); } else { fmgBinder = BND4.Read(desc.AssetPath); } foreach (var file in fmgBinder.Files) { if (_fmgs.ContainsKey((ItemFMGTypes)file.ID)) { file.Bytes = _fmgs[(ItemFMGTypes)file.ID].Write(); } } var descw = AssetLocator.GetEnglishItemMsgbnd(true); if (fmgBinder is BND3 bnd3) { Utils.WriteWithBackup(AssetLocator.GameRootDirectory, AssetLocator.GameModDirectory, descw.AssetPath, bnd3); } else if (fmgBinder is BND4 bnd4) { Utils.WriteWithBackup(AssetLocator.GameRootDirectory, AssetLocator.GameModDirectory, descw.AssetPath, bnd4); } }
public static void CombineAI(List <string> maps, string outDir) { // Only works for Sekiro, since all other games have additional per-map metadata that actually matters string commonPath = $@"{outDir}\..\script\aicommon.luabnd.dcx"; BND4 aiCommon = BND4.Read(commonPath); HashSet <string> aiFiles = new HashSet <string>(aiCommon.Files.Select(f => f.Name)); foreach (string map in maps) { string aiPath = $@"{outDir}\..\script\{map}.luabnd.dcx"; if (!File.Exists(aiPath)) { continue; } BND4 ai = BND4.Read(aiPath); ai.Files = ai.Files.Where(file => { if (!file.Name.Contains("out")) { return(true); } if (!aiFiles.Contains(file.Name)) { aiCommon.Files.Add(file); aiFiles.Add(file.Name); } return(false); }).ToList(); ai.Write($@"{outDir}\script\{map}.luabnd.dcx"); } int startId = 2000; foreach (BinderFile file in aiCommon.Files) { if (file.ID < 3000) { file.ID = startId++; } Console.WriteLine(file); } aiCommon.Files.Sort((a, b) => a.ID.CompareTo(b.ID)); aiCommon.Write($@"{outDir}\script\aicommon.luabnd.dcx"); }
public static SoulsFormats.FLVER LoadMapFlver(string noExtensionPath) { if (File.Exists(noExtensionPath + ".mapbnd.dcx")) { // DS3's snowflake packaging of flvers return(SoulsFormats.FLVER.Read(BND4.Read(noExtensionPath + ".mapbnd.dcx").Files[0].Bytes)); } else if (File.Exists(noExtensionPath + ".flver")) { // Usual case for DS1 with udsfm return(SoulsFormats.FLVER.Read(noExtensionPath + ".flver")); } else if (File.Exists(noExtensionPath + ".flver.dcx")) { // Bloodborne and DS1R return(SoulsFormats.FLVER.Read(noExtensionPath + ".flver.dcx")); } return(null); }
private void OverrideBnd <T>(string fromDir, string toDir, Dictionary <string, Dictionary <string, T> > data, Func <T, byte[]> writer, string ext = "*bnd.dcx") { foreach (string path in Directory.GetFiles($@"{dir}\{fromDir}", ext)) { string fname = Path.GetFileName(path); string name = BaseName(path); if (!data.ContainsKey(name)) { continue; } Dictionary <string, T> bnds = data[name]; BND4 bnd; try { bnd = BND4.Read(path); } catch (Exception ex) { throw new Exception($"Failed to load {path}: {ex}"); } foreach (BinderFile file in bnd.Files) { string bndName = BaseName(file.Name); if (!bnds.ContainsKey(bndName)) { continue; } try { file.Bytes = writer(bnds[bndName]); } catch (Exception ex) { Console.WriteLine($"Failed to load {path}: {bndName}: {ex}"); } } string outPath = $@"{dir}\{toDir}\{fname}"; Console.WriteLine($"Writing to {outPath}"); bnd.Write(outPath, DCX.Type.SekiroKRAK); } }
static public void ImportFlver(DarkSoulsTools.GameType gameType, string path, string assetName, string texturePath = null) { FLVER flver; FLVERAssetLink link = ScriptableObject.CreateInstance <FLVERAssetLink>(); if (path.Contains(".mapbnd")) { BND4 bnd = BND4.Read(path); link.Type = FLVERAssetLink.ContainerType.Mapbnd; link.ArchivePath = path; link.FlverPath = bnd.Files[0].Name; flver = FLVER.Read(bnd.Files[0].Bytes); } else { link.Type = FLVERAssetLink.ContainerType.None; link.FlverPath = path; flver = FLVER.Read(path); } ImportFlver(flver, link, gameType, assetName, texturePath); }
private static void LoadParamsBBSekrio() { var dir = AssetLocator.GameRootDirectory; var mod = AssetLocator.GameModDirectory; if (!File.Exists($@"{dir}\\param\gameparam\gameparam.parambnd.dcx")) { MessageBox.Show("Could not find param file. Functionality will be limited.", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Load params var param = $@"{mod}\param\gameparam\gameparam.parambnd.dcx"; if (!File.Exists(param)) { param = $@"{dir}\param\gameparam\gameparam.parambnd.dcx"; } BND4 paramBnd = BND4.Read(param); LoadParamFromBinder(paramBnd); }
public static void LoadMTDBND() { MtdDict.Clear(); MTDBND = null; if (GameType == GameTypes.SDT) { MTDBND = BND4.Read(GetInterrootPath($@"mtd\allmaterialbnd.mtdbnd.dcx")); foreach (var f in MTDBND.Files) { var key = Utils.GetShortIngameFileName(f.Name); if (!MtdDict.ContainsKey(key)) { MtdDict.Add(key, MTD.Read(f.Bytes)); } else { MtdDict[key] = MTD.Read(f.Bytes); } } } }
public void Combine(GameMod mod) { var modA = this; var modB = mod; foreach (string filePath in modB.FilePaths) { bool hasFile = modA.FilePaths.Contains(filePath); if (!hasFile || Path.GetFileName(filePath) != "gameparam.parambnd.dcx") { string pathA = modA.FullModPath + @"\" + filePath; string pathB = modB.FullModPath + @"\" + filePath; Directory.CreateDirectory(pathA); File.Copy(pathA, pathB, true); } else if (Path.GetFileName(filePath) == "gameparam.parambnd.dcx") { var paramA = BND4.Read(modA.FullModPath + @"\" + filePath); var paramB = BND4.Read(modB.FullModPath + @"\" + filePath); //compare them and stuff } } }
public static bool LoadParamBND(bool forceReload) { string interroot = GameDataManager.InterrootPath; bool justNowLoadedParamBND = false; if (forceReload || !ParamBNDs.ContainsKey(GameDataManager.GameType)) { ParamBNDs.Add(GameDataManager.GameType, null); if (GameDataManager.GameType == GameDataManager.GameTypes.DS1) { if (Directory.Exists($"{interroot}\\param\\GameParam\\") && File.Exists($"{interroot}\\param\\GameParam\\GameParam.parambnd")) { ParamBNDs[GameDataManager.GameType] = BND3.Read($"{interroot}\\param\\GameParam\\GameParam.parambnd"); } else { return(false); } } else if (GameDataManager.GameType == GameDataManager.GameTypes.BB) { if (Directory.Exists($"{interroot}\\param\\GameParam\\") && File.Exists($"{interroot}\\param\\GameParam\\GameParam.parambnd.dcx")) { ParamBNDs[GameDataManager.GameType] = BND4.Read($"{interroot}\\param\\GameParam\\GameParam.parambnd.dcx"); } else { return(false); } } else if (GameDataManager.GameType == GameDataManager.GameTypes.DS3) { if (Directory.Exists($"{interroot}\\param\\GameParam\\") && File.Exists($"{interroot}\\param\\GameParam\\GameParam_dlc2.parambnd.dcx")) { ParamBNDs[GameDataManager.GameType] = BND4.Read($"{interroot}\\param\\GameParam\\GameParam_dlc2.parambnd.dcx"); } else if (File.Exists($"{interroot}\\Data0.bdt")) { ParamBNDs[GameDataManager.GameType] = SFUtil.DecryptDS3Regulation($"{interroot}\\Data0.bdt"); } else { return(false); } } else { throw new NotImplementedException(); } justNowLoadedParamBND = true; } if (justNowLoadedParamBND || forceReload || GameTypeCurrentLoadedParamsAreFrom != GameDataManager.GameType) { LoadStuffFromParamBND(); } return(true); }
static void ExportModel(MenuCommand menuCommand) { if (Selection.activeObject == null) { return; } var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject); if (!assetPath.ToUpper().EndsWith(".FBX")) { EditorUtility.DisplayDialog("Invalid asset", "Please select an fbx asset", "Ok"); } // Load the FBX as a prefab //GameObject obj = PrefabUtility.LoadPrefabContents(assetPath); GameObject obj = AssetDatabase.LoadAssetAtPath <GameObject>(assetPath); // Go through everything and strip the prefixes fbx exporters love to add Stack <GameObject> gameObjects = new Stack <GameObject>(); GameObject bonesRoot = null; GameObject meshesRoot = null; gameObjects.Push(obj); while (gameObjects.Count > 0) { var o = gameObjects.Pop(); o.name = o.name.Split(':').Last(); if (o.name == "Bones") { bonesRoot = o; } if (o.name == "Meshes") { meshesRoot = o; } for (int i = 0; i < o.transform.childCount; i++) { gameObjects.Push(o.transform.GetChild(i).gameObject); } } // Load the source c0000 and target flvers /*var sourceBnd = BND4.Read($@"{DarkSoulsTools.Interroot}\chr\c0000.chrbnd.dcx"); * var sourceFlver = FLVER.Read(sourceBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes); * var targetBnd = BND4.Read($@"{DarkSoulsTools.Interroot}\parts\lg_m_9000.partsbnd.dcx"); * var targetFlver = FLVER.Read(targetBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes);*/ var sourceBnd = BND4.Read($@"{DarkSoulsTools.Interroot}\chr\c4033.chrbnd.dcx"); var sourceFlver = FLVER.Read(sourceBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes); var targetBnd = BND4.Read($@"{DarkSoulsTools.Interroot}\chr\c4033.chrbnd.dcx"); var targetFlver = FLVER.Read(targetBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes); // Build a bone reindexing table Dictionary <string, int> SourceBoneTable = new Dictionary <string, int>(); for (int i = 0; i < sourceFlver.Bones.Count; i++) { if (!SourceBoneTable.ContainsKey(sourceFlver.Bones[i].Name)) { SourceBoneTable.Add(sourceFlver.Bones[i].Name, i); } } if (meshesRoot == null) { throw new Exception("Could not find Meshes group for this FBX"); } if (bonesRoot == null) { throw new Exception("Could not find Bones group for this FBX"); } //sourceFlver.Bones.Add(targetFlver.Bones[29]); var templateMesh = targetFlver.Meshes.First(); targetFlver.Bones = sourceFlver.Bones; targetFlver.Meshes.Clear(); //targetFlver.SekiroUnk = sourceFlver.SekiroUnk; for (var meshIdx = 0; meshIdx < meshesRoot.transform.childCount; meshIdx++) { // Get the mesh object var meshObj = meshesRoot.transform.GetChild(meshIdx).gameObject; // Get the skin and mesh var meshSkin = meshObj.GetComponent <SkinnedMeshRenderer>(); var bones = meshSkin.bones; var mesh = meshSkin.sharedMesh; // Remap table to recover source bone indices var boneRemap = new int[bones.Length]; for (int i = 0; i < bones.Length; i++) { var name = bones[i].gameObject.name; if (SourceBoneTable.ContainsKey(name)) { boneRemap[i] = SourceBoneTable[name]; } else { boneRemap[i] = 0; } } // Build the submesh's bone table HashSet <int> usedBones = new HashSet <int>(); foreach (var weight in mesh.boneWeights) { if (weight.boneIndex0 >= 0) { usedBones.Add(boneRemap[weight.boneIndex0]); } if (weight.boneIndex1 >= 0) { usedBones.Add(boneRemap[weight.boneIndex1]); } if (weight.boneIndex2 >= 0) { usedBones.Add(boneRemap[weight.boneIndex2]); } if (weight.boneIndex3 >= 0) { usedBones.Add(boneRemap[weight.boneIndex3]); } } // Bad hack for (int i = 0; i < targetFlver.Bones.Count(); i++) { usedBones.Add(i); } var submeshBones = usedBones.OrderBy(x => x).ToArray(); var meshToSubmeshBone = new Dictionary <int, int>(); for (int i = 0; i < submeshBones.Count(); i++) { meshToSubmeshBone.Add(submeshBones[i], i); } // Finally port the mesh to the target //var fmesh = targetFlver.Meshes[0]; var fmesh = new FLVER.Mesh(templateMesh); fmesh.BoneIndices = sourceFlver.Meshes[0].BoneIndices; //submeshBones.ToList(); var min = mesh.bounds.min; var max = mesh.bounds.max; //fmesh.BoundingBoxMax = sourceFlver.Header.BoundingBoxMax; //fmesh.BoundingBoxMin = new System.Numerics.Vector3(max.x*100, max.y*100, max.z*100); //fmesh.BoundingBoxMin = sourceFlver.Header.BoundingBoxMin; //fmesh.MaterialIndex = 0; //targetFlver.Header.BoundingBoxMin = sourceFlver.Header.BoundingBoxMin; //targetFlver.Header.BoundingBoxMax = sourceFlver.Header.BoundingBoxMax; /*foreach (var b in usedBones) * { * targetFlver.Bones[b].Unk3C = 8; * }*/ foreach (var b in targetFlver.Bones) { if (b.Unk3C == 2) { b.Unk3C = 8; } } //targetFlver.Bones[140].Unk3C = 4; //targetFlver.Bones[140].Name = "LG_M_9000"; // Port vertices fmesh.Vertices.Clear(); fmesh.Vertices.Capacity = mesh.vertexCount; var mverts = mesh.vertices; var mnorms = mesh.normals; var mtangs = mesh.tangents; var muvs = mesh.uv; var mbones = mesh.boneWeights; for (int i = 0; i < mesh.vertexCount; i++) { var vert = new FLVER.Vertex(); var pos = mverts[i]; vert.Positions.Add(new System.Numerics.Vector3(pos.x, pos.y, pos.z)); var normal = mnorms[i]; vert.Normals.Add(new System.Numerics.Vector4(-normal.x, -normal.y, -normal.z, -1.0f)); var tangent = mtangs[i]; vert.Tangents.Add(new System.Numerics.Vector4(-tangent.x, -tangent.y, -tangent.z, -tangent.w)); vert.Tangents.Add(new System.Numerics.Vector4(-tangent.x, -tangent.y, -tangent.z, -tangent.w)); var color = new Color32(0xFF, 0xFF, 0x00, 0xFF); //mesh.colors32[i]; vert.Colors.Add(new FLVER.Vertex.Color(color.a, color.r, color.g, color.b)); /*vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f)); * vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f)); * vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f)); * vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f));*/ var uv = muvs[i]; vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f)); vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f)); vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f)); vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f)); vert.BoneIndices = new int[4]; vert.BoneWeights = new float[4]; var bone = mbones[i]; //vert.Tangents.Add(new System.Numerics.Vector4(bone.weight0, bone.weight1, bone.weight2, bone.weight3)); vert.BoneWeights[0] = bone.weight0; vert.BoneWeights[1] = bone.weight1; vert.BoneWeights[2] = bone.weight2; vert.BoneWeights[3] = bone.weight3; vert.BoneIndices[0] = meshToSubmeshBone[boneRemap[bone.boneIndex0]]; vert.BoneIndices[1] = meshToSubmeshBone[boneRemap[bone.boneIndex1]]; vert.BoneIndices[2] = meshToSubmeshBone[boneRemap[bone.boneIndex2]]; vert.BoneIndices[3] = meshToSubmeshBone[boneRemap[bone.boneIndex3]]; for (int b = 0; b < 3; b++) { if (vert.BoneIndices[b] == -1) { vert.BoneIndices[b] = 0; } } fmesh.Vertices.Add(vert); } // Port faceset var fset = new FLVER.FaceSet(fmesh.FaceSets[0]); var tris = new uint[mesh.triangles.Count()]; var mtris = mesh.triangles; for (int i = 0; i < tris.Count(); i++) { tris[i] = ((uint)mtris[i]); } fset.Vertices = tris; fset.CullBackfaces = false; fset.TriangleStrip = false; fmesh.FaceSets.Clear(); var fset2 = new FLVER.FaceSet(FLVER.FaceSet.FSFlags.LodLevel1, false, false, fset.Unk06, fset.Unk07, fset.IndexSize, fset.Vertices); var fset3 = new FLVER.FaceSet(FLVER.FaceSet.FSFlags.LodLevel2, false, false, fset.Unk06, fset.Unk07, fset.IndexSize, fset.Vertices); var fset4 = new FLVER.FaceSet(FLVER.FaceSet.FSFlags.Unk80000000, false, false, fset.Unk06, fset.Unk07, fset.IndexSize, fset.Vertices); fmesh.FaceSets.Add(fset); fmesh.FaceSets.Add(fset2); fmesh.FaceSets.Add(fset3); fmesh.FaceSets.Add(fset4); fmesh.MaterialIndex = meshIdx; //fmesh.MaterialIndex = 0; targetFlver.Meshes.Add(fmesh); //targetFlver.BufferLayouts } //targetFlver.Materials[0].MTD = $@"M[ARSN].mtd"; targetFlver.Materials[0].MTD = "C[ARSN].mtd"; targetFlver.Materials[0].Textures[0].Type = "g_DiffuseTexture"; targetFlver.Materials[0].Textures[0].Path = "c5020_shrek_a.dds"; targetFlver.Materials[0].Textures[1].Path = ""; targetFlver.Materials[0].Textures[2].Path = ""; targetFlver.Materials[0].Textures[3].Type = "g_BumpmapTexture"; targetFlver.Materials[0].Textures[3].Path = "SYSTEX_DummyNormal.tga"; targetFlver.Materials.Add(new FLVER.Material("shrek2", "C[ARSN].mtd", targetFlver.Materials[0].Flags, targetFlver.Materials[0].GXBytes)); targetFlver.Materials[1].MTD = "C[ARSN].mtd"; targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[0])); targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[1])); targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[2])); targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[3])); targetFlver.Materials[1].Textures[0].Type = "g_DiffuseTexture"; targetFlver.Materials[1].Textures[0].Path = "c5020_shrekshirt_a.dds"; targetFlver.Materials[1].Textures[1].Path = ""; targetFlver.Materials[1].Textures[2].Path = ""; targetFlver.Materials[1].Textures[3].Type = "g_BumpmapTexture"; targetFlver.Materials[1].Textures[3].Path = "SYSTEX_DummyNormal.tga"; // Finally save targetBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes = targetFlver.Write(); //targetBnd.Write($@"{DarkSoulsTools.ModProjectDirectory}\parts\lg_m_9000.partsbnd.dcx", DCX.Type.SekiroDFLT); targetBnd.Write($@"{DarkSoulsTools.ModProjectDirectory}\chr\c4033.chrbnd.dcx", DCX.Type.DarkSouls3); }
public Test() { BND4.Read("test.bnd"); }