From 4c1e0d844e558fb2e1394a107e7e2a08d49e27b9 Mon Sep 17 00:00:00 2001 From: Boris Timofeev Date: Mon, 6 Mar 2017 21:52:11 +0300 Subject: [PATCH] Add option "ignore checksum" --- app/src/main/cpp/xdelta3.c | 12 +++++--- .../java/org/emunix/unipatcher/Settings.java | 5 ++++ .../org/emunix/unipatcher/WorkerService.java | 2 +- .../org/emunix/unipatcher/patcher/APS.java | 4 +-- .../emunix/unipatcher/patcher/APS_GBA.java | 7 +++-- .../emunix/unipatcher/patcher/APS_N64.java | 8 ++++-- .../org/emunix/unipatcher/patcher/BPS.java | 18 +++++++----- .../org/emunix/unipatcher/patcher/DPS.java | 10 ++++--- .../org/emunix/unipatcher/patcher/EBP.java | 12 ++++---- .../org/emunix/unipatcher/patcher/IPS.java | 4 +++ .../org/emunix/unipatcher/patcher/PPF.java | 28 +++++++++++-------- .../emunix/unipatcher/patcher/Patcher.java | 2 +- .../org/emunix/unipatcher/patcher/UPS.java | 14 ++++++---- .../org/emunix/unipatcher/patcher/XDelta.java | 6 ++-- app/src/main/res/values-ru/strings.xml | 3 ++ app/src/main/res/values/strings.xml | 3 ++ app/src/main/res/xml/preferences.xml | 8 ++++++ .../emunix/unipatcher/patcher/BPSTest.java | 2 +- .../emunix/unipatcher/patcher/UPSTest.java | 2 +- 19 files changed, 99 insertions(+), 51 deletions(-) diff --git a/app/src/main/cpp/xdelta3.c b/app/src/main/cpp/xdelta3.c index a02e5f5..86842ea 100644 --- a/app/src/main/cpp/xdelta3.c +++ b/app/src/main/cpp/xdelta3.c @@ -30,7 +30,7 @@ along with UniPatcher. If not, see . #include "xdelta3/xdelta3/xdelta3.h" #include "xdelta3/xdelta3/xdelta3.c" -int apply(FILE *patch, FILE *in, FILE *out); +int apply(FILE *patch, FILE *in, FILE *out, int ignoreChecksum); const int ERR_UNABLE_OPEN_PATCH = -5001; const int ERR_UNABLE_OPEN_ROM = -5002; @@ -41,7 +41,8 @@ int Java_org_emunix_unipatcher_patcher_XDelta_xdelta3apply(JNIEnv *env, jobject this, jstring patchPath, jstring romPath, - jstring outputPath) { + jstring outputPath, + jboolean ignoreChecksum) { int ret = 0; const char *patchName = (*env)->GetStringUTFChars(env, patchPath, NULL); const char *romName = (*env)->GetStringUTFChars(env, romPath, NULL); @@ -70,7 +71,7 @@ int Java_org_emunix_unipatcher_patcher_XDelta_xdelta3apply(JNIEnv *env, return ERR_UNABLE_OPEN_OUTPUT; } - ret = apply(patchFile, romFile, outputFile); + ret = apply(patchFile, romFile, outputFile, (int)ignoreChecksum); fclose(patchFile); fclose(romFile); @@ -78,7 +79,7 @@ int Java_org_emunix_unipatcher_patcher_XDelta_xdelta3apply(JNIEnv *env, return ret; } -int apply(FILE *patch, FILE *in, FILE *out) { +int apply(FILE *patch, FILE *in, FILE *out, int ignoreChecksum) { int BUFFER_SIZE = 32768; int r, ret; @@ -93,6 +94,9 @@ int apply(FILE *patch, FILE *in, FILE *out) { xd3_init_config(&config, 0); config.winsize = BUFFER_SIZE; + if (ignoreChecksum) { + config.flags |= XD3_ADLER32_NOVER; + } xd3_config_stream(&stream, &config); source.blksize = BUFFER_SIZE; diff --git a/app/src/main/java/org/emunix/unipatcher/Settings.java b/app/src/main/java/org/emunix/unipatcher/Settings.java index f1b98b0..c71d277 100644 --- a/app/src/main/java/org/emunix/unipatcher/Settings.java +++ b/app/src/main/java/org/emunix/unipatcher/Settings.java @@ -69,4 +69,9 @@ public class Settings { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); return prefs.getString("output_directory", ""); } + + public static boolean getIgnoreChecksum(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + return prefs.getBoolean("ignore_checksum", false); + } } diff --git a/app/src/main/java/org/emunix/unipatcher/WorkerService.java b/app/src/main/java/org/emunix/unipatcher/WorkerService.java index 5cb7459..dcc2dff 100644 --- a/app/src/main/java/org/emunix/unipatcher/WorkerService.java +++ b/app/src/main/java/org/emunix/unipatcher/WorkerService.java @@ -158,7 +158,7 @@ public class WorkerService extends IntentService { try { if ("ppf".equals(ext)) Utils.copyFile(this, romFile, outputFile); - patcher.apply(); + patcher.apply(Settings.getIgnoreChecksum(this)); } catch (PatchException | IOException e) { if (Utils.getFreeSpace(outputFile.getParentFile()) == 0) { errorMsg = getString(R.string.notify_error_not_enough_space); diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/APS.java b/app/src/main/java/org/emunix/unipatcher/patcher/APS.java index 5c2f9be..8fdc7e5 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/APS.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/APS.java @@ -43,7 +43,7 @@ public class APS extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { Patcher aps = null; switch (checkAPS(patchFile)) { case APS_N64_PATCH: @@ -56,7 +56,7 @@ public class APS extends Patcher { throw new PatchException(context.getString(R.string.notify_error_not_aps_patch)); } - aps.apply(); + aps.apply(ignoreChecksum); } public int checkAPS(File file) throws PatchException, IOException { diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/APS_GBA.java b/app/src/main/java/org/emunix/unipatcher/patcher/APS_GBA.java index 1fd36cf..60f4412 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/APS_GBA.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/APS_GBA.java @@ -77,7 +77,7 @@ public class APS_GBA extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { long fileSize1, fileSize2, bytesLeft, offset; int crc, patchCrc1, patchCrc2, pCount, oCount; boolean isOriginal = false; @@ -138,7 +138,8 @@ public class APS_GBA extends Patcher { } else if (crc == patchCrc2) { isModified = true; } else { - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); } if (isOriginal && isModified) throw new PatchException(context.getString(R.string.notify_error_not_aps_patch)); @@ -153,7 +154,7 @@ public class APS_GBA extends Patcher { if (isOriginal) { Utils.truncateFile(outputFile, fileSize2); - } else { + } else if (isModified) { Utils.truncateFile(outputFile, fileSize1); } } diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/APS_N64.java b/app/src/main/java/org/emunix/unipatcher/patcher/APS_N64.java index 2faa42a..694b712 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/APS_N64.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/APS_N64.java @@ -47,7 +47,7 @@ public class APS_N64 extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { BufferedInputStream romStream = null; BufferedInputStream patchStream = null; BufferedOutputStream outputStream = null; @@ -96,8 +96,10 @@ public class APS_N64 extends Patcher { int country = patchStream.read(); byte[] crc = new byte[8]; patchStream.read(crc); - if (!validateROM(endianness, cardID, country, crc)) - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + if (!validateROM(endianness, cardID, country, crc)) + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } // skip bytes for future expansion byte[] skip = new byte[5]; patchStream.read(skip); diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/BPS.java b/app/src/main/java/org/emunix/unipatcher/patcher/BPS.java index 46719ff..922226a 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/BPS.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/BPS.java @@ -50,7 +50,7 @@ public class BPS extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { if (patchFile.length() < 19) { throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); @@ -68,9 +68,11 @@ public class BPS extends Patcher { if (bpsCrc.getPatchFileCRC() != bpsCrc.getRealPatchCRC()) throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); - long realRomCrc = FileUtils.checksumCRC32(romFile); - if (realRomCrc != bpsCrc.getInputFileCRC()) { - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + long realRomCrc = FileUtils.checksumCRC32(romFile); + if (realRomCrc != bpsCrc.getInputFileCRC()) { + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } } patch = new RandomAccessFile(patchFile, "r").getChannel(); @@ -133,9 +135,11 @@ public class BPS extends Patcher { IOUtils.closeQuietly(output); } - long realOutCrc = FileUtils.checksumCRC32(outputFile); - if (realOutCrc != bpsCrc.getOutputFileCRC()) - throw new PatchException(context.getString(R.string.notify_error_wrong_checksum_after_patching)); + if(!ignoreChecksum) { + long realOutCrc = FileUtils.checksumCRC32(outputFile); + if (realOutCrc != bpsCrc.getOutputFileCRC()) + throw new PatchException(context.getString(R.string.notify_error_wrong_checksum_after_patching)); + } } // decode pointer diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/DPS.java b/app/src/main/java/org/emunix/unipatcher/patcher/DPS.java index bcf60a7..4f848b4 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/DPS.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/DPS.java @@ -42,7 +42,7 @@ public class DPS extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { if (patchFile.length() < MIN_SIZE_PATCH) { throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); @@ -63,9 +63,11 @@ public class DPS extends Patcher { throw new PatchException(context.getString(R.string.notify_error_not_dps_patch)); // verify rom - long romSize = getUInt(buffer, 194); - if (romSize != romFile.length()) - throw new IOException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + long romSize = getUInt(buffer, 194); + if (romSize != romFile.length()) + throw new IOException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } romStream = new RandomAccessFile(romFile, "r"); outputStream = new RandomAccessFile(outputFile, "rw"); diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/EBP.java b/app/src/main/java/org/emunix/unipatcher/patcher/EBP.java index fb3457b..b86901d 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/EBP.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/EBP.java @@ -68,12 +68,12 @@ public class EBP extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { File cleanRom = File.createTempFile("rom", null, context.getCacheDir()); File ipsPatch = File.createTempFile("patch", null, context.getCacheDir()); try { Utils.copyFile(context, romFile, cleanRom); - prepareCleanRom(cleanRom); + prepareCleanRom(cleanRom, ignoreChecksum); EBPtoIPS(patchFile, ipsPatch); @@ -85,7 +85,7 @@ public class EBP extends Patcher { } } - private void prepareCleanRom(File file) throws IOException, PatchException { + private void prepareCleanRom(File file, boolean ignoreChecksum) throws IOException, PatchException { // delete smc header SnesSmcHeader smc = new SnesSmcHeader(); try { @@ -95,8 +95,10 @@ public class EBP extends Patcher { } // check rom size and remove unused expanded space - if (file.length() < EB_CLEAN_ROM_SIZE) - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + if (file.length() < EB_CLEAN_ROM_SIZE) + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } if (file.length() > EB_CLEAN_ROM_SIZE && checkExpanded(file)) removeExpanded(file); diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/IPS.java b/app/src/main/java/org/emunix/unipatcher/patcher/IPS.java index 23f69d8..65dce3e 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/IPS.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/IPS.java @@ -50,6 +50,10 @@ public class IPS extends Patcher { } @Override + public void apply(boolean ignoreChecksum) throws PatchException, IOException { + apply(); + } + public void apply() throws PatchException, IOException { BufferedInputStream romStream = null; BufferedInputStream patchStream = null; diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/PPF.java b/app/src/main/java/org/emunix/unipatcher/patcher/PPF.java index 1bc5005..373e2bd 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/PPF.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/PPF.java @@ -68,7 +68,7 @@ public class PPF extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { if (patchFile.length() < 61) { throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); } @@ -78,10 +78,10 @@ public class PPF extends Patcher { applyPPF1(); break; case 2: - applyPPF2(); + applyPPF2(ignoreChecksum); break; case 3: - applyPPF3(); + applyPPF3(ignoreChecksum); break; default: throw new PatchException(context.getString(R.string.notify_error_not_ppf_patch)); @@ -112,15 +112,17 @@ public class PPF extends Patcher { } } - private void applyPPF2() throws IOException, PatchException { + private void applyPPF2(boolean ignoreChecksum) throws IOException, PatchException { try { patchStream = new RandomAccessFile(patchFile, "r"); // Check size of ROM patchStream.seek(56); long romSize = readLittleEndianInt(patchStream); - if (romSize != romFile.length()) { - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + if (romSize != romFile.length()) { + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } } outputStream = new RandomAccessFile(outputFile, "rw"); @@ -131,8 +133,10 @@ public class PPF extends Patcher { outputStream.seek(0x9320); patchStream.read(patchBinaryBlock, 0, 1024); outputStream.read(romBinaryBlock, 0, 1024); - if (!Arrays.equals(patchBinaryBlock, romBinaryBlock)) - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + if (!Arrays.equals(patchBinaryBlock, romBinaryBlock)) + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } // Calculate end of patch data long dataEnd = patchFile.length(); @@ -160,7 +164,7 @@ public class PPF extends Patcher { } } - private void applyPPF3() throws IOException, PatchException { + private void applyPPF3(boolean ignoreChecksum) throws IOException, PatchException { try { patchStream = new RandomAccessFile(patchFile, "r"); outputStream = new RandomAccessFile(outputFile, "rw"); @@ -182,8 +186,10 @@ public class PPF extends Patcher { } patchStream.read(patchBinaryBlock, 0, 1024); outputStream.read(romBinaryBlock, 0, 1024); - if (!Arrays.equals(patchBinaryBlock, romBinaryBlock)) - throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + if (!Arrays.equals(patchBinaryBlock, romBinaryBlock)) + throw new PatchException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } } // Calculate end of patch data diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/Patcher.java b/app/src/main/java/org/emunix/unipatcher/patcher/Patcher.java index bbadf2e..4ff5512 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/Patcher.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/Patcher.java @@ -37,5 +37,5 @@ public abstract class Patcher { outputFile = output; } - public abstract void apply() throws PatchException, IOException; + public abstract void apply(boolean ignoreChecksum) throws PatchException, IOException; } diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/UPS.java b/app/src/main/java/org/emunix/unipatcher/patcher/UPS.java index 9383dec..81e19b0 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/UPS.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/UPS.java @@ -44,7 +44,7 @@ public class UPS extends Patcher { } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { if (patchFile.length() < 18) { throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); @@ -90,7 +90,9 @@ public class UPS extends Patcher { ySize = tmp; upsCrc.swapInOut(); } else { - throw new IOException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + if (!ignoreChecksum) { + throw new IOException(context.getString(R.string.notify_error_rom_not_compatible_with_patch)); + } } romStream = new BufferedInputStream(new FileInputStream(romFile)); @@ -125,9 +127,11 @@ public class UPS extends Patcher { IOUtils.closeQuietly(outputStream); } - long realOutCrc = FileUtils.checksumCRC32(outputFile); - if (realOutCrc != upsCrc.getOutputFileCRC()) - throw new PatchException(context.getString(R.string.notify_error_wrong_checksum_after_patching)); + if (!ignoreChecksum) { + long realOutCrc = FileUtils.checksumCRC32(outputFile); + if (realOutCrc != upsCrc.getOutputFileCRC()) + throw new PatchException(context.getString(R.string.notify_error_wrong_checksum_after_patching)); + } } // decode pointer diff --git a/app/src/main/java/org/emunix/unipatcher/patcher/XDelta.java b/app/src/main/java/org/emunix/unipatcher/patcher/XDelta.java index 970a1fb..153ff41 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/XDelta.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/XDelta.java @@ -38,14 +38,14 @@ public class XDelta extends Patcher { private static final int ERR_WRONG_CHECKSUM = -5010; private static final int ERR_INVALID_INPUT = -17712; - public static native int xdelta3apply(String patchPath, String romPath, String outputPath); + public static native int xdelta3apply(String patchPath, String romPath, String outputPath, boolean ignoreChecksum); public XDelta(Context context, File patch, File rom, File output) { super(context, patch, rom, output); } @Override - public void apply() throws PatchException, IOException { + public void apply(boolean ignoreChecksum) throws PatchException, IOException { if (checkXDelta1(patchFile)) throw new PatchException(context.getString(R.string.notify_error_xdelta1_unsupported)); @@ -55,7 +55,7 @@ public class XDelta extends Patcher { throw new PatchException(context.getString(R.string.notify_error_failed_load_lib_xdelta3)); } - int ret = xdelta3apply(patchFile.getPath(), romFile.getPath(), outputFile.getPath()); + int ret = xdelta3apply(patchFile.getPath(), romFile.getPath(), outputFile.getPath(), ignoreChecksum); switch (ret) { case NO_ERROR: diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 585fec2..803be43 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -113,6 +113,9 @@ Укажите директорию с патчами Укажите директорию для сохранения Иначе ROM будет сохранён в директорию с ROM\'ами + Применение патчей + Игнорировать контрольную сумму + Не показывать ошибку, если используется неподходящий ROM. Используйте осторожно: включив эту опцию можно получить непроходимую игру. Помощь diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ca5a176..63af5a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -113,6 +113,9 @@ Specify patches directory Specify output directory Otherwise ROM will be stored in the ROM directory + Patching + Ignore checksums + Do not interrupt patching if you use the wrong ROM. Use caution: this option can break your game. Help diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 5d3ea05..f0a1a97 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -33,4 +33,12 @@ android:summary="@string/settings_output_directory_description" android:title="@string/settings_output_directory"/> + + + + \ No newline at end of file diff --git a/app/src/test/java/org/emunix/unipatcher/patcher/BPSTest.java b/app/src/test/java/org/emunix/unipatcher/patcher/BPSTest.java index 947a5e4..c4f1b89 100644 --- a/app/src/test/java/org/emunix/unipatcher/patcher/BPSTest.java +++ b/app/src/test/java/org/emunix/unipatcher/patcher/BPSTest.java @@ -48,7 +48,7 @@ public class BPSTest { BPS patcher = new BPS(mockContext, patch, in, out); try { - patcher.apply(); + patcher.apply(false); } catch (PatchException | IOException e) { fail("Patching failed"); } diff --git a/app/src/test/java/org/emunix/unipatcher/patcher/UPSTest.java b/app/src/test/java/org/emunix/unipatcher/patcher/UPSTest.java index f2b3adf..b36776f 100644 --- a/app/src/test/java/org/emunix/unipatcher/patcher/UPSTest.java +++ b/app/src/test/java/org/emunix/unipatcher/patcher/UPSTest.java @@ -67,7 +67,7 @@ public class UPSTest { UPS patcher = new UPS(mockContext, patch, in, out); try { - patcher.apply(); + patcher.apply(false); } catch (PatchException | IOException e) { fail("Patching failed"); }