public Patch Commit(string root) { Patch uninstall = new Patch(); uninstall.isUninstall = true; Console.WriteLine(); Console.WriteLine("Patching..."); Console.WriteLine(); foreach (AddedFile file in addedFiles) { string path = root + file.path; DeletedFile backup = new DeletedFile(file.path); uninstall.deletedFiles.Add(backup); File.WriteAllBytes(path, file.data); PrintFile(PatchType.ADD, file.path); } foreach (ModifiedFile file in modifiedFiles) { string path = root + file.path; if (File.Exists(path)) { byte[] data = File.ReadAllBytes(path); ModifiedFile backup = new ModifiedFile(file.path, data); uninstall.modifiedFiles.Add(backup); } File.WriteAllBytes(path, file.data); PrintFile(PatchType.MODIFY, file.path); } foreach (DeletedFile file in deletedFiles) { string path = root + file.path; if (File.Exists(path)) { byte[] data = File.ReadAllBytes(path); AddedFile backup = new AddedFile(file.path, data); uninstall.addedFiles.Add(backup); } File.Delete(path); PrintFile(PatchType.DELETE, file.path); } foreach (HipFile file in hipFiles) { string path = root + file.path; HipFile backup = new HipFile(file.path); HipSection[] hip = HipFileToHipArray(path); Section_HIPA hipa = (Section_HIPA)hip[0]; Section_PACK pack = (Section_PACK)hip[1]; Section_DICT dict = (Section_DICT)hip[2]; Section_STRM strm = (Section_STRM)hip[3]; List <Section_AHDR> ahdrList = dict.ATOC.AHDRList; List <Section_LHDR> lhdrList = dict.LTOC.LHDRList; Dictionary <uint, Section_AHDR> ahdrDict = ahdrList.ToDictionary(s => s.assetID); PrintFile(PatchType.MODIFY, file.path); foreach (AddedAsset asset in file.addedAssets) { Section_ADBG adbg = new Section_ADBG(asset.alignment, asset.name, asset.filename, asset.checksum); Section_AHDR ahdr = new Section_AHDR(asset.id, new string(asset.type), (AHDRFlags)asset.flags, adbg); ahdr.data = asset.data; DeletedAsset backupAsset = new DeletedAsset(asset); backup.deletedAssets.Add(backupAsset); ahdrList.Add(ahdr); Section_LHDR lhdr = lhdrList[asset.layer]; lhdr.assetIDlist.Add(asset.id); PrintAsset(PatchType.ADD, asset.name); } foreach (ModifiedAsset asset in file.modifiedAssets) { if (!ahdrDict.ContainsKey(asset.id)) { break; } Section_ADBG adbg = new Section_ADBG(asset.alignment, asset.name, asset.filename, asset.checksum); Section_AHDR ahdr = new Section_AHDR(asset.id, new string(asset.type), (AHDRFlags)asset.flags, adbg); ahdr.data = asset.data; Section_AHDR oldAHDR = ahdrDict[asset.id]; ahdrList.Remove(oldAHDR); ahdrList.Add(ahdr); ModifiedAsset backupAsset = new ModifiedAsset(oldAHDR, hip); backup.modifiedAssets.Add(backupAsset); PrintAsset(PatchType.MODIFY, asset.name); } foreach (DeletedAsset asset in file.deletedAssets) { if (!ahdrDict.ContainsKey(asset.id)) { break; } Section_AHDR ahdr = ahdrDict[asset.id]; ahdrList.Remove(ahdr); AddedAsset backupAsset = new AddedAsset(ahdr, hip); backup.addedAssets.Add(backupAsset); Section_LHDR lhdr = lhdrList[asset.layer]; lhdr.assetIDlist.Remove(asset.id); PrintAsset(PatchType.DELETE, asset.name); } pack.PCNT.AHDRCount = ahdrList.Count; hip = SetupStream(ref hipa, ref pack, ref dict, ref strm); File.WriteAllBytes(path, HipArrayToFile(hip)); uninstall.hipFiles.Add(backup); } Console.WriteLine("Done patching."); Console.WriteLine(); return(uninstall); }
static void Main(string[] args) { Console.WriteLine("BFBB Patch Tool v0.4 by Seil"); if (args.Length == 0) { Option option = Option.None; while (option != Option.Close) { Console.WriteLine(); Console.WriteLine("Press 0 to install a patch."); Console.WriteLine("Press 1 to create a new patch."); Console.WriteLine("Press 2 to quit."); option = ReadOption(); if (option == Option.Create) { FolderBrowserDialog folderDialog = new FolderBrowserDialog(); folderDialog.Description = "Select the root folder of your UN-MODDED game."; if (folderDialog.ShowDialog() != DialogResult.OK) { continue; } string originalRoot = folderDialog.SelectedPath; Console.WriteLine("Original game: " + originalRoot); folderDialog.Description = "Select the root folder of your MODDED game."; if (folderDialog.ShowDialog() != DialogResult.OK) { continue; } string moddedRoot = folderDialog.SelectedPath; Console.WriteLine("Modded game: " + moddedRoot); SaveFileDialog fileDialog = new SaveFileDialog { Title = "Save patch file", FileName = "mod.patch", Filter = "Patch file (*.patch)|*.patch|All files|*.*" }; if (fileDialog.ShowDialog() != DialogResult.OK) { continue; } string patchFile = fileDialog.FileName; Console.WriteLine("Patch file: " + patchFile); Patch patch = new Patch(originalRoot, moddedRoot); patch.Write(patchFile); Console.WriteLine("Patch file saved to " + patchFile); } else if (option == Option.Install) { FolderBrowserDialog folderDialog = new FolderBrowserDialog { Description = "Select the root folder of your game." }; if (folderDialog.ShowDialog() != DialogResult.OK) { continue; } string root = folderDialog.SelectedPath; Console.WriteLine("Game root: " + root); OpenFileDialog openDialog = new OpenFileDialog { Title = "Open patch file", Filter = "Patch file (*.patch)|*.patch|All files|*.*" }; if (openDialog.ShowDialog() != DialogResult.OK) { continue; } string patchFile = openDialog.FileName; Console.WriteLine("Patch file: " + patchFile); Patch patch = new Patch(patchFile); string uninstallFile = null; if (!patch.isUninstall) { SaveFileDialog saveDialog = new SaveFileDialog { Title = "Save uninstall patch file", Filter = "Patch file (*.patch)|*.patch|All files|*.*" }; if (saveDialog.ShowDialog() == DialogResult.OK) { uninstallFile = saveDialog.FileName; Console.WriteLine("Uninstall patch file: " + uninstallFile); } } Console.WriteLine(); patch.Print(); PatchOption patchOption = PatchOption.None; while (patchOption != PatchOption.Confirm) { Console.WriteLine(); Console.WriteLine("Do you want to commit this patch?"); Console.WriteLine(); Console.WriteLine("Press 0 to patch your game."); Console.WriteLine("Press 1 to cancel."); patchOption = ReadPatchOption(); if (patchOption == PatchOption.Confirm) { Patch uninstall = patch.Commit(root); if (uninstallFile != null) { uninstall.Write(uninstallFile); Console.WriteLine("Uninstaller patch saved to " + uninstallFile); Console.WriteLine("Run this patch to restore your game to its original version."); Console.WriteLine(); } } else if (patchOption == PatchOption.Cancel) { break; } } } } } }