static string tlzcDecompressToTempFile(string infile) { string outfile = TempUtil.GetTempFileName(); tlzcDecompress(infile, outfile); return(outfile); }
private void buttonPatch_Click(object sender, EventArgs e) { Invoke(new BoolDelegate(SetInteractionEnabled), false); string outDirPath = @"new/patched"; var outDir = Directory.CreateDirectory(outDirPath); Thread thread = new Thread(delegate() { foreach (var ctrl in FileSelectControls) { ctrl.OutDir = outDir.FullName; ctrl.StartWorker(); while (ctrl.IsWorkerRunning()) { Thread.Sleep(300); } } TempUtil.RemoveTempFolder(); Invoke(new BoolDelegate(SetInteractionEnabled), true); }); thread.Start(); }
static string svoExtractToTempDir(string infile, bool nometa = false) { string extractPath = TempUtil.GetTempFileName(); if (Directory.Exists(extractPath)) { Util.DeleteDirectoryAggressive(extractPath, true); } Directory.CreateDirectory(extractPath); using (var fps4 = new FPS4(infile)) { fps4.Extract(extractPath, nometa); } Logger.LogDirData(extractPath, "FPS4 extract of " + infile); return(extractPath); }
public static void PatchChara(string charaPath, string patchDir, string outDir, string outMd5 = null, BackgroundWorker worker = null) { if (!File.Exists(charaPath)) { throw new PatchingException("File not found: " + charaPath); } if (worker != null) { worker.ReportProgress(0, "Confirming source file..."); } // if patched file exists and matches, exit early string outPath = Path.Combine(outDir, "chara.svo"); try { CompareMd5Output(outPath, outMd5); return; } catch (PatchingException) { } catch (FileNotFoundException) { } CompareMd5(charaPath, "38984a5656b7a2faac3a7e24c962607e"); Logger.LogFileData(charaPath, "chara.svo"); Logger.LogDirData(patchDir, "chara patches"); if (worker != null) { worker.ReportProgress(0, "Extracting source file..."); } string extractPath = svoExtractToTempDir(charaPath); if (worker != null) { worker.ReportProgress(0, "Patching files..."); } foreach (var patchDirG in Directory.GetDirectories(patchDir)) { string charaFilePath = Path.Combine(extractPath, Path.GetFileName(patchDirG) + ".DAT"); string decompPath = TempUtil.GetTempFileName(); tlzcDecompress(charaFilePath, decompPath); string subDir = svoExtractToTempDir(decompPath); foreach (var patchDirH in Directory.GetDirectories(patchDirG)) { string subPath = Path.Combine(subDir, Path.GetFileName(patchDirH)); string subSubDir = svoExtractToTempDir(subPath, true); foreach (var patch in Util.DirectoryGetFilesWorkaround(patchDirH)) { string toPatchCompressed = Path.Combine(subSubDir, Path.GetFileNameWithoutExtension(patch)); string toPatch = TempUtil.GetTempFileName(); tlzcDecompress(toPatchCompressed, toPatch); string patched = TempUtil.GetTempFileName(); XdeltaApply(toPatch, patched, patch); File.Delete(toPatch); tlzcCompress(patched, toPatchCompressed); File.Delete(patched); } string newSubPath = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(subPath)) { fps4.Alignment = 0x80; fps4.Pack(subSubDir, newSubPath); } File.Delete(subPath); File.Move(newSubPath, subPath); Util.DeleteDirectoryAggressive(subSubDir, true); } string newPath = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(decompPath)) { fps4.Alignment = 0x80; fps4.Pack(subDir, newPath); } tlzcCompress(newPath, charaFilePath); File.Delete(newPath); File.Delete(decompPath); Util.DeleteDirectoryAggressive(subDir, true); } // dice minigame textures { string EP_0670_010 = Path.Combine(extractPath, "EP_0670_010.DAT"); string EP_0670_010decomp = tlzcDecompressToTempFile(EP_0670_010); string EP_0670_010extract = svoExtractToTempDir(EP_0670_010decomp); { string EP_0670_010e_0002 = Path.Combine(EP_0670_010extract, "0002"); string EP_0670_010e_0002extract = svoExtractToTempDir(EP_0670_010e_0002, true); { string EP_0670_010e_0002e_0005 = Path.Combine(EP_0670_010e_0002extract, "0005"); string EP_0670_010e_0002e_0005decomp = tlzcDecompressToTempFile(EP_0670_010e_0002e_0005); BlockCopy(EP_0670_010e_0002e_0005decomp, 0x100, EP_0670_010e_0002e_0005decomp, 0x100100, 0x100000); tlzcCompress(EP_0670_010e_0002e_0005decomp, EP_0670_010e_0002e_0005); File.Delete(EP_0670_010e_0002e_0005decomp); string EP_0670_010e_0002e_0006 = Path.Combine(EP_0670_010e_0002extract, "0006"); string EP_0670_010e_0002e_0006decomp = tlzcDecompressToTempFile(EP_0670_010e_0002e_0006); BlockCopy(EP_0670_010e_0002e_0006decomp, 0x100, EP_0670_010e_0002e_0006decomp, 0x100100, 0x100000); tlzcCompress(EP_0670_010e_0002e_0006decomp, EP_0670_010e_0002e_0006); File.Delete(EP_0670_010e_0002e_0006decomp); } string EP_0670_010e_0002new = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(EP_0670_010e_0002)) { fps4.Alignment = 0x80; fps4.Pack(EP_0670_010e_0002extract, EP_0670_010e_0002new); } File.Delete(EP_0670_010e_0002); File.Move(EP_0670_010e_0002new, EP_0670_010e_0002); Util.DeleteDirectoryAggressive(EP_0670_010e_0002extract, true); } string EP_0670_010new = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(EP_0670_010decomp)) { fps4.Alignment = 0x80; fps4.Pack(EP_0670_010extract, EP_0670_010new); } tlzcCompress(EP_0670_010new, EP_0670_010); File.Delete(EP_0670_010decomp); File.Delete(EP_0670_010new); Util.DeleteDirectoryAggressive(EP_0670_010extract, true); } // "and they were never heard from again" textures { string GAMEOVER = Path.Combine(extractPath, "GAMEOVER.DAT"); string GAMEOVERdecomp = tlzcDecompressToTempFile(GAMEOVER); string GAMEOVERextract = svoExtractToTempDir(GAMEOVERdecomp); { string GAMEOVERe_0002 = Path.Combine(GAMEOVERextract, "0002"); string GAMEOVERe_0002extract = svoExtractToTempDir(GAMEOVERe_0002, true); { string GAMEOVERe_0002e_0001 = Path.Combine(GAMEOVERe_0002extract, "0001"); string GAMEOVERe_0002e_0001decomp = tlzcDecompressToTempFile(GAMEOVERe_0002e_0001); BlockCopy(GAMEOVERe_0002e_0001decomp, 0x55D80, GAMEOVERe_0002e_0001decomp, 0xD80, 0x55000); BlockCopy(GAMEOVERe_0002e_0001decomp, 0x55D80, GAMEOVERe_0002e_0001decomp, 0xAAD80, 0x55000); tlzcCompress(GAMEOVERe_0002e_0001decomp, GAMEOVERe_0002e_0001); File.Delete(GAMEOVERe_0002e_0001decomp); } string GAMEOVERe_0002new = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(GAMEOVERe_0002)) { fps4.Alignment = 0x80; fps4.Pack(GAMEOVERe_0002extract, GAMEOVERe_0002new); } File.Delete(GAMEOVERe_0002); File.Move(GAMEOVERe_0002new, GAMEOVERe_0002); Util.DeleteDirectoryAggressive(GAMEOVERe_0002extract, true); } string GAMEOVERnew = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(GAMEOVERdecomp)) { fps4.Alignment = 0x80; fps4.Pack(GAMEOVERextract, GAMEOVERnew); } tlzcCompress(GAMEOVERnew, GAMEOVER); File.Delete(GAMEOVERdecomp); File.Delete(GAMEOVERnew); Util.DeleteDirectoryAggressive(GAMEOVERextract, true); } // more dice minigame textures why are there so many copies of those { string POR_C = Path.Combine(extractPath, "POR_C.DAT"); string POR_Cdecomp = tlzcDecompressToTempFile(POR_C); string POR_Cextract = svoExtractToTempDir(POR_Cdecomp, true); { string POR_Ce_0002 = Path.Combine(POR_Cextract, "0002"); string POR_Ce_0002extract = svoExtractToTempDir(POR_Ce_0002, true); { string POR_Ce_0002e_0026 = Path.Combine(POR_Ce_0002extract, "0026"); string POR_Ce_0002e_0026decomp = tlzcDecompressToTempFile(POR_Ce_0002e_0026); BlockCopy(POR_Ce_0002e_0026decomp, 0x100, POR_Ce_0002e_0026decomp, 0x100100, 0x100000); tlzcCompress(POR_Ce_0002e_0026decomp, POR_Ce_0002e_0026); File.Delete(POR_Ce_0002e_0026decomp); string POR_Ce_0002e_0027 = Path.Combine(POR_Ce_0002extract, "0027"); string POR_Ce_0002e_0027decomp = tlzcDecompressToTempFile(POR_Ce_0002e_0027); BlockCopy(POR_Ce_0002e_0027decomp, 0x100, POR_Ce_0002e_0027decomp, 0x100100, 0x100000); tlzcCompress(POR_Ce_0002e_0027decomp, POR_Ce_0002e_0027); File.Delete(POR_Ce_0002e_0027decomp); } string POR_Ce_0002new = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(POR_Ce_0002)) { fps4.Alignment = 0x80; fps4.Pack(POR_Ce_0002extract, POR_Ce_0002new); } File.Delete(POR_Ce_0002); File.Move(POR_Ce_0002new, POR_Ce_0002); Util.DeleteDirectoryAggressive(POR_Ce_0002extract, true); } string POR_Cnew = TempUtil.GetTempFileName(); using (var fps4 = new FPS4(POR_Cdecomp)) { fps4.Alignment = 0x80; fps4.Pack(POR_Cextract, POR_Cnew); } tlzcCompress(POR_Cnew, POR_C); File.Delete(POR_Cdecomp); File.Delete(POR_Cnew); Util.DeleteDirectoryAggressive(POR_Cextract, true); } // extract yuri towel costume into its own archive { string EP_1320_060 = Path.Combine(extractPath, "EP_1320_060.DAT"); string EP_1320_060decomp = tlzcDecompressToTempFile(EP_1320_060); string EP_1320_060extract = svoExtractToTempDir(EP_1320_060decomp); { string EP_1320_060e_0002 = Path.Combine(EP_1320_060extract, "0002"); string EP_1320_060e_0002extract = svoExtractToTempDir(EP_1320_060e_0002); { foreach (string file in Util.DirectoryGetFilesWorkaround(EP_1320_060e_0002extract)) { if (!file.EndsWith("4")) { File.Delete(file); } } string EP_1320_060e_0002new = Path.Combine(EP_1320_060extract, "0002.new"); using (var fps4 = new FPS4()) { fps4.Alignment = 0x80; fps4.ContentBitmask = 0x0047; fps4.Pack(Util.DirectoryGetFilesWorkaround(EP_1320_060e_0002extract), EP_1320_060e_0002new, "n"); } File.Delete(EP_1320_060e_0002); File.Move(EP_1320_060e_0002new, EP_1320_060e_0002); Util.DeleteDirectoryAggressive(EP_1320_060e_0002extract, true); } File.Delete(Path.Combine(EP_1320_060extract, "0001")); File.Copy(Path.Combine(EP_1320_060extract, "0003"), Path.Combine(EP_1320_060extract, "0001")); string EP_1320_060e_0000 = Path.Combine(EP_1320_060extract, "0000"); string EP_1320_060e_0000extract = Path.Combine(EP_1320_060extract, "0000.ext"); if (Directory.Exists(EP_1320_060e_0000extract)) { Util.DeleteDirectoryAggressive(EP_1320_060e_0000extract, true); } Directory.CreateDirectory(EP_1320_060e_0000extract); using (var fps4 = new FPS4(EP_1320_060e_0000)) { fps4.Extract(EP_1320_060e_0000extract); } { foreach (string dir in Directory.GetDirectories(EP_1320_060e_0000extract)) { if (!Path.GetFileName(dir).StartsWith("P")) { Util.DeleteDirectoryAggressive(dir, true); } } foreach (string dir in Directory.GetDirectories(Directory.GetDirectories(EP_1320_060e_0000extract).First())) { string dirname = Path.GetFileName(dir); if (!(dirname.StartsWith("Y") || dirname.EndsWith("2"))) { Util.DeleteDirectoryAggressive(dir, true); } } foreach (string dir in Directory.GetDirectories(Directory.GetDirectories(Directory.GetDirectories(EP_1320_060e_0000extract).First()).First())) { string dirname = Path.GetFileName(dir); if (!dir.EndsWith("M")) { Util.DeleteDirectoryAggressive(dir, true); } } string EP_1320_060e_0000new = Path.Combine(EP_1320_060extract, "0000.new"); using (var fps4 = new FPS4()) { fps4.Alignment = 0x80; fps4.ContentBitmask = 0x0047; var files = Util.DirectoryGetFilesWorkaround(EP_1320_060e_0000extract, "*", System.IO.SearchOption.AllDirectories).OrderBy(x => x.Split('.').Last()).ToArray(); fps4.Pack(files, EP_1320_060e_0000new, "p"); } File.Delete(EP_1320_060e_0000); File.Move(EP_1320_060e_0000new, EP_1320_060e_0000); Util.DeleteDirectoryAggressive(EP_1320_060e_0000extract, true); } } string YUR_C201new = Path.Combine(extractPath, "YUR_C201.DAT.dec.new"); using (var fps4 = new FPS4()) { fps4.Alignment = 0x80; fps4.ContentBitmask = 0x0007; fps4.ArchiveName = "YUR_C201"; fps4.Pack(Util.DirectoryGetFilesWorkaround(EP_1320_060extract), YUR_C201new); } Util.DeleteDirectoryAggressive(EP_1320_060extract, true); tlzcCompress(YUR_C201new, Path.Combine(extractPath, "YUR_C201.DAT")); File.Delete(EP_1320_060decomp); File.Delete(YUR_C201new); } if (worker != null) { worker.ReportProgress(100, "Packing modified file..."); } Logger.LogDirData(extractPath, "chara dir patched"); using (var fps4 = new FPS4()) { using (var oldfps4 = new FPS4(charaPath)) { fps4.Unknown2 = oldfps4.Unknown2; fps4.ArchiveName = oldfps4.ArchiveName; } fps4.Alignment = 0x800; fps4.Pack(extractPath, outPath); } Logger.LogFileData(outPath, "chara.svo patched"); Util.DeleteDirectoryAggressive(extractPath, true); if (outMd5 != null) { CompareMd5Output(outPath, outMd5); } }
public static void PatchEffect(string effectPath, string patchDir, string outDir, string outMd5 = null, BackgroundWorker worker = null) { if (!File.Exists(effectPath)) { throw new PatchingException("File not found: " + effectPath); } if (worker != null) { worker.ReportProgress(0, "Confirming source file..."); } // if patched file exists and matches, exit early string outPath = Path.Combine(outDir, "effect.svo"); try { CompareMd5Output(outPath, outMd5); return; } catch (PatchingException) { } catch (FileNotFoundException) { } CompareMd5(effectPath, "ada3bdb2e2ca481b44bc9e209b019dc8"); Logger.LogFileData(effectPath, "effect.svo"); Logger.LogDirData(patchDir, "effect patches"); // extract effect.svo if (worker != null) { worker.ReportProgress(0, "Extracting source file..."); } string extractPath = svoExtractToTempDir(effectPath); if (worker != null) { worker.ReportProgress(0, "Patching files..."); } // image assets for SURPRISE ENCOUNTER! and so on string surpriseJpn = tlzcDecompressToTempFile(Path.Combine(extractPath, "E_A023.DAT")); string surpriseEng = tlzcDecompressToTempFile(Path.Combine(extractPath, "E_A034.DAT")); BlockCopy(surpriseEng, 0x100, surpriseJpn, 0x100, 0x80000); tlzcCompress(surpriseJpn, Path.Combine(extractPath, "E_A023.DAT")); System.IO.File.Delete(surpriseJpn); System.IO.File.Delete(surpriseEng); // image assets for game over screen string gameover = tlzcDecompressToTempFile(Path.Combine(extractPath, "E_A104_GAMEOVER.DAT")); BlockCopy(gameover, 0x55D80, gameover, 0xD80, 0x55000); BlockCopy(gameover, 0x55D80, gameover, 0xAAD80, 0x55000); tlzcCompress(gameover, Path.Combine(extractPath, "E_A104_GAMEOVER.DAT")); System.IO.File.Delete(gameover); // image assets for dice minigame string dice1 = tlzcDecompressToTempFile(Path.Combine(extractPath, "E_MG_STONERESULT01.DAT")); BlockCopy(dice1, 0x100, dice1, 0x100100, 0x100000); tlzcCompress(dice1, Path.Combine(extractPath, "E_MG_STONERESULT01.DAT")); System.IO.File.Delete(dice1); string dice2 = tlzcDecompressToTempFile(Path.Combine(extractPath, "E_MG_STONERESULT02.DAT")); BlockCopy(dice2, 0x100, dice2, 0x100100, 0x100000); tlzcCompress(dice2, Path.Combine(extractPath, "E_MG_STONERESULT02.DAT")); System.IO.File.Delete(dice2); // remaining assets with xdelta patches foreach (string patch in Util.DirectoryGetFilesWorkaround(patchDir)) { string fileName = Path.GetFileNameWithoutExtension(patch); string sourcePath = Path.Combine(extractPath, fileName + ".DAT"); string decompressedPath = tlzcDecompressToTempFile(sourcePath); string patchedPath = TempUtil.GetTempFileName(); XdeltaApply(decompressedPath, patchedPath, patch); tlzcCompress(patchedPath, sourcePath); System.IO.File.Delete(decompressedPath); System.IO.File.Delete(patchedPath); } // pack up modified effect.svo if (worker != null) { worker.ReportProgress(100, "Packing modified file..."); } Logger.LogDirData(extractPath, "effect dir patched"); using (var fps4 = new FPS4(effectPath)) { fps4.Alignment = 0x800; fps4.Pack(extractPath, outPath); } Logger.LogFileData(outPath, "effect.svo patched"); // clean up Util.DeleteDirectoryAggressive(extractPath, true); if (outMd5 != null) { CompareMd5Output(outPath, outMd5); } }
public static void PatchUI(string uiPath, string patchDir, string outDir, string outMd5 = null, BackgroundWorker worker = null) { if (!File.Exists(uiPath)) { throw new PatchingException("File not found: " + uiPath); } if (worker != null) { worker.ReportProgress(0, "Confirming source file..."); } // if patched file exists and matches, exit early string outPath = Path.Combine(outDir, "UI.svo"); try { CompareMd5Output(outPath, outMd5); return; } catch (PatchingException) { } catch (FileNotFoundException) { } CompareMd5(uiPath, "9d0a479c838c4811e5df5f6a6815071d"); Logger.LogFileData(uiPath, "UI.svo"); Logger.LogDirData(patchDir, "UI patches"); // extract if (worker != null) { worker.ReportProgress(0, "Extracting source file..."); } string extractPath = svoExtractToTempDir(uiPath); // patch int i = 0; var files = Util.DirectoryGetFilesWorkaround(patchDir); foreach (string patch in files) { if (worker != null) { worker.ReportProgress((i / files.Length) * 100, "Patching file " + (i + 1) + " of " + files.Length + "..."); } string fileName = Path.GetFileNameWithoutExtension(patch); string sourcePath = Path.Combine(extractPath, fileName); string patchedPath = TempUtil.GetTempFileName(); XdeltaApply(sourcePath, patchedPath, patch); File.Delete(sourcePath); File.Move(patchedPath, sourcePath); ++i; } // copy unchanged 360 english files over japanese ones File.Copy(Path.Combine(extractPath, "MINIGAMEISHI_E.TXV"), Path.Combine(extractPath, "MINIGAMEISHI.TXV"), true); File.Copy(Path.Combine(extractPath, "EVENTMAP_E.TXV"), Path.Combine(extractPath, "EVENTMAP.TXV"), true); // copy english poker text textures to new PS3 poker deck BlockCopy(Path.Combine(extractPath, "MINIGAMEPOKER_E.TXV"), 0x0, Path.Combine(extractPath, "MINIGAMEPOKER.TXV"), 0x0, 0x6AB900); BlockCopy(Path.Combine(extractPath, "MINIGAMEPOKER_E.TXV"), 0x14519E0, Path.Combine(extractPath, "MINIGAMEPOKER.TXV"), 0x14519E0, 0x5E620); // pack if (worker != null) { worker.ReportProgress(100, "Packing modified file..."); } Logger.LogDirData(extractPath, "UI dir patched"); using (var fps4btl = new FPS4(uiPath)) { fps4btl.Alignment = 0x800; fps4btl.Pack(extractPath, outPath); } Logger.LogFileData(outPath, "UI.svo patched"); Util.DeleteDirectoryAggressive(extractPath, true); if (outMd5 != null) { CompareMd5Output(outPath, outMd5); } }
public static void PatchBtl(string btlPath, string patchDir, string outDir, string outMd5 = null, BackgroundWorker worker = null) { if (!File.Exists(btlPath)) { throw new PatchingException("File not found: " + btlPath); } if (worker != null) { worker.ReportProgress(0, "Confirming source file..."); } // if patched file exists and matches, exit early string outPath = Path.Combine(outDir, "btl.svo"); try { CompareMd5Output(outPath, outMd5); return; } catch (PatchingException) { } catch (FileNotFoundException) { } CompareMd5(btlPath, "37bed259717dd27e5145d8899e7c36d9"); Logger.LogFileData(btlPath, "btl.svo"); Logger.LogDirData(patchDir, "btl patches"); // extract if (worker != null) { worker.ReportProgress(0, "Extracting source file..."); } string extractPath = svoExtractToTempDir(btlPath); string btlPackPath = svoExtractToTempDir(Path.Combine(extractPath, "BTL_PACK.DAT")); string file3Path = svoExtractToTempDir(Path.Combine(btlPackPath, "0003"), nometa: true); // patch int i = 0; var files = Util.DirectoryGetFilesWorkaround(patchDir); foreach (string patch in files) { if (worker != null) { worker.ReportProgress((i / files.Length) * 100, "Patching file " + (i + 1) + " of " + files.Length + "..."); } string fileName = Path.GetFileNameWithoutExtension(patch); string sourcePath = Path.Combine(file3Path, "0" + fileName); string decompressedPath = tlzcDecompressToTempFile(sourcePath); string patchedPath = TempUtil.GetTempFileName(); XdeltaApply(decompressedPath, patchedPath, patch); tlzcCompress(patchedPath, sourcePath); System.IO.File.Delete(decompressedPath); System.IO.File.Delete(patchedPath); ++i; } // pack if (worker != null) { worker.ReportProgress(100, "Packing modified file..."); } Logger.LogDirData(file3Path, "btl/btl_pack/3 dir patched"); using (var fps4file3 = new FPS4(Path.Combine(btlPackPath, "0003"))) { fps4file3.Alignment = 0x80; fps4file3.Pack(file3Path, Path.Combine(btlPackPath, "0003.new")); } File.Delete(Path.Combine(btlPackPath, "0003")); File.Move(Path.Combine(btlPackPath, "0003.new"), Path.Combine(btlPackPath, "0003")); Util.DeleteDirectoryAggressive(file3Path, true); using (var fps4btlPack = new FPS4(Path.Combine(extractPath, "BTL_PACK.DAT"))) { fps4btlPack.Alignment = 0x80; fps4btlPack.Pack(btlPackPath, Path.Combine(extractPath, "BTL_PACK.DAT.new")); } File.Delete(Path.Combine(extractPath, "BTL_PACK.DAT")); File.Move(Path.Combine(extractPath, "BTL_PACK.DAT.new"), Path.Combine(extractPath, "BTL_PACK.DAT")); Util.DeleteDirectoryAggressive(btlPackPath, true); Logger.LogDirData(extractPath, "btl dir patched"); using (var fps4btl = new FPS4(btlPath)) { fps4btl.Alignment = 0x800; fps4btl.Pack(extractPath, outPath); } Logger.LogFileData(outPath, "btl.svo patched"); Util.DeleteDirectoryAggressive(extractPath, true); if (outMd5 != null) { CompareMd5Output(outPath, outMd5); } }
public static void PatchScenario(string scenarioPath, string patchDir, string outDir, string outMd5 = null, BackgroundWorker worker = null) { if (!File.Exists(scenarioPath)) { throw new PatchingException("File not found: " + scenarioPath); } if (worker != null) { worker.ReportProgress(0, "Confirming source file..."); } // if patched file exists and matches, exit early string outPath = Path.Combine(outDir, "scenario.dat"); try { CompareMd5Output(outPath, outMd5); return; } catch (PatchingException) { } catch (FileNotFoundException) { } CompareMd5(scenarioPath, "4ef82c6ebc5f1303b07c97aa848db123"); Logger.LogFileData(scenarioPath, "scenario.dat"); Logger.LogDirData(patchDir, "scenario patches"); // extract scenario.dat if (worker != null) { worker.ReportProgress(0, "Extracting source file..."); } string extractPath = TempUtil.GetTempFileName(); if (Directory.Exists(extractPath)) { Util.DeleteDirectoryAggressive(extractPath, true); } Directory.CreateDirectory(extractPath); var scenario = new HyoutaTools.Tales.Vesperia.Scenario.ScenarioDat(new System.IO.FileStream(scenarioPath, System.IO.FileMode.Open)); scenario.Extract(extractPath); // patch all files int i = 0; var files = Util.DirectoryGetFilesWorkaround(extractPath); foreach (var f in files) { if (worker != null) { worker.ReportProgress((i / files.Length) * 100, "Patching file " + (i + 1) + " of " + files.Length + "..."); } var tempfileDecomp = TempUtil.GetTempFileName(); var tempfilePatched = TempUtil.GetTempFileName(); ComptoeDecompress(f, tempfileDecomp); XdeltaApply( tempfileDecomp, tempfilePatched, Path.Combine(patchDir, Path.GetFileNameWithoutExtension(f) + ".xdelta3") ); ComptoeCompress(tempfilePatched, f); File.Delete(tempfileDecomp); File.Delete(tempfilePatched); ++i; } // pack it back up if (worker != null) { worker.ReportProgress(100, "Packing modified file..."); } Logger.LogDirData(extractPath, "scenario dir patched"); using (var scenarioNew = new HyoutaTools.Tales.Vesperia.Scenario.ScenarioDat()) { scenarioNew.Import(extractPath); scenarioNew.Write(outPath); } Logger.LogFileData(outPath, "scenario.dat patched"); // clean up Util.DeleteDirectoryAggressive(extractPath, true); if (outMd5 != null) { CompareMd5Output(outPath, outMd5); } }
public static void PatchElf(string ebootPath, string patchDir, string outDir, string outMd5 = null, BackgroundWorker worker = null) { string ebootModPath = Path.GetFullPath("ebootmod/ebootMOD.exe"); ebootPath = Path.GetFullPath(ebootPath); patchDir = Path.GetFullPath(patchDir); outDir = Path.GetFullPath(outDir); if (!File.Exists(ebootPath)) { throw new PatchingException("File not found: " + ebootPath); } if (worker != null) { worker.ReportProgress(0, "Confirming source file..."); } Patcher.CompareMd5(ebootPath, "3171173bba33c43be95e840733ca40a8"); // decrypt if (worker != null) { worker.ReportProgress(0, "Decrypting..."); } string elfPath = Path.Combine(Path.GetDirectoryName(ebootModPath), Path.GetFileName(ebootPath) + "-mod.ELF"); int tries = 5; while (!(File.Exists(elfPath) && Patcher.CalcMd5(elfPath) == "a424aa775b707539dbff08cdb2e61ff5")) { if (--tries < 0) { throw new PatchingException("Could not decrypt EBOOT. Confirm that EBOOT is correctly ripped and ebootMOD is working correctly."); } // this is super ugly but the only sensible way since calling unself directly searches the keys who-knows-where try { RunEbootModAndKill(ebootModPath, "\"" + ebootPath + "\""); } catch (Exception e) { throw new PatchingException("Failed during execution of ebootMOD. Make sure you copied _everything_ from the ebootmod archive into the ebootmod folder and try again.", e); } // sleep a bit to reduce chance of ebootMod still having the file handle System.Threading.Thread.Sleep(250); } // patch the elf if (worker != null) { worker.ReportProgress(0, "Patching..."); } string patchedElf = TempUtil.GetTempFileName(); Patcher.XdeltaApply(elfPath, patchedElf, Path.Combine(patchDir, "ToV.elf.xdelta3")); if (outMd5 != null) { Patcher.CompareMd5Output(patchedElf, outMd5); } // encrypt if (worker != null) { worker.ReportProgress(0, "Encrypting..."); } string outPath = Path.Combine(outDir, "EBOOT.BIN"); RunEbootMod(ebootModPath, ebootPath, patchedElf, outPath); File.Delete(patchedElf); }
private void PatchForm_Load(object sender, EventArgs e) { TempUtil.RemoveTempFolder(); if (!Directory.Exists("new/patches")) { MessageBox.Show(this, "Patch folder could not be found at " + Path.GetFullPath("new/patches") + "." + Environment.NewLine + "Please make sure the archive containing the patch files was fully extracted and no files were moved or renamed, then run the patcher again.", "Patches not found!", MessageBoxButtons.OK, MessageBoxIcon.Error ); Close(); return; } if (!CheckForExecutable("comptoe") || !CheckForExecutable("xdelta")) { Close(); return; } if (!LoadOutputChecksums()) { Close(); return; } string ebootModPath = Path.GetFullPath("ebootmod/ebootMOD.exe"); if (!File.Exists(ebootModPath)) { MessageBox.Show(this, "ebootMOD could not be found at " + ebootModPath + "." + Environment.NewLine + "ebootMOD is required to patch EBOOT.BIN. Please read the readme, find a copy of ebootMOD, and place it at the appropriate location." + Environment.NewLine + "The patcher will still run, but will not be able to patch EBOOT.BIN until you do so.", "ebootMOD not found!", MessageBoxButtons.OK, MessageBoxIcon.Warning ); } fileSelectControlElf.LabelText = "EBOOT.BIN"; fileSelectControlElf.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "EBOOT.BIN"); fileSelectControlElf.PatchDir = "new/patches"; fileSelectControlElf.PatchFunction = ElfPatcher.PatchElf; fileSelectControlElf.OutputChecksum = OutputChecksums.GetValueOrDefault("ToV.elf", null); fileSelectControlString.LabelText = "string.svo"; fileSelectControlString.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "string.svo"); fileSelectControlString.PatchDir = "new/patches"; fileSelectControlString.PatchFunction = Patcher.PatchString; fileSelectControlString.OutputChecksum = OutputChecksums.GetValueOrDefault("string.svo", null); fileSelectControlScenario.LabelText = "scenario.dat"; fileSelectControlScenario.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "scenario.dat"); fileSelectControlScenario.PatchDir = "new/patches/scenario"; fileSelectControlScenario.PatchFunction = Patcher.PatchScenario; fileSelectControlScenario.OutputChecksum = OutputChecksums.GetValueOrDefault("scenario.dat", null); fileSelectControlBtl.LabelText = "btl.svo"; fileSelectControlBtl.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "btl.svo"); fileSelectControlBtl.PatchDir = "new/patches/btl"; fileSelectControlBtl.PatchFunction = Patcher.PatchBtl; fileSelectControlBtl.OutputChecksum = OutputChecksums.GetValueOrDefault("btl.svo", null); fileSelectControlChat.LabelText = "chat.svo"; fileSelectControlChat.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "chat.svo"); fileSelectControlChat.PatchDir = "new/patches/chat"; fileSelectControlChat.PatchFunction = Patcher.PatchChat; fileSelectControlChat.OutputChecksum = OutputChecksums.GetValueOrDefault("chat.svo", null); fileSelectControlUI.LabelText = "UI.svo"; fileSelectControlUI.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "UI.svo"); fileSelectControlUI.PatchDir = "new/patches/UI"; fileSelectControlUI.PatchFunction = Patcher.PatchUI; fileSelectControlUI.OutputChecksum = OutputChecksums.GetValueOrDefault("UI.svo", null); fileSelectControlEffect.LabelText = "effect.svo"; fileSelectControlEffect.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "effect.svo"); fileSelectControlEffect.PatchDir = "new/patches/effect"; fileSelectControlEffect.PatchFunction = Patcher.PatchEffect; fileSelectControlEffect.OutputChecksum = OutputChecksums.GetValueOrDefault("effect.svo", null); fileSelectControlChara.LabelText = "chara.svo"; fileSelectControlChara.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "chara.svo"); fileSelectControlChara.PatchDir = "new/patches/chara"; fileSelectControlChara.PatchFunction = Patcher.PatchChara; fileSelectControlChara.OutputChecksum = OutputChecksums.GetValueOrDefault("chara.svo", null); fileSelectControlMenu.LabelText = "menu.svo"; fileSelectControlMenu.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "menu.svo"); fileSelectControlMenu.PatchDir = "new/patches"; fileSelectControlMenu.PatchFunction = Patcher.PatchMenu; fileSelectControlMenu.OutputChecksum = OutputChecksums.GetValueOrDefault("menu.svo", null); fileSelectControlParam.LabelText = "PARAM.SFO"; fileSelectControlParam.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "PARAM.SFO"); fileSelectControlParam.PatchDir = null; fileSelectControlParam.PatchFunction = Patcher.PatchParam; fileSelectControlParam.OutputChecksum = OutputChecksums.GetValueOrDefault("PARAM.SFO", null); fileSelectControlTrophy.LabelText = "TROPHY.TRP"; fileSelectControlTrophy.FilePath = Path.Combine(Directory.GetCurrentDirectory(), "TROPHY.TRP"); fileSelectControlTrophy.PatchDir = "new/patches"; fileSelectControlTrophy.PatchFunction = PatchTrophyAfterWarning; fileSelectControlTrophy.OutputChecksum = OutputChecksums.GetValueOrDefault("TROPHY.TRP", null); FileSelectControls.Add(fileSelectControlElf); FileSelectControls.Add(fileSelectControlBtl); FileSelectControls.Add(fileSelectControlChara); FileSelectControls.Add(fileSelectControlChat); FileSelectControls.Add(fileSelectControlEffect); FileSelectControls.Add(fileSelectControlMenu); FileSelectControls.Add(fileSelectControlScenario); FileSelectControls.Add(fileSelectControlString); FileSelectControls.Add(fileSelectControlUI); FileSelectControls.Add(fileSelectControlParam); FileSelectControls.Add(fileSelectControlTrophy); }