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)