From 22543f0710688b1d83dd21d41cd72db7c19cebd6 Mon Sep 17 00:00:00 2001
From: Boris Timofeev <mashin87@gmail.com>
Date: Mon, 23 Jan 2017 15:41:04 +0300
Subject: [PATCH] Support IPS32 patches

---
 README.md                                     |   2 +-
 .../org/emunix/unipatcher/patcher/IPS.java    | 143 +++++++++++++++++-
 app/src/main/res/raw-it/about.md              |   2 +-
 app/src/main/res/raw-it/faq.md                |   2 +-
 app/src/main/res/raw-pl/about.md              |   2 +-
 app/src/main/res/raw-pl/faq.md                |   2 +-
 app/src/main/res/raw-ru/about.md              |   2 +-
 app/src/main/res/raw-ru/faq.md                |   2 +-
 app/src/main/res/raw/about.md                 |   2 +-
 app/src/main/res/raw/faq.md                   |   2 +-
 app/src/main/res/values-it/strings.xml        |   2 +-
 app/src/main/res/values-pl/strings.xml        |   2 +-
 app/src/main/res/values-ru/strings.xml        |   2 +-
 app/src/main/res/values/strings.xml           |   2 +-
 .../emunix/unipatcher/patcher/IPSTest.java    |  15 ++
 app/src/test/resources/ips/extend_ips32.bin   |   1 +
 app/src/test/resources/ips/extend_ips32.ips   | Bin 0 -> 226 bytes
 .../test/resources/ips/extend_ips32_mod.bin   |   1 +
 app/src/test/resources/ips/min_ips32.bin      | Bin 0 -> 1 bytes
 app/src/test/resources/ips/min_ips32.ips      | Bin 0 -> 16 bytes
 app/src/test/resources/ips/min_ips32_mod.bin  |   1 +
 app/src/test/resources/ips/rle_ips32.bin      |   1 +
 app/src/test/resources/ips/rle_ips32.ips      | Bin 0 -> 18 bytes
 app/src/test/resources/ips/rle_ips32_mod.bin  |   1 +
 google-play/en/google-play.txt                |   1 +
 google-play/it/google-play.txt                |   1 +
 google-play/pl/google-play.txt                |   1 +
 google-play/ru/google-play.txt                |   1 +
 28 files changed, 173 insertions(+), 20 deletions(-)
 create mode 100644 app/src/test/resources/ips/extend_ips32.bin
 create mode 100644 app/src/test/resources/ips/extend_ips32.ips
 create mode 100644 app/src/test/resources/ips/extend_ips32_mod.bin
 create mode 100644 app/src/test/resources/ips/min_ips32.bin
 create mode 100644 app/src/test/resources/ips/min_ips32.ips
 create mode 100644 app/src/test/resources/ips/min_ips32_mod.bin
 create mode 100644 app/src/test/resources/ips/rle_ips32.bin
 create mode 100644 app/src/test/resources/ips/rle_ips32.ips
 create mode 100644 app/src/test/resources/ips/rle_ips32_mod.bin

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 @@
     <string name="send_feedback_error_no_email_apps">Non ci sono client email installati</string>
 
     <string name="share_dialog_title">Condividi UniPatcher</string>
-    <string name="share_text">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
+    <string name="share_text">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
 </string>
 
     <!-- Navigation list -->
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 @@
     <string name="send_feedback_error_no_email_apps">Tu nie ma żadnych klientów E-Mail zainstalowanych</string>
 
     <string name="share_dialog_title">Udostępnij UniPatcher-a swoim znajomym</string>
-    <string name="share_text">Pobierz najlepszy program do łatkowania ROM-ów. Wspiera typy łatek: IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP i XDelta3.\n\n</string>
+    <string name="share_text">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</string>
 
     <!-- Navigation list -->
     <string name="nav_apply_patch">Zastosuj łatkę</string>
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 @@
     <string name="send_feedback_error_no_email_apps">Не установлен email клиент</string>
 
     <string name="share_dialog_title">Рассказать о UniPatcher</string>
-    <string name="share_text">Скачай лучший ROM патчер для Android. Поддерживает патчи в форматах IPS, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3.\\n\\n
+    <string name="share_text">Скачай лучший ROM патчер для Android. Поддерживает патчи в форматах IPS, IPS32, UPS, BPS, APS (GBA), APS (N64), PPF, DPS, EBP и XDelta3.\\n\\n
 </string>
 
     <!-- Navigation list -->
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 @@
     <string name="send_feedback_error_no_email_apps">There are no email clients installed</string>
 
     <string name="share_dialog_title">Share UniPatcher</string>
-    <string name="share_text">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</string>
+    <string name="share_text">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</string>
 
     <!-- Navigation list -->
     <string name="nav_apply_patch">Apply patch</string>
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 @@
+7I�5�7P�'9R0H��	#u��r4�	rCYr�W�rW9E�4u�4	X#�X	#G�#u�#	W#�u	4u�#�rW �C�G#u	�0�x#�P�4�G#��#�r4	W	2G`�t��C	TTeWFT�FThFT�eHFTteAgHTeAhteAet�FTWHtEcT�yeEFWFThv�Te
\ 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 0000000000000000000000000000000000000000..1a5dccae6bc85173b1b2088f97bc901a45b7745f
GIT binary patch
literal 226
zcmeYa2sSoiU|?WkU`z#4ybO&0fs`}@yO9V8Dg!whKr8_g^<!XCb^_AD46Mq|Dn=mY
zL<VMMClerJ9Rs5)kXp~s6O!uYoa#8EBvn{tMv0M_X<56Qp$Sk-tliC2IHas4InX&Q
nB*QHv)dPtCQw@BZk}B+;;T+OpD%MhFDi#hj+_T-))!z*O;J9m2

literal 0
HcmV?d00001

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 @@
+7Ie5�7P�'9R0���	#u��r4�	r222#�rW9E�������������������������u	4u�#�rW �C�#B#u	#C$2B�P�4�G#��#�r4	W	2G`�t��C	TTeWFT�FThFT�eHFTteAgHTe#B4eAet�FTWHtEcT�yeEFWFThv�TETeFCeA�te$�t25v�F14eFC�F5Tv�cQCVThFTeHFTe����������������������������������������������������������������������������eGhCT�5�v5WFTeI�
\ 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 0000000000000000000000000000000000000000..f76dd238ade08917e6712764a16a22005a50573d
GIT binary patch
literal 1
IcmZPo000310RR91

literal 0
HcmV?d00001

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 0000000000000000000000000000000000000000..624394a352ab634a90dead04f646036f295349fb
GIT binary patch
literal 16
UcmeYa2sSoi00GATuCD%W02+}4aR2}S

literal 0
HcmV?d00001

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�@�#Y�0G	�6Y�7�)�P�#xP�E	'�	W#��W	#u�#P�#	�b0��	#P�'0�r0�`�#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 0000000000000000000000000000000000000000..d96ff821b0fa9190cc70389d07ff9011a4c18cba
GIT binary patch
literal 18
XcmeYa2sSoiU|>)NVuk;%uKsQSA58<Z

literal 0
HcmV?d00001

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�@�#Y�0G	�6Y�7�)�P�#xP�E	'���������������������������������#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.
 
 <b>UniPatcher supports the most popular formats patches</b> used in Nintendo, Super Nintendo, Sega MegaDrive / Sega Genesis, Gameboy, Game Boy Advance, Sony PlayStation and other games:
 &bull; IPS
+&bull; IPS32
 &bull; UPS
 &bull; BPS
 &bull; 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.
 
 <b>UniPatcher supporta i più popolari formati di patch</b> usati da Nintendo, Super Nintendo, Sega Mega Drive / Sega Genesis, Gameboy, Game Boy Advance, Sony PlayStation e altri giochi:
 &bull; IPS
+&bull; IPS32
 &bull; UPS
 &bull; BPS
 &bull; 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
 
 <b>UniPatcher wspiera najbardziej popularne łatki</b> używane w Nintendo, Super Nintendo, Sega MegaDrive / Sega Genesis, Gameboy, Game Boy Advance, Sony PlayStation i innych grach:
 &bull; IPS
+&bull; IPS32
 &bull; UPS
 &bull; BPS
 &bull; 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 @@
 
 <b>Unipatcher поддерживает самые популярные форматы патчей</b> используемые в играх Nintendo, Sega MegaDrive, Gameboy, Sony PlayStation и многих других:
 &bull; IPS
+&bull; IPS32
 &bull; UPS
 &bull; BPS
 &bull; APS (GBA)