/// <summary> /// Load a BND4 file into the existing object, overwriting existing data. /// </summary> /// <param name="filePath"></param> public void LoadInPlace(string filePath) { Utils.Assert(File.Exists(filePath), "File does not exist"); using (BinReader bin = new BinReader(File.OpenRead(filePath))) { if (DEBUG) { Console.WriteLine("[DEBUG] READ BND4 HEADERS"); } header = bin.ReadStruct <BND4Header>(); header.AssertIntegrity(); isUnicode = header.isUnicode; entries = new BND4Entry[header.fileCnt]; for (int i = 0; i < header.fileCnt; i++) { if (DEBUG) { Console.WriteLine(string.Format("[DEBUG] READ ENTRY HEADER {0}/{1}", i + 1, header.fileCnt)); } entries[i] = new BND4Entry(); entries[i].header = bin.ReadStruct <BND4EntryHeader>(); entries[i].header.AssertIntegrity(); if (DEBUG) { Console.WriteLine(string.Format("[DEBUG] READ ENTRY NAME {0}/{1}", i + 1, header.fileCnt)); } bin.StepInto(entries[i].header.entryNameOffset); entries[i].name = header.isUnicode ? bin.ReadWideString() : bin.ReadShiftJIS(); bin.StepOut(); if (DEBUG) { Console.WriteLine(string.Format("[DEBUG] READ ENTRY DATA {0}/{1}", i + 1, header.fileCnt)); } bin.StepInto(entries[i].header.entryDataOffset); entries[i].data = bin.ReadBytes((int)entries[i].header.entrySize); bin.StepOut(); } if (DEBUG) { Console.WriteLine("[DEBUG] READ COMPLETE"); } } }
/// <summary> /// Patch the DS3 account flag that controls if a save can be opened by a user. /// </summary> /// <param name="steamID"></param> public void PatchDS3AccountFlag(ulong steamID) { if (DEBUG) { Console.WriteLine("[DEBUG] PATCH MENU ACCOUNT FLAG..."); } BND4Entry menuEntry = entries[10]; // Overwrite account flag in menu file (Responsible for "Cannot load save" msg on startup) byte[] menuData = menuEntry.DecryptData(); Array.Copy(BitConverter.GetBytes(steamID), 0, menuData, 0x8, 8); menuEntry.SetEncryptedData(menuData); // Get used save slots bool array to overwrite save-specific account flags byte[] usedCharSlots = new byte[10]; Array.Copy(menuData, 0x1098, usedCharSlots, 0, 10); // For each used char. slot, patch its account flag for (int i = 0; i < 10; i++) { if (0 == usedCharSlots[i]) { continue; } if (DEBUG) { Console.WriteLine("[DEBUG] PATCH ACCOUNT FLAG CHAR #" + i.ToString()); } byte[] slotData = entries[i].DecryptData(); // This offset always seems to go 0x6F under the account flag uint flagOffset = BitConverter.ToUInt32(slotData, 0x58) + 0x6F; Array.Copy(BitConverter.GetBytes(steamID), 0, slotData, flagOffset, 8); entries[i].SetEncryptedData(slotData); } if (DEBUG) { Console.WriteLine("[DEBUG] ACCOUNT FLAG PATCHED"); } }