diff --git a/README.md b/README.md index 9330beb..bdf1ada 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ UniPatcher ---------- -UniPatcher is a ROM patcher for Android that supports IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patch types. +UniPatcher is a ROM patcher for Android that supports IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patch types. ### Additional features: 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 7e7871d..c732fa9 100644 --- a/app/src/main/java/org/emunix/unipatcher/patcher/IPS.java +++ b/app/src/main/java/org/emunix/unipatcher/patcher/IPS.java @@ -1,5 +1,5 @@ /* -Copyright (C) 2013, 2016 Boris Timofeev +Copyright (C) 2013, 2016, 2017 Boris Timofeev This file is part of UniPatcher. @@ -36,7 +36,12 @@ import java.util.Arrays; public class IPS extends Patcher { - private static final byte[] MAGIC_NUMBER = {0x50, 0x41, 0x54, 0x43, 0x48}; // "PATCH" + public static final int NOT_IPS_PATCH = 0; + public static final int IPS_PATCH = 1; + public static final int IPS32_PATCH = 2; + + private static final byte[] MAGIC_NUMBER_IPS = {0x50, 0x41, 0x54, 0x43, 0x48}; // "PATCH" + private static final byte[] MAGIC_NUMBER_IPS32 = {0x49, 0x50, 0x53, 0x33, 0x32}; // "IPS32" public IPS(Context context, File patch, File rom, File output) { super(context, patch, rom, output); @@ -44,6 +49,19 @@ public class IPS extends Patcher { @Override public void apply() throws PatchException, IOException { + switch (checkIPS(patchFile)) { + case IPS_PATCH: + applyIPS(); + break; + case IPS32_PATCH: + applyIPS32(); + break; + case NOT_IPS_PATCH: + throw new PatchException(context.getString(R.string.notify_error_not_ips_patch)); + } + } + + public void applyIPS() throws PatchException, IOException { BufferedInputStream romStream = null; BufferedInputStream patchStream = null; @@ -67,17 +85,17 @@ public class IPS extends Patcher { // check magic string byte[] magic = new byte[5]; size = patchStream.read(magic); - if (size != 5 || !Arrays.equals(magic, MAGIC_NUMBER)) + if (size != 5 || !Arrays.equals(magic, MAGIC_NUMBER_IPS)) throw new PatchException(context.getString(R.string.notify_error_not_ips_patch)); while (true) { - offset = readOffset(patchStream, 3); + offset = (int)readOffset(patchStream, 3); if (offset < 0) throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); if (offset == 0x454f46) { // EOF // truncate file or copy tail if (romPos < romSize) { - offset = readOffset(patchStream, 3); + offset = (int)readOffset(patchStream, 3); if (offset != -1 && offset >= romPos) { size = offset - romPos; } else { @@ -142,8 +160,119 @@ public class IPS extends Patcher { } } - private int readOffset(InputStream stream, int numBytes) throws IOException { - int offset = 0; + public void applyIPS32() throws PatchException, IOException { + + BufferedInputStream romStream = null; + BufferedInputStream patchStream = null; + BufferedOutputStream outputStream = null; + + try { + romStream = new BufferedInputStream(new FileInputStream(romFile)); + patchStream = new BufferedInputStream(new FileInputStream(patchFile)); + outputStream = new BufferedOutputStream(new FileOutputStream(outputFile)); + + long romSize = romFile.length(); + long romPos = 0; + long outPos = 0; + long offset; + long size; + + if (patchFile.length() < 16) { + throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); + } + + byte[] magic = new byte[5]; + size = patchStream.read(magic); + if (size != 5 || !Arrays.equals(magic, MAGIC_NUMBER_IPS32)) + throw new PatchException(context.getString(R.string.notify_error_not_ips_patch)); + + while (true) { + offset = readOffset(patchStream, 4); + if (offset < 0) + throw new PatchException(context.getString(R.string.notify_error_patch_corrupted)); + if (offset == 0x45454f46) { // EEOF + // copy tail + if (romPos < romSize) { + size = romSize - romPos; + Utils.copy(romStream, outputStream, size); + } + break; + } + + if (offset <= romSize) { + if (outPos < offset) { + size = offset - outPos; + Utils.copy(romStream, outputStream, size); + romPos += size; + outPos += size; + } + } else { + if (outPos < romSize) { + size = romSize - outPos; + Utils.copy(romStream, outputStream, size); + romPos += size; + outPos += size; + } + if (outPos < offset) { + size = offset - outPos; + Utils.copy(size, (byte) 0x0, outputStream); + outPos += size; + } + } + + size = (patchStream.read() << 8) + patchStream.read(); + if (size != 0) { + byte[] data = new byte[(int)size]; + patchStream.read(data); + outputStream.write(data); + outPos += size; + } else { // RLE + size = (patchStream.read() << 8) + patchStream.read(); + byte val = (byte) patchStream.read(); + byte[] data = new byte[(int)size]; + Arrays.fill(data, val); + outputStream.write(data); + outPos += size; + } + + if (offset <= romSize) { + if (romPos + size > romSize) { + romPos = (int) romSize; + } else { + byte[] buf = new byte[(int)size]; + romStream.read(buf); + romPos += size; + } + } + } + } finally { + IOUtils.closeQuietly(romStream); + IOUtils.closeQuietly(patchStream); + IOUtils.closeQuietly(outputStream); + } + } + + public int checkIPS(File file) throws PatchException, IOException { + FileInputStream stream = null; + try { + stream = new FileInputStream(file); + byte[] magic = new byte[5]; + int count = stream.read(magic); + if (count < 5) + throw new PatchException(context.getString(R.string.notify_error_not_ips_patch)); + if (Arrays.equals(magic, MAGIC_NUMBER_IPS)) { + return IPS_PATCH; + } else if (Arrays.equals(magic, MAGIC_NUMBER_IPS32)) { + return IPS32_PATCH; + } + } finally { + IOUtils.closeQuietly(stream); + } + return NOT_IPS_PATCH; + } + + private long readOffset(InputStream stream, int numBytes) throws IOException { + long offset = 0; while (numBytes-- != 0) { int b = stream.read(); if (b == -1) diff --git a/app/src/main/res/raw-it/about.md b/app/src/main/res/raw-it/about.md index dfc54de..a8a8663 100644 --- a/app/src/main/res/raw-it/about.md +++ b/app/src/main/res/raw-it/about.md @@ -1,4 +1,4 @@ -UniPatcher è un patcher che supporta i tipi di patch IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP e XDelta3. +UniPatcher è un patcher che supporta i tipi di patch IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP e XDelta3. Funzioni aggiuntive: diff --git a/app/src/main/res/raw-it/faq.md b/app/src/main/res/raw-it/faq.md index f64357a..d4540eb 100644 --- a/app/src/main/res/raw-it/faq.md +++ b/app/src/main/res/raw-it/faq.md @@ -6,7 +6,7 @@ UniPatcher è uno strumento per Android per applicare delle patch alle ROM di va #### Quali formati di patch sono supportati? -L'app supporta le patch IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP e XDelta3. +L'app supporta le patch IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP e XDelta3. #### Posso hackerare o crackare i giochi di Android con questa app? diff --git a/app/src/main/res/raw-pl/about.md b/app/src/main/res/raw-pl/about.md index 153777d..23f6ed0 100644 --- a/app/src/main/res/raw-pl/about.md +++ b/app/src/main/res/raw-pl/about.md @@ -1,4 +1,4 @@ -UniPatcher jest programem do łatkowania ROM-ów. Wsparcie dla typów łatek: IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP i XDelta3. +UniPatcher jest programem do łatkowania ROM-ów. Wsparcie dla typów łatek: IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP i XDelta3. Dodatkowe funkcje: diff --git a/app/src/main/res/raw-pl/faq.md b/app/src/main/res/raw-pl/faq.md index 5c57508..985d3db 100644 --- a/app/src/main/res/raw-pl/faq.md +++ b/app/src/main/res/raw-pl/faq.md @@ -6,7 +6,7 @@ UniPatcher jest narzędziem do łatkowania ROM-ów różnych konsol #### Jakie formaty łatek są obsługiwane? -The app supports IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patches. +The app supports IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patches. #### Czy mogę hakować albo crackować gry Android za pomocą tej aplikacji? diff --git a/app/src/main/res/raw-ru/about.md b/app/src/main/res/raw-ru/about.md index d454973..de90764 100644 --- a/app/src/main/res/raw-ru/about.md +++ b/app/src/main/res/raw-ru/about.md @@ -1,4 +1,4 @@ -UniPatcher это ROM патчер поддерживающий патчи в форматах IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3. +UniPatcher это ROM патчер поддерживающий патчи в форматах IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3. Дополнительные функции: diff --git a/app/src/main/res/raw-ru/faq.md b/app/src/main/res/raw-ru/faq.md index 5df31a6..34ffac0 100644 --- a/app/src/main/res/raw-ru/faq.md +++ b/app/src/main/res/raw-ru/faq.md @@ -6,7 +6,7 @@ #### Какие форматы патчей поддерживаются? -Приложение поддерживает патчи в форматах IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3. +Приложение поддерживает патчи в форматах IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3. #### Возможно ли с помощью этого приложения взломать игру для Android? diff --git a/app/src/main/res/raw/about.md b/app/src/main/res/raw/about.md index a31f1aa..ee8f18d 100644 --- a/app/src/main/res/raw/about.md +++ b/app/src/main/res/raw/about.md @@ -1,4 +1,4 @@ -UniPatcher is a ROM patcher that supports IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patch types. +UniPatcher is a ROM patcher that supports IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patch types. Additional features: diff --git a/app/src/main/res/raw/faq.md b/app/src/main/res/raw/faq.md index 18d0011..0ec73d8 100644 --- a/app/src/main/res/raw/faq.md +++ b/app/src/main/res/raw/faq.md @@ -6,7 +6,7 @@ UniPatcher is an Android tool for applying patches to ROM images of various vide #### What patch formats are supported? -The app supports IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patches. +The app supports IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patches. #### Can I hack or crack Android game using this app? diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index dabb22f..84da352 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -131,7 +131,7 @@ Non ci sono client email installati Condividi UniPatcher - Scarica il miglior patcher di ROM per Android. Supporta i formati IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP e XDelta3.\\n\\n + Scarica il miglior patcher di ROM per Android. Supporta i formati IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP e XDelta3.\\n\\n diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index f34f6d3..a6c992b 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -131,7 +131,7 @@ Tu nie ma żadnych klientów E-Mail zainstalowanych Udostępnij UniPatcher-a swoim znajomym - Pobierz najlepszy program do łatkowania ROM-ów. Wspiera typy łatek: IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP i XDelta3.\n\n + Pobierz najlepszy program do łatkowania ROM-ów. Wspiera typy łatek: IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP i XDelta3.\n\n Zastosuj łatkę diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 9a742e8..9a8abf6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -131,7 +131,7 @@ Не установлен email клиент Рассказать о UniPatcher - Скачай лучший ROM патчер для Android. Поддерживает патчи в форматах IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3.\\n\\n + Скачай лучший ROM патчер для Android. Поддерживает патчи в форматах IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3.\\n\\n diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e5108f2..98d6ceb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -131,7 +131,7 @@ There are no email clients installed Share UniPatcher - Download the best ROM patcher for Android. It supports IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patch types.\n\n + Download the best ROM patcher for Android. It supports IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP and XDelta3 patch types.\n\n Apply patch diff --git a/app/src/test/java/org/emunix/unipatcher/patcher/IPSTest.java b/app/src/test/java/org/emunix/unipatcher/patcher/IPSTest.java index 6f3da76..fd8f64a 100644 --- a/app/src/test/java/org/emunix/unipatcher/patcher/IPSTest.java +++ b/app/src/test/java/org/emunix/unipatcher/patcher/IPSTest.java @@ -74,6 +74,21 @@ public class IPSTest { assertTrue(ApplyPatch("/ips/truncate.ips", "/ips/truncate.bin", "/ips/truncate_modified.bin")); } + @Test + public void IPS32_MinPatch() throws Exception { + assertTrue(ApplyPatch("/ips/min_ips32.ips", "/ips/min_ips32.bin", "/ips/min_ips32_mod.bin")); + } + + @Test + public void IPS32_RlePatch() throws Exception { + assertTrue(ApplyPatch("/ips/rle_ips32.ips", "/ips/rle_ips32.bin", "/ips/rle_ips32_mod.bin")); + } + + @Test + public void IPS32_ExtendPatch() throws Exception { + assertTrue(ApplyPatch("/ips/extend_ips32.ips", "/ips/extend_ips32.bin", "/ips/extend_ips32_mod.bin")); + } + private boolean ApplyPatch(String patchName, String origName, String modifiedName) throws Exception { File patch = new File(this.getClass().getResource(patchName).getPath()); File in = new File(getClass().getResource(origName).getPath()); diff --git a/app/src/test/resources/ips/extend_ips32.bin b/app/src/test/resources/ips/extend_ips32.bin new file mode 100644 index 0000000..68da3dd --- /dev/null +++ b/app/src/test/resources/ips/extend_ips32.bin @@ -0,0 +1 @@ +7I57P'9R0H #ur4 rCYrWrW9E4u4 X#X #G#u# W#u 4u#rW CG#u 0x#P4G##r4 W 2G`tC TTeWFTFThFTeHFTteAgHTeAhteAetFTWHtEcTyeEFWFThvTe \ No newline at end of file diff --git a/app/src/test/resources/ips/extend_ips32.ips b/app/src/test/resources/ips/extend_ips32.ips new file mode 100644 index 0000000..1a5dcca Binary files /dev/null and b/app/src/test/resources/ips/extend_ips32.ips differ diff --git a/app/src/test/resources/ips/extend_ips32_mod.bin b/app/src/test/resources/ips/extend_ips32_mod.bin new file mode 100644 index 0000000..87f7dcc --- /dev/null +++ b/app/src/test/resources/ips/extend_ips32_mod.bin @@ -0,0 +1 @@ +7Ie57P'9R0 #ur4 r222#rW9Eu 4u#rW C#B#u #C$2BP4G##r4 W 2G`tC TTeWFTFThFTeHFTteAgHTe#B4eAetFTWHtEcTyeEFWFThvTETeFCeAte$t25vF14eFCF5TvcQCVThFTeHFTeeGhCT5v5WFTeI \ No newline at end of file diff --git a/app/src/test/resources/ips/min_ips32.bin b/app/src/test/resources/ips/min_ips32.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/app/src/test/resources/ips/min_ips32.bin differ diff --git a/app/src/test/resources/ips/min_ips32.ips b/app/src/test/resources/ips/min_ips32.ips new file mode 100644 index 0000000..624394a Binary files /dev/null and b/app/src/test/resources/ips/min_ips32.ips differ diff --git a/app/src/test/resources/ips/min_ips32_mod.bin b/app/src/test/resources/ips/min_ips32_mod.bin new file mode 100644 index 0000000..ce542ef --- /dev/null +++ b/app/src/test/resources/ips/min_ips32_mod.bin @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/src/test/resources/ips/rle_ips32.bin b/app/src/test/resources/ips/rle_ips32.bin new file mode 100644 index 0000000..4071e68 --- /dev/null +++ b/app/src/test/resources/ips/rle_ips32.bin @@ -0,0 +1 @@ +!7I#d@#Y0G 6Y7)P#xPE ' W#W #u#P# b0 #P'0r0`#u \ No newline at end of file diff --git a/app/src/test/resources/ips/rle_ips32.ips b/app/src/test/resources/ips/rle_ips32.ips new file mode 100644 index 0000000..d96ff82 Binary files /dev/null and b/app/src/test/resources/ips/rle_ips32.ips differ diff --git a/app/src/test/resources/ips/rle_ips32_mod.bin b/app/src/test/resources/ips/rle_ips32_mod.bin new file mode 100644 index 0000000..6392fdf --- /dev/null +++ b/app/src/test/resources/ips/rle_ips32_mod.bin @@ -0,0 +1 @@ +!7I#d@#Y0G 6Y7)P#xPE '#u \ No newline at end of file diff --git a/google-play/en/google-play.txt b/google-play/en/google-play.txt index aea91b4..e6e4648 100644 --- a/google-play/en/google-play.txt +++ b/google-play/en/google-play.txt @@ -8,6 +8,7 @@ Utility to apply patches to game rom. UniPatcher supports the most popular formats patches used in Nintendo, Super Nintendo, Sega MegaDrive / Sega Genesis, Gameboy, Game Boy Advance, Sony PlayStation and other games: • IPS +• IPS32 • UPS • BPS • APS (GBA) diff --git a/google-play/it/google-play.txt b/google-play/it/google-play.txt index fd57228..ca5b773 100644 --- a/google-play/it/google-play.txt +++ b/google-play/it/google-play.txt @@ -8,6 +8,7 @@ Utilità per applicare le patch alle ROM dei giochi. UniPatcher supporta i più popolari formati di patch usati da Nintendo, Super Nintendo, Sega Mega Drive / Sega Genesis, Gameboy, Game Boy Advance, Sony PlayStation e altri giochi: • IPS +• IPS32 • UPS • BPS • APS (GBA) diff --git a/google-play/pl/google-play.txt b/google-play/pl/google-play.txt index 326567e..ddec3f9 100644 --- a/google-play/pl/google-play.txt +++ b/google-play/pl/google-play.txt @@ -8,6 +8,7 @@ Narzędzie do aplikowania łatek do ROM-ów UniPatcher wspiera najbardziej popularne łatki używane w Nintendo, Super Nintendo, Sega MegaDrive / Sega Genesis, Gameboy, Game Boy Advance, Sony PlayStation i innych grach: • IPS +• IPS32 • UPS • BPS • APS (GBA) diff --git a/google-play/ru/google-play.txt b/google-play/ru/google-play.txt index eaefcd5..04e6789 100644 --- a/google-play/ru/google-play.txt +++ b/google-play/ru/google-play.txt @@ -8,6 +8,7 @@ Unipatcher поддерживает самые популярные форматы патчей используемые в играх Nintendo, Sega MegaDrive, Gameboy, Sony PlayStation и многих других: • IPS +• IPS32 • UPS • BPS • APS (GBA)