diff --git a/LICENSE b/LICENSE index 261eeb9..29f81d8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,201 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 7b761ca..1d6134a 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,77 @@ -# NativeModMenu - -### High-Performance In-Memory Dex Loader for Android - -`NativeModMenu` is a sophisticated reimplementation of the LGL Android Mod Menu. It leverages `InMemoryDexClassLoader` to load the Java UI layer directly from system memory, eliminating the need for physical `.dex` files on the device storage. - ---- - -## Technical Overview - -This implementation focuses on stealth and efficiency by embedding the `FloatingModMenu.dex` as a HEX-encoded string within the native binary. At runtime, the JNI layer performs a dynamic bootstrap to initialize the menu without leaving any traces in the application's assets or data folders. - -### Key Architectural Differences - -* **Zero Disk Footprint:** No external dex file is shipped; the menu exists only in memory. -* **Volatile Loading:** Utilizes `dalvik.system.InMemoryDexClassLoader` for runtime execution. -* **Native-Led Initialization:** The entire menu lifecycle is managed via JNI native bindings. -* **Reduced Attack Surface:** Eliminates file-based detection vectors by avoiding asset extraction. -* **Native Compatibility:** Fully compatible with existing LGL Java menu logic. - ---- - -## Core Logic Flow - -1. **Data Embedding:** The `FloatingModMenu.dex` is converted to a HEX string and compiled into the C++ source. -2. **Buffer Reconstruction:** At runtime, the HEX string is decoded into a `ByteBuffer`. -3. **Class Loading:** The `InMemoryDexClassLoader` interprets the buffer and loads the `uk.lgl.modmenu.FloatingModMenu` class. -4. **JNI Registration:** Native functions are dynamically bound to the Java class methods. -5. **Execution:** The `binJava()` entry point triggers `FloatingModMenu.antik(Context)` to render the UI. - ---- - -## JNI Native Interface - -The following methods are registered dynamically to bridge the Native and Java layers: - -| Method | Functionality | -| --- | --- | -| `Icon()` | Returns the primary menu icon | -| `IconWebViewData()` | Manages WebView icon resources | -| `getFeatureList()` | Retrieves the feature configuration array | -| `settingsList()` | Retrieves the menu settings configuration | -| `Changes(...)` | Main event handler for feature toggles | -| `setTitleText(...)` | Customizes the UI title appearance | -| `setHeadingText(...)` | Customizes the UI heading appearance | - ---- - -## Implementation Details - -### Requirements - -* **Android Version:** 8.0 (API 26) or higher -* **Architecture:** ARMv7, ARM64-v8a -* **Environment:** Native JNI-based injection - -### Entry Point - -```cpp -// Executed post JNI_OnLoad -void binJava(); - -``` - -The `binJava` function is responsible for retrieving the `Application` context via `ActivityThread` and initiating the memory-loading sequence. - ---- - -## Legal Notice - -This project is developed strictly for **educational and research purposes**. Modifying the runtime behavior of third-party applications may violate their Terms of Service. The developers assume no liability for misuse. - -## Acknowledgments - -* **Original Architecture:** LGL Android Mod Menu -* **Lead Developer:** AntikMods -* **Memory Loading Logic:** NepMods +# NativeModMenu + +### High-Performance In-Memory Dex Loader for Android + +`NativeModMenu` is a sophisticated reimplementation of the LGL Android Mod Menu. It leverages `InMemoryDexClassLoader` to load the Java UI layer directly from system memory, eliminating the need for physical `.dex` files on the device storage. + +--- + +## Technical Overview + +This implementation focuses on stealth and efficiency by embedding the `FloatingModMenu.dex` as a HEX-encoded string within the native binary. At runtime, the JNI layer performs a dynamic bootstrap to initialize the menu without leaving any traces in the application's assets or data folders. + +### Key Architectural Differences + +* **Zero Disk Footprint:** No external dex file is shipped; the menu exists only in memory. +* **Volatile Loading:** Utilizes `dalvik.system.InMemoryDexClassLoader` for runtime execution. +* **Native-Led Initialization:** The entire menu lifecycle is managed via JNI native bindings. +* **Reduced Attack Surface:** Eliminates file-based detection vectors by avoiding asset extraction. +* **Native Compatibility:** Fully compatible with existing LGL Java menu logic. + +--- + +## Core Logic Flow + +1. **Data Embedding:** The `FloatingModMenu.dex` is converted to a HEX string and compiled into the C++ source. +2. **Buffer Reconstruction:** At runtime, the HEX string is decoded into a `ByteBuffer`. +3. **Class Loading:** The `InMemoryDexClassLoader` interprets the buffer and loads the `uk.lgl.modmenu.FloatingModMenu` class. +4. **JNI Registration:** Native functions are dynamically bound to the Java class methods. +5. **Execution:** The `binJava()` entry point triggers `FloatingModMenu.antik(Context)` to render the UI. + +--- + +## JNI Native Interface + +The following methods are registered dynamically to bridge the Native and Java layers: + +| Method | Functionality | +| --- | --- | +| `Icon()` | Returns the primary menu icon | +| `IconWebViewData()` | Manages WebView icon resources | +| `getFeatureList()` | Retrieves the feature configuration array | +| `settingsList()` | Retrieves the menu settings configuration | +| `Changes(...)` | Main event handler for feature toggles | +| `setTitleText(...)` | Customizes the UI title appearance | +| `setHeadingText(...)` | Customizes the UI heading appearance | + +--- + +## Implementation Details + +### Requirements + +* **Android Version:** 8.0 (API 26) or higher +* **Architecture:** ARMv7, ARM64-v8a +* **Environment:** Native JNI-based injection + +### Entry Point + +```cpp +// Executed post JNI_OnLoad +void binJava(); + +``` + +The `binJava` function is responsible for retrieving the `Application` context via `ActivityThread` and initiating the memory-loading sequence. + +--- + +## Legal Notice + +This project is developed strictly for **educational and research purposes**. Modifying the runtime behavior of third-party applications may violate their Terms of Service. The developers assume no liability for misuse. + +## Acknowledgments + +* **Original Architecture:** LGL Android Mod Menu +* **Lead Developer:** AntikMods +* **Memory Loading Logic:** NepMods diff --git a/app/build.gradle b/app/build.gradle index f53a8dc..e89d584 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,90 +1,91 @@ -import com.android.build.gradle.tasks.ExternalNativeBuildTask -import java.io.FileInputStream - -plugins { - alias(libs.plugins.android.application) -} - -class JavaDex { - public static String xxd_p(String filePath) { - StringBuilder hexString = new StringBuilder() - File file = new File(filePath) - try (FileInputStream fis = new FileInputStream(file)) { - byte[] data = fis.readAllBytes() - for (byte b : data) { - hexString.append(String.format("%02X", b)) - } - } - return hexString.toString() - } -} - -android { - namespace 'uk.lgl' - compileSdk 36 - - defaultConfig { - applicationId "uk.lgl" - minSdk 28 - targetSdk 36 - versionCode 1 - versionName "1.0" - - ndk { - abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' - } - - multiDexEnabled false - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - externalNativeBuild { - ndkBuild { - path file('src/main/jni/Android.mk') - } - } - - android.applicationVariants.all { variant -> - def variantName = variant.name.capitalize() - def taskName = "Dex2CppAnd8Up${variantName}" - - def customTask = tasks.register(taskName) { - outputs.upToDateWhen { false } - - def mergeDexTask = tasks.findByName("mergeDex${variantName}") - if (mergeDexTask) { - dependsOn mergeDexTask - } - - doLast { - def dexDir = file("${project.buildDir}/intermediates/dex/${variant.name}/mergeDex${variantName}") - def dexFiles = fileTree(dir: dexDir, include: "**/classes.dex") - - if (dexFiles.isEmpty()) { - throw new GradleException("classes.dex not found for ${variant.name} in ${dexDir}") - } - - def dexFile = dexFiles.first() - String hexString = JavaDex.xxd_p(dexFile.absolutePath) - def headerFile = file("${project.projectDir}/src/main/jni/JavaGPP/Interface/OreoOrMore.h") - - headerFile.parentFile.mkdirs() - headerFile.write("#define OreoOrMore \"${hexString}\"\n") - println ">>> Success: Generated header for ${variantName}" - } - } - - tasks.configureEach { task -> - if (task.name.startsWith("buildNdkBuild${variantName}") || - task.name.startsWith("externalNativeBuild${variantName}")) { - task.dependsOn customTask - } - } - } +import com.android.build.gradle.tasks.ExternalNativeBuildTask +import java.io.FileInputStream + +plugins { + alias(libs.plugins.android.application) +} + +class JavaDex { + public static String xxd_p(String filePath) { + StringBuilder hexString = new StringBuilder() + File file = new File(filePath) + try (FileInputStream fis = new FileInputStream(file)) { + byte[] data = fis.readAllBytes() + for (byte b : data) { + hexString.append(String.format("%02X", b)) + } + } + return hexString.toString() + } +} + +android { + namespace 'com.android.support' + compileSdk 36 + + defaultConfig { + applicationId "com.android.support" + minSdk 28 + targetSdk 36 + versionCode 1 + versionName "1.0" + + ndk { + abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' + } + + multiDexEnabled false + } + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + externalNativeBuild { + ndkBuild { + path file('src/main/jni/Android.mk') + } + ndkVersion = '28.2.13676358' + } + + android.applicationVariants.all { variant -> + def variantName = variant.name.capitalize() + def taskName = "Dex2CppAnd8Up${variantName}" + + def customTask = tasks.register(taskName) { + outputs.upToDateWhen { false } + + def mergeDexTask = tasks.findByName("mergeDex${variantName}") + if (mergeDexTask) { + dependsOn mergeDexTask + } + + doLast { + def dexDir = file("${project.buildDir}/intermediates/dex/${variant.name}/mergeDex${variantName}") + def dexFiles = fileTree(dir: dexDir, include: "**/classes.dex") + + if (dexFiles.isEmpty()) { + throw new GradleException("classes.dex not found for ${variant.name} in ${dexDir}") + } + + def dexFile = dexFiles.first() + String hexString = JavaDex.xxd_p(dexFile.absolutePath) + def headerFile = file("${project.projectDir}/src/main/jni/Includes/Dex.h") + + headerFile.parentFile.mkdirs() + headerFile.write("#define hexdex \"${hexString}\"\n") + println ">>> Success: Generated header for ${variantName}" + } + } + + tasks.configureEach { task -> + if (task.name.startsWith("buildNdkBuild${variantName}") || + task.name.startsWith("externalNativeBuild${variantName}")) { + task.dependsOn customTask + } + } + } } \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..64b4a05 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,21 +1,21 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. #-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d033f3..e524f52 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,14 +1,16 @@ + package="com.android.support"> - @@ -16,4 +18,4 @@ - \ No newline at end of file + diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..cbc1231 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/android/support/MainActivity.java b/app/src/main/java/com/android/support/MainActivity.java new file mode 100644 index 0000000..0a67956 --- /dev/null +++ b/app/src/main/java/com/android/support/MainActivity.java @@ -0,0 +1,18 @@ +package com.android.support; + +import android.app.Activity; +import android.os.Bundle; + +public class MainActivity extends Activity { + + static { + System.loadLibrary("LGL"); + } + + //To call onCreate, please refer to README.md + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Menu.CreateMenu(this); + } +} diff --git a/app/src/main/java/com/android/support/Menu.java b/app/src/main/java/com/android/support/Menu.java new file mode 100644 index 0000000..eb63b37 --- /dev/null +++ b/app/src/main/java/com/android/support/Menu.java @@ -0,0 +1,1086 @@ +//Please don't replace listeners with lambda! + +package com.android.support; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; +import android.net.Uri; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.text.Html; +import android.text.InputFilter; +import android.text.InputType; +import android.text.TextUtils; +import android.text.method.DigitsKeyListener; +import android.util.Base64; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.webkit.WebView; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RelativeLayout; +import android.widget.ScrollView; +import android.widget.SeekBar; +import android.widget.Spinner; +import android.widget.Switch; +import android.widget.TextView; +import android.widget.Toast; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.widget.RelativeLayout.ALIGN_PARENT_LEFT; +import static android.widget.RelativeLayout.ALIGN_PARENT_RIGHT; + +public class Menu { + //********** Here you can easly change the menu appearance **********// + + //region Variable + public static final String TAG = "Mod_Menu"; //Tag for logcat + + int TEXT_COLOR = Color.parseColor("#82CAFD"); + int TEXT_COLOR_2 = Color.parseColor("#FFFFFF"); + int BTN_COLOR = Color.parseColor("#1C262D"); + int MENU_BG_COLOR = Color.parseColor("#EE1C2A35"); //#AARRGGBB + int MENU_FEATURE_BG_COLOR = Color.parseColor("#DD141C22"); //#AARRGGBB + int MENU_WIDTH = 290; + int MENU_HEIGHT = 210; + int POS_X = 0; + int POS_Y = 100; + + float MENU_CORNER = 4f; + int ICON_SIZE = 45; //Change both width and height of image + float ICON_ALPHA = 0.7f; //Transparent + int ToggleON = Color.GREEN; + int ToggleOFF = Color.RED; + int BtnON = Color.parseColor("#1b5e20"); + int BtnOFF = Color.parseColor("#7f0000"); + int CategoryBG = Color.parseColor("#2F3D4C"); + int SeekBarColor = Color.parseColor("#80CBC4"); + int SeekBarProgressColor = Color.parseColor("#80CBC4"); + int CheckBoxColor = Color.parseColor("#80CBC4"); + int RadioColor = Color.parseColor("#FFFFFF"); + String NumberTxtColor = "#41c300"; + //********************************************************************// + + RelativeLayout mCollapsed, mRootContainer; + LinearLayout mExpanded, mods, mSettings, mCollapse; + LinearLayout.LayoutParams scrlLLExpanded, scrlLL; + WindowManager mWindowManager; + WindowManager.LayoutParams vmParams; + ImageView startimage; + FrameLayout rootFrame; + ScrollView scrollView; + boolean stopChecking, overlayRequired; + Context getContext; + + //initialize methods from the native library + native void Init(Context context, TextView title, TextView subTitle); + + native String Icon(); + + native String IconWebViewData(); + + native String[] GetFeatureList(); + + native String[] SettingsList(); + + public static native void Changes(Context con, int fNum, String fName, int i, boolean bool, String str); + + + //Here we write the code for our Menu + // Reference: https://www.androidhive.info/2016/11/android-floating-widget-like-facebook-chat-head/ + public Menu(Context context) { + + getContext = context; + Preferences.context = context; + rootFrame = new FrameLayout(context); // Global markup + rootFrame.setOnTouchListener(onTouchListener()); + mRootContainer = new RelativeLayout(context); // Markup on which two markups of the icon and the menu itself will be placed + mCollapsed = new RelativeLayout(context); // Markup of the icon (when the menu is minimized) + mCollapsed.setVisibility(View.VISIBLE); + mCollapsed.setAlpha(ICON_ALPHA); + + //********** The box of the mod menu ********** + mExpanded = new LinearLayout(context); // Menu markup (when the menu is expanded) + mExpanded.setVisibility(View.GONE); + mExpanded.setBackgroundColor(MENU_BG_COLOR); + mExpanded.setOrientation(LinearLayout.VERTICAL); + // mExpanded.setPadding(1, 1, 1, 1); //So borders would be visible + mExpanded.setLayoutParams(new LinearLayout.LayoutParams(dp(MENU_WIDTH), WRAP_CONTENT)); + GradientDrawable gdMenuBody = new GradientDrawable(); + gdMenuBody.setCornerRadius(MENU_CORNER); //Set corner + gdMenuBody.setColor(MENU_BG_COLOR); //Set background color + gdMenuBody.setStroke(1, Color.parseColor("#32cb00")); //Set border + //mExpanded.setBackground(gdMenuBody); //Apply GradientDrawable to it + + //********** The icon to open mod menu ********** + startimage = new ImageView(context); + startimage.setLayoutParams(new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + int applyDimension = (int) TypedValue.applyDimension(1, ICON_SIZE, context.getResources().getDisplayMetrics()); //Icon size + startimage.getLayoutParams().height = applyDimension; + startimage.getLayoutParams().width = applyDimension; + //startimage.requestLayout(); + startimage.setScaleType(ImageView.ScaleType.FIT_XY); + byte[] decode = Base64.decode(Icon(), 0); + startimage.setImageBitmap(BitmapFactory.decodeByteArray(decode, 0, decode.length)); + ((ViewGroup.MarginLayoutParams) startimage.getLayoutParams()).topMargin = convertDipToPixels(10); + //Initialize event handlers for buttons, etc. + startimage.setOnTouchListener(onTouchListener()); + startimage.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + mCollapsed.setVisibility(View.GONE); + mExpanded.setVisibility(View.VISIBLE); + } + }); + + //********** The icon in Webview to open mod menu ********** + WebView wView = new WebView(context); //Icon size width=\"50\" height=\"50\" + wView.setLayoutParams(new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + int applyDimension2 = (int) TypedValue.applyDimension(1, ICON_SIZE, context.getResources().getDisplayMetrics()); //Icon size + wView.getLayoutParams().height = applyDimension2; + wView.getLayoutParams().width = applyDimension2; + wView.loadData("" + + "" + + "" + + "" + + "" + + "", "text/html", "utf-8"); + wView.setBackgroundColor(0x00000000); //Transparent + wView.setAlpha(ICON_ALPHA); + wView.setOnTouchListener(onTouchListener()); + + //********** Settings icon ********** + TextView settings = new TextView(context); //Android 5 can't show ⚙, instead show other icon instead + settings.setText(Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M ? "⚙" : "\uD83D\uDD27"); + settings.setTextColor(TEXT_COLOR); + settings.setTypeface(Typeface.DEFAULT_BOLD); + settings.setTextSize(20.0f); + RelativeLayout.LayoutParams rlsettings = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + rlsettings.addRule(ALIGN_PARENT_RIGHT); + settings.setLayoutParams(rlsettings); + settings.setOnClickListener(new View.OnClickListener() { + boolean settingsOpen; + + @Override + public void onClick(View v) { + try { + settingsOpen = !settingsOpen; + if (settingsOpen) { + scrollView.removeView(mods); + scrollView.addView(mSettings); + scrollView.scrollTo(0, 0); + } else { + scrollView.removeView(mSettings); + scrollView.addView(mods); + } + } catch (IllegalStateException e) { + } + } + }); + + //********** Settings ********** + mSettings = new LinearLayout(context); + mSettings.setOrientation(LinearLayout.VERTICAL); + featureList(SettingsList(), mSettings); + + //********** Title ********** + RelativeLayout titleText = new RelativeLayout(context); + titleText.setPadding(10, 5, 10, 5); + titleText.setVerticalGravity(16); + + TextView title = new TextView(context); + title.setTextColor(TEXT_COLOR); + title.setTextSize(18.0f); + title.setGravity(Gravity.CENTER); + RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + rl.addRule(RelativeLayout.CENTER_HORIZONTAL); + title.setLayoutParams(rl); + + //********** Sub title ********** + TextView subTitle = new TextView(context); + subTitle.setEllipsize(TextUtils.TruncateAt.MARQUEE); + subTitle.setMarqueeRepeatLimit(-1); + subTitle.setSingleLine(true); + subTitle.setSelected(true); + subTitle.setTextColor(TEXT_COLOR); + subTitle.setTextSize(10.0f); + subTitle.setGravity(Gravity.CENTER); + subTitle.setPadding(0, 0, 0, 5); + + //********** Mod menu feature list ********** + scrollView = new ScrollView(context); + //Auto size. To set size manually, change the width and height example 500, 500 + scrlLL = new LinearLayout.LayoutParams(MATCH_PARENT, dp(MENU_HEIGHT)); + scrlLLExpanded = new LinearLayout.LayoutParams(mExpanded.getLayoutParams()); + scrlLLExpanded.weight = 1.0f; + scrollView.setLayoutParams(Preferences.isExpanded ? scrlLLExpanded : scrlLL); + scrollView.setBackgroundColor(MENU_FEATURE_BG_COLOR); + mods = new LinearLayout(context); + mods.setOrientation(LinearLayout.VERTICAL); + + //********** RelativeLayout for buttons ********** + RelativeLayout relativeLayout = new RelativeLayout(context); + relativeLayout.setPadding(10, 3, 10, 3); + relativeLayout.setVerticalGravity(Gravity.CENTER); + + //********** Hide/Kill button ********** + RelativeLayout.LayoutParams lParamsHideBtn = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + lParamsHideBtn.addRule(ALIGN_PARENT_LEFT); + + Button hideBtn = new Button(context); + hideBtn.setLayoutParams(lParamsHideBtn); + hideBtn.setBackgroundColor(Color.TRANSPARENT); + hideBtn.setText("HIDE/KILL (Hold)"); + hideBtn.setTextColor(TEXT_COLOR); + hideBtn.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + mCollapsed.setVisibility(View.VISIBLE); + mCollapsed.setAlpha(0); + mExpanded.setVisibility(View.GONE); + Toast.makeText(view.getContext(), "Icon hidden. Remember the hidden icon position", Toast.LENGTH_LONG).show(); + } + }); + hideBtn.setOnLongClickListener(new View.OnLongClickListener() { + public boolean onLongClick(View view) { + Toast.makeText(view.getContext(), "Menu killed", Toast.LENGTH_LONG).show(); + rootFrame.removeView(mRootContainer); + mWindowManager.removeView(rootFrame); + return false; + } + }); + + //********** Close button ********** + RelativeLayout.LayoutParams lParamsCloseBtn = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + lParamsCloseBtn.addRule(ALIGN_PARENT_RIGHT); + + Button closeBtn = new Button(context); + closeBtn.setLayoutParams(lParamsCloseBtn); + closeBtn.setBackgroundColor(Color.TRANSPARENT); + closeBtn.setText("MINIMIZE"); + closeBtn.setTextColor(TEXT_COLOR); + closeBtn.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + mCollapsed.setVisibility(View.VISIBLE); + mCollapsed.setAlpha(ICON_ALPHA); + mExpanded.setVisibility(View.GONE); + } + }); + + //********** Adding view components ********** + mRootContainer.addView(mCollapsed); + mRootContainer.addView(mExpanded); + if (IconWebViewData() != null) { + mCollapsed.addView(wView); + } else { + mCollapsed.addView(startimage); + } + titleText.addView(title); + titleText.addView(settings); + mExpanded.addView(titleText); + mExpanded.addView(subTitle); + scrollView.addView(mods); + mExpanded.addView(scrollView); + relativeLayout.addView(hideBtn); + relativeLayout.addView(closeBtn); + mExpanded.addView(relativeLayout); + + Init(context, title, subTitle); + } + + + private static Menu menu; + + public static void CreateMenu(final Context context) { + if (!(context instanceof Activity)) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + Activity activity = getTopActivity(); + if (activity != null) { + activity.setTheme(android.R.style.Theme_Material); + menu = new Menu(activity); + menu.SetWindowManagerActivity(); + menu.ShowMenu(); + } + } + }); + } else { + ((Activity) context).setTheme(android.R.style.Theme_Material); + menu = new Menu((Activity) context); + menu.SetWindowManagerActivity(); + menu.ShowMenu(); + } + } + + private static Activity getTopActivity() { + try { + Class at = Class.forName("android.app.ActivityThread"); + Method current = at.getDeclaredMethod("currentActivityThread"); + current.setAccessible(true); + Object atObj = current.invoke(null); + + Field activities = at.getDeclaredField("mActivities"); + activities.setAccessible(true); + Map map = (Map) activities.get(atObj); + + for (Object record : map.values()) { + Class ar = record.getClass(); + Field paused = ar.getDeclaredField("paused"); + paused.setAccessible(true); + if (!paused.getBoolean(record)) { + Field activity = ar.getDeclaredField("activity"); + activity.setAccessible(true); + return (Activity) activity.get(record); + } + } + } catch (Throwable ignored) {} + return null; + } + + + public void ShowMenu() { + rootFrame.addView(mRootContainer); + + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + boolean viewLoaded = false; + + @Override + public void run() { + mods.removeAllViews(); + featureList(GetFeatureList(), mods); + + } + }, 500); + } + + + @SuppressLint("WrongConstant") + public void SetWindowManagerActivity() { + vmParams = new WindowManager.LayoutParams( + WindowManager.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.WRAP_CONTENT, + POS_X,//initialX + POS_Y,//initialy + WindowManager.LayoutParams.TYPE_APPLICATION, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN | + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, + PixelFormat.TRANSPARENT + ); + vmParams.gravity = 51; + vmParams.x = POS_X; + vmParams.y = POS_Y; + + mWindowManager = ((Activity) getContext).getWindowManager(); + mWindowManager.addView(rootFrame, vmParams); + } + + private View.OnTouchListener onTouchListener() { + return new View.OnTouchListener() { + final View collapsedView = mCollapsed; + final View expandedView = mExpanded; + private float initialTouchX, initialTouchY; + private int initialX, initialY; + + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + initialX = vmParams.x; + initialY = vmParams.y; + initialTouchX = motionEvent.getRawX(); + initialTouchY = motionEvent.getRawY(); + return true; + case MotionEvent.ACTION_UP: + int rawX = (int) (motionEvent.getRawX() - initialTouchX); + int rawY = (int) (motionEvent.getRawY() - initialTouchY); + mExpanded.setAlpha(1f); + mCollapsed.setAlpha(1f); + //The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little while clicking. + //So that is click event. + if (rawX < 10 && rawY < 10 && isViewCollapsed()) { + //When user clicks on the image view of the collapsed layout, + //visibility of the collapsed layout will be changed to "View.GONE" + //and expanded view will become visible. + try { + collapsedView.setVisibility(View.GONE); + expandedView.setVisibility(View.VISIBLE); + } catch (NullPointerException e) { + + } + } + return true; + case MotionEvent.ACTION_MOVE: + mExpanded.setAlpha(0.5f); + mCollapsed.setAlpha(0.5f); + //Calculate the X and Y coordinates of the view. + vmParams.x = initialX + ((int) (motionEvent.getRawX() - initialTouchX)); + vmParams.y = initialY + ((int) (motionEvent.getRawY() - initialTouchY)); + //Update the layout with new X & Y coordinate + mWindowManager.updateViewLayout(rootFrame, vmParams); + return true; + default: + return false; + } + } + }; + } + + private void featureList(String[] listFT, LinearLayout linearLayout) { + //Currently looks messy right now. Let me know if you have improvements + int featNum, subFeat = 0; + LinearLayout llBak = linearLayout; + + for (int i = 0; i < listFT.length; i++) { + boolean switchedOn = false; + //Log.i("featureList", listFT[i]); + String feature = listFT[i]; + if (feature.contains("_True")) { + switchedOn = true; + feature = feature.replaceFirst("_True", ""); + } + + linearLayout = llBak; + if (feature.contains("CollapseAdd_")) { + //if (collapse != null) + linearLayout = mCollapse; + feature = feature.replaceFirst("CollapseAdd_", ""); + } + String[] str = feature.split("_"); + + //Assign feature number + if (TextUtils.isDigitsOnly(str[0]) || str[0].matches("-[0-9]*")) { + featNum = Integer.parseInt(str[0]); + feature = feature.replaceFirst(str[0] + "_", ""); + subFeat++; + } else { + //Subtract feature number. We don't want to count ButtonLink, Category, RichTextView and RichWebView + featNum = i - subFeat; + } + String[] strSplit = feature.split("_"); + switch (strSplit[0]) { + case "Toggle": + Switch(linearLayout, featNum, strSplit[1], switchedOn); + break; + case "SeekBar": + SeekBar(linearLayout, featNum, strSplit[1], Integer.parseInt(strSplit[2]), Integer.parseInt(strSplit[3])); + break; + case "Button": + Button(linearLayout, featNum, strSplit[1]); + break; + case "ButtonOnOff": + ButtonOnOff(linearLayout, featNum, strSplit[1], switchedOn); + break; + case "Spinner": + TextView(linearLayout, strSplit[1]); + Spinner(linearLayout, featNum, strSplit[1], strSplit[2]); + break; + case "InputText": + InputText(linearLayout, featNum, strSplit[1]); + break; + case "InputValue": + if (strSplit.length == 3) + InputNum(linearLayout, featNum, strSplit[2], Integer.parseInt(strSplit[1])); + if (strSplit.length == 2) + InputNum(linearLayout, featNum, strSplit[1], 0); + break; + case "CheckBox": + CheckBox(linearLayout, featNum, strSplit[1], switchedOn); + break; + case "RadioButton": + RadioButton(linearLayout, featNum, strSplit[1], strSplit[2]); + break; + case "Collapse": + Collapse(linearLayout, strSplit[1], switchedOn); + subFeat++; + break; + case "ButtonLink": + subFeat++; + ButtonLink(linearLayout, strSplit[1], strSplit[2]); + break; + case "Category": + subFeat++; + Category(linearLayout, strSplit[1]); + break; + case "RichTextView": + subFeat++; + TextView(linearLayout, strSplit[1]); + break; + case "RichWebView": + subFeat++; + WebTextView(linearLayout, strSplit[1]); + break; + } + } + } + + private void Switch(LinearLayout linLayout, final int featNum, final String featName, boolean swiOn) { + final Switch switchR = new Switch(getContext); + ColorStateList buttonStates = new ColorStateList( + new int[][]{ + new int[]{-android.R.attr.state_enabled}, + new int[]{android.R.attr.state_checked}, + new int[]{} + }, + new int[]{ + Color.BLUE, + ToggleON, // ON + ToggleOFF // OFF + } + ); + //Set colors of the switch. Comment out if you don't like it + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + try { + switchR.getThumbDrawable().setTintList(buttonStates); + switchR.getTrackDrawable().setTintList(buttonStates); + } catch (NullPointerException ex) { + Log.d(TAG, String.valueOf(ex)); + } + } + switchR.setText(featName); + switchR.setTextColor(TEXT_COLOR_2); + switchR.setPadding(10, 5, 0, 5); + switchR.setChecked(Preferences.loadPrefBool(featName, featNum, swiOn)); + switchR.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + public void onCheckedChanged(CompoundButton compoundButton, boolean bool) { + Preferences.changeFeatureBool(featName, featNum, bool); + switch (featNum) { + case -1: //Save perferences + Preferences.with(switchR.getContext()).writeBoolean(-1, bool); + if (bool == false) + Preferences.with(switchR.getContext()).clear(); //Clear perferences if switched off + break; + case -3: + Preferences.isExpanded = bool; + scrollView.setLayoutParams(bool ? scrlLLExpanded : scrlLL); + break; + } + } + }); + + linLayout.addView(switchR); + } + + private void SeekBar(LinearLayout linLayout, final int featNum, final String featName, final int min, int max) { + int loadedProg = Preferences.loadPrefInt(featName, featNum); + LinearLayout linearLayout = new LinearLayout(getContext); + linearLayout.setPadding(10, 5, 0, 5); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setGravity(Gravity.CENTER); + + final TextView textView = new TextView(getContext); + textView.setText(Html.fromHtml(featName + ": " + ((loadedProg == 0) ? min : loadedProg))); + textView.setTextColor(TEXT_COLOR_2); + + SeekBar seekBar = new SeekBar(getContext); + seekBar.setPadding(25, 10, 35, 10); + seekBar.setMax(max); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + seekBar.setMin(min); //setMin for Oreo and above + seekBar.setProgress((loadedProg == 0) ? min : loadedProg); + seekBar.getThumb().setColorFilter(SeekBarColor, PorterDuff.Mode.SRC_ATOP); + seekBar.getProgressDrawable().setColorFilter(SeekBarProgressColor, PorterDuff.Mode.SRC_ATOP); + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + public void onStartTrackingTouch(SeekBar seekBar) { + } + + public void onStopTrackingTouch(SeekBar seekBar) { + } + + public void onProgressChanged(SeekBar seekBar, int i, boolean z) { + //if progress is greater than minimum, don't go below. Else, set progress + seekBar.setProgress(i < min ? min : i); + Preferences.changeFeatureInt(featName, featNum, i < min ? min : i); + textView.setText(Html.fromHtml(featName + ": " + (i < min ? min : i))); + } + }); + linearLayout.addView(textView); + linearLayout.addView(seekBar); + + linLayout.addView(linearLayout); + } + + private void Button(LinearLayout linLayout, final int featNum, final String featName) { + final Button button = new Button(getContext); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + layoutParams.setMargins(7, 5, 7, 5); + button.setLayoutParams(layoutParams); + button.setTextColor(TEXT_COLOR_2); + button.setAllCaps(false); //Disable caps to support html + button.setText(Html.fromHtml(featName)); + button.setBackgroundColor(BTN_COLOR); + button.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + switch (featNum) { + + case -6: + scrollView.removeView(mSettings); + scrollView.addView(mods); + break; + case -100: + stopChecking = true; + break; + } + Preferences.changeFeatureInt(featName, featNum, 0); + } + }); + + linLayout.addView(button); + } + + private void ButtonLink(LinearLayout linLayout, final String featName, final String url) { + final Button button = new Button(getContext); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + layoutParams.setMargins(7, 5, 7, 5); + button.setLayoutParams(layoutParams); + button.setAllCaps(false); //Disable caps to support html + button.setTextColor(TEXT_COLOR_2); + button.setText(Html.fromHtml(featName)); + button.setBackgroundColor(BTN_COLOR); + button.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setData(Uri.parse(url)); + getContext.startActivity(intent); + } + }); + linLayout.addView(button); + } + + private void ButtonOnOff(LinearLayout linLayout, final int featNum, String featName, boolean switchedOn) { + final Button button = new Button(getContext); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + layoutParams.setMargins(7, 5, 7, 5); + button.setLayoutParams(layoutParams); + button.setTextColor(TEXT_COLOR_2); + button.setAllCaps(false); //Disable caps to support html + + final String finalfeatName = featName.replace("OnOff_", ""); + boolean isOn = Preferences.loadPrefBool(featName, featNum, switchedOn); + if (isOn) { + button.setText(Html.fromHtml(finalfeatName + ": ON")); + button.setBackgroundColor(BtnON); + isOn = false; + } else { + button.setText(Html.fromHtml(finalfeatName + ": OFF")); + button.setBackgroundColor(BtnOFF); + isOn = true; + } + final boolean finalIsOn = isOn; + button.setOnClickListener(new View.OnClickListener() { + boolean isOn = finalIsOn; + + public void onClick(View v) { + Preferences.changeFeatureBool(finalfeatName, featNum, isOn); + //Log.d(TAG, finalfeatName + " " + featNum + " " + isActive2); + if (isOn) { + button.setText(Html.fromHtml(finalfeatName + ": ON")); + button.setBackgroundColor(BtnON); + isOn = false; + } else { + button.setText(Html.fromHtml(finalfeatName + ": OFF")); + button.setBackgroundColor(BtnOFF); + isOn = true; + } + } + }); + linLayout.addView(button); + } + + private void Spinner(LinearLayout linLayout, final int featNum, final String featName, final String list) { + Log.d(TAG, "spinner " + featNum + " " + featName + " " + list); + final List lists = new LinkedList<>(Arrays.asList(list.split(","))); + + // Create another LinearLayout as a workaround to use it as a background + // to keep the down arrow symbol. No arrow symbol if setBackgroundColor set + LinearLayout linearLayout2 = new LinearLayout(getContext); + LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT); + layoutParams2.setMargins(7, 2, 7, 2); + linearLayout2.setOrientation(LinearLayout.VERTICAL); + linearLayout2.setBackgroundColor(BTN_COLOR); + linearLayout2.setLayoutParams(layoutParams2); + + final Spinner spinner = new Spinner(getContext, Spinner.MODE_DROPDOWN); + spinner.setLayoutParams(layoutParams2); + spinner.getBackground().setColorFilter(1, PorterDuff.Mode.SRC_ATOP); //trick to show white down arrow color + //Creating the ArrayAdapter instance having the list + ArrayAdapter aa = new ArrayAdapter(getContext, android.R.layout.simple_spinner_dropdown_item, lists); + aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + //Setting the ArrayAdapter data on the Spinner' + spinner.setAdapter(aa); + spinner.setSelection(Preferences.loadPrefInt(featName, featNum)); + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parentView, View selectedItemView, int position, long id) { + Preferences.changeFeatureInt(spinner.getSelectedItem().toString(), featNum, position); + ((TextView) parentView.getChildAt(0)).setTextColor(TEXT_COLOR_2); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + linearLayout2.addView(spinner); + linLayout.addView(linearLayout2); + } + + private void InputNum(LinearLayout linLayout, final int featNum, final String featName, final int maxValue) { + LinearLayout linearLayout = new LinearLayout(getContext); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + layoutParams.setMargins(7, 5, 7, 5); + + final Button button = new Button(getContext); + int num = Preferences.loadPrefInt(featName, featNum); + button.setText(Html.fromHtml(featName + ": " + ((num == 0) ? 1 : num) + "")); + button.setAllCaps(false); + button.setLayoutParams(layoutParams); + button.setBackgroundColor(BTN_COLOR); + button.setTextColor(TEXT_COLOR_2); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + AlertDialog.Builder alertName = new AlertDialog.Builder(getContext); + final EditText editText = new EditText(getContext); + if (maxValue != 0) + editText.setHint("Max value: " + maxValue); + editText.setInputType(InputType.TYPE_CLASS_NUMBER); + editText.setKeyListener(DigitsKeyListener.getInstance("0123456789-")); + InputFilter[] FilterArray = new InputFilter[1]; + FilterArray[0] = new InputFilter.LengthFilter(10); + editText.setFilters(FilterArray); + editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + InputMethodManager imm = (InputMethodManager) getContext.getSystemService(getContext.INPUT_METHOD_SERVICE); + if (hasFocus) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + } else { + imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); + } + } + }); + editText.requestFocus(); + + alertName.setTitle("Input number"); + alertName.setView(editText); + LinearLayout layoutName = new LinearLayout(getContext); + layoutName.setOrientation(LinearLayout.VERTICAL); + layoutName.addView(editText); // displays the user input bar + alertName.setView(layoutName); + + alertName.setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + int num; + try { + num = Integer.parseInt(TextUtils.isEmpty(editText.getText().toString()) ? "0" : editText.getText().toString()); + if (maxValue != 0 && num >= maxValue) + num = maxValue; + } catch (NumberFormatException ex) { + if (maxValue != 0) + num = maxValue; + else + num = 2147483640; + } + + button.setText(Html.fromHtml(featName + ": " + num + "")); + Preferences.changeFeatureInt(featName, featNum, num); + + editText.setFocusable(false); + } + }); + + alertName.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // dialog.cancel(); // closes dialog + InputMethodManager imm = (InputMethodManager) getContext.getSystemService(getContext.INPUT_METHOD_SERVICE); + imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); + } + }); + + if (overlayRequired) { + AlertDialog dialog = alertName.create(); // display the dialog + dialog.getWindow().setType(Build.VERSION.SDK_INT >= 26 ? 2038 : 2002); + dialog.show(); + } else { + alertName.show(); + } + } + }); + + linearLayout.addView(button); + linLayout.addView(linearLayout); + } + + private void InputText(LinearLayout linLayout, final int featNum, final String featName) { + LinearLayout linearLayout = new LinearLayout(getContext); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + layoutParams.setMargins(7, 5, 7, 5); + + final Button button = new Button(getContext); + + String string = Preferences.loadPrefString(featName, featNum); + button.setText(Html.fromHtml(featName + ": " + string + "")); + + button.setAllCaps(false); + button.setLayoutParams(layoutParams); + button.setBackgroundColor(BTN_COLOR); + button.setTextColor(TEXT_COLOR_2); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + AlertDialog.Builder alertName = new AlertDialog.Builder(getContext); + + final EditText editText = new EditText(getContext); + editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + InputMethodManager imm = (InputMethodManager) getContext.getSystemService(getContext.INPUT_METHOD_SERVICE); + if (hasFocus) { + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + } else { + imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); + } + } + }); + editText.requestFocus(); + + alertName.setTitle("Input text"); + alertName.setView(editText); + LinearLayout layoutName = new LinearLayout(getContext); + layoutName.setOrientation(LinearLayout.VERTICAL); + layoutName.addView(editText); // displays the user input bar + alertName.setView(layoutName); + + alertName.setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + String str = editText.getText().toString(); + button.setText(Html.fromHtml(featName + ": " + str + "")); + Preferences.changeFeatureString(featName, featNum, str); + editText.setFocusable(false); + } + }); + + alertName.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + //dialog.cancel(); // closes dialog + InputMethodManager imm = (InputMethodManager) getContext.getSystemService(getContext.INPUT_METHOD_SERVICE); + imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); + } + }); + + + if (overlayRequired) { + AlertDialog dialog = alertName.create(); // display the dialog + dialog.getWindow().setType(Build.VERSION.SDK_INT >= 26 ? 2038 : 2002); + dialog.show(); + } else { + alertName.show(); + } + } + }); + + linearLayout.addView(button); + linLayout.addView(linearLayout); + } + + private void CheckBox(LinearLayout linLayout, final int featNum, final String featName, boolean switchedOn) { + final CheckBox checkBox = new CheckBox(getContext); + checkBox.setText(featName); + checkBox.setTextColor(TEXT_COLOR_2); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + checkBox.setButtonTintList(ColorStateList.valueOf(CheckBoxColor)); + checkBox.setChecked(Preferences.loadPrefBool(featName, featNum, switchedOn)); + checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (checkBox.isChecked()) { + Preferences.changeFeatureBool(featName, featNum, isChecked); + } else { + Preferences.changeFeatureBool(featName, featNum, isChecked); + } + } + }); + linLayout.addView(checkBox); + } + + private void RadioButton(LinearLayout linLayout, final int featNum, String featName, final String list) { + //Credit: LoraZalora + final List lists = new LinkedList<>(Arrays.asList(list.split(","))); + + final TextView textView = new TextView(getContext); + textView.setText(featName + ":"); + textView.setTextColor(TEXT_COLOR_2); + + final RadioGroup radioGroup = new RadioGroup(getContext); + radioGroup.setPadding(10, 5, 10, 5); + radioGroup.setOrientation(LinearLayout.VERTICAL); + radioGroup.addView(textView); + + for (int i = 0; i < lists.size(); i++) { + final RadioButton Radioo = new RadioButton(getContext); + final String finalfeatName = featName, radioName = lists.get(i); + View.OnClickListener first_radio_listener = new View.OnClickListener() { + public void onClick(View v) { + textView.setText(Html.fromHtml(finalfeatName + ": " + radioName)); + Preferences.changeFeatureInt(finalfeatName, featNum, radioGroup.indexOfChild(Radioo)); + } + }; + System.out.println(lists.get(i)); + Radioo.setText(lists.get(i)); + Radioo.setTextColor(Color.LTGRAY); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + Radioo.setButtonTintList(ColorStateList.valueOf(RadioColor)); + Radioo.setOnClickListener(first_radio_listener); + radioGroup.addView(Radioo); + } + + int index = Preferences.loadPrefInt(featName, featNum); + if (index > 0) { //Preventing it to get an index less than 1. below 1 = null = crash + textView.setText(Html.fromHtml(featName + ": " + lists.get(index - 1))); + ((RadioButton) radioGroup.getChildAt(index)).setChecked(true); + } + linLayout.addView(radioGroup); + } + + private void Collapse(LinearLayout linLayout, final String text, final boolean expanded) { + LinearLayout.LayoutParams layoutParamsLL = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + layoutParamsLL.setMargins(0, 5, 0, 0); + + LinearLayout collapse = new LinearLayout(getContext); + collapse.setLayoutParams(layoutParamsLL); + collapse.setVerticalGravity(16); + collapse.setOrientation(LinearLayout.VERTICAL); + + final LinearLayout collapseSub = new LinearLayout(getContext); + collapseSub.setVerticalGravity(16); + collapseSub.setPadding(0, 5, 0, 5); + collapseSub.setOrientation(LinearLayout.VERTICAL); + collapseSub.setBackgroundColor(Color.parseColor("#222D38")); + collapseSub.setVisibility(View.GONE); + mCollapse = collapseSub; + + final TextView textView = new TextView(getContext); + textView.setBackgroundColor(CategoryBG); + textView.setText("▽ " + text + " ▽"); + textView.setGravity(Gravity.CENTER); + textView.setTextColor(TEXT_COLOR_2); + textView.setTypeface(null, Typeface.BOLD); + textView.setPadding(0, 20, 0, 20); + + if (expanded) { + collapseSub.setVisibility(View.VISIBLE); + textView.setText("△ " + text + " △"); + } + + textView.setOnClickListener(new View.OnClickListener() { + boolean isChecked = expanded; + + @Override + public void onClick(View v) { + + boolean z = !isChecked; + isChecked = z; + if (z) { + collapseSub.setVisibility(View.VISIBLE); + textView.setText("△ " + text + " △"); + return; + } + collapseSub.setVisibility(View.GONE); + textView.setText("▽ " + text + " ▽"); + } + }); + collapse.addView(textView); + collapse.addView(collapseSub); + linLayout.addView(collapse); + } + + private void Category(LinearLayout linLayout, String text) { + TextView textView = new TextView(getContext); + textView.setBackgroundColor(CategoryBG); + textView.setText(Html.fromHtml(text)); + textView.setGravity(Gravity.CENTER); + textView.setTextColor(TEXT_COLOR_2); + textView.setTypeface(null, Typeface.BOLD); + textView.setPadding(0, 5, 0, 5); + linLayout.addView(textView); + } + + private void TextView(LinearLayout linLayout, String text) { + TextView textView = new TextView(getContext); + textView.setText(Html.fromHtml(text)); + textView.setTextColor(TEXT_COLOR_2); + textView.setPadding(10, 5, 10, 5); + linLayout.addView(textView); + } + + private void WebTextView(LinearLayout linLayout, String text) { + WebView wView = new WebView(getContext); + wView.loadData(text, "text/html", "utf-8"); + wView.setBackgroundColor(0x00000000); //Transparent + wView.setPadding(0, 5, 0, 5); + linLayout.addView(wView); + } + + private boolean isViewCollapsed() { + return rootFrame == null || mCollapsed.getVisibility() == View.VISIBLE; + } + + //For our image a little converter + private int convertDipToPixels(int i) { + return (int) ((((float) i) * getContext.getResources().getDisplayMetrics().density) + 0.5f); + } + + private int dp(int i) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) i, getContext.getResources().getDisplayMetrics()); + } + + public void setVisibility(int view) { + if (rootFrame != null) { + rootFrame.setVisibility(view); + } + } + + public void onDestroy() { + if (rootFrame != null) { + mWindowManager.removeView(rootFrame); + } + } +} diff --git a/app/src/main/java/com/android/support/Preferences.java b/app/src/main/java/com/android/support/Preferences.java new file mode 100644 index 0000000..050dfdb --- /dev/null +++ b/app/src/main/java/com/android/support/Preferences.java @@ -0,0 +1,483 @@ +package com.android.support; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Build; + +import java.util.LinkedHashSet; +import java.util.Set; + +public class Preferences { + private static SharedPreferences sharedPreferences; + private static Preferences prefsInstance; + public static Context context; + public static boolean loadPref, isExpanded; + + private static final String LENGTH = "_length"; + private static final String DEFAULT_STRING_VALUE = ""; + private static final int DEFAULT_INT_VALUE = 0; //-1 + private static final double DEFAULT_DOUBLE_VALUE = 0d; //-1d + private static final float DEFAULT_FLOAT_VALUE = 0f; //-1f + private static final long DEFAULT_LONG_VALUE = 0L; //-1L + private static final boolean DEFAULT_BOOLEAN_VALUE = false; + + + public static void changeFeatureInt(String featureName, int featureNum, int value) { + Preferences.with(context).writeInt(featureNum, value); + Menu.Changes(context, featureNum, featureName, value, false, null); + } + + public static void changeFeatureString(String featureName, int featureNum, String str) { + Preferences.with(context).writeString(featureNum, str); + Menu.Changes(context, featureNum, featureName, 0, false, str); + } + + public static void changeFeatureBool(String featureName, int featureNum, boolean bool) { + Preferences.with(context).writeBoolean(featureNum, bool); + Menu.Changes(context, featureNum, featureName, 0, bool, null); + } + + public static int loadPrefInt(String featureName, int featureNum) { + if (loadPref) { + int i = Preferences.with(context).readInt(featureNum); + Menu.Changes(context, featureNum, featureName, i, false, null); + return i; + } + return 0; + } + + public static boolean loadPrefBool(String featureName, int featureNum, boolean bDef) { + boolean bool = Preferences.with(context).readBoolean(featureNum, bDef); + if (featureNum == -1) { + loadPref = bool; + } + if (featureNum == -3) { + isExpanded = bool; + } + if (loadPref || featureNum < 0) { + bDef = bool; + } + + Menu.Changes(context, featureNum, featureName, 0, bDef, null); + return bDef; + } + + public static String loadPrefString(String featureName, int featureNum) { + if (loadPref || featureNum <= 0) { + String str = Preferences.with(context).readString(featureNum); + Menu.Changes(context, featureNum, featureName, 0, false, str); + return str; + } + return ""; + } + + private Preferences(Context context) { + sharedPreferences = context.getApplicationContext().getSharedPreferences( + context.getPackageName() + "_preferences", + Context.MODE_PRIVATE + ); + } + + private Preferences(Context context, String preferencesName) { + sharedPreferences = context.getApplicationContext().getSharedPreferences( + preferencesName, + Context.MODE_PRIVATE + ); + } + + /** + * @param context + * @return Returns a 'Preferences' instance + */ + public static Preferences with(Context context) { + if (prefsInstance == null) { + prefsInstance = new Preferences(context); + } + return prefsInstance; + } + + /** + * @param context + * @param forceInstantiation + * @return Returns a 'Preferences' instance + */ + public static Preferences with(Context context, boolean forceInstantiation) { + if (forceInstantiation) { + prefsInstance = new Preferences(context); + } + return prefsInstance; + } + + /** + * @param context + * @param preferencesName + * @return Returns a 'Preferences' instance + */ + public static Preferences with(Context context, String preferencesName) { + if (prefsInstance == null) { + prefsInstance = new Preferences(context, preferencesName); + } + return prefsInstance; + } + + /** + * @param context + * @param preferencesName + * @param forceInstantiation + * @return Returns a 'Preferences' instance + */ + public static Preferences with(Context context, String preferencesName, + boolean forceInstantiation) { + if (forceInstantiation) { + prefsInstance = new Preferences(context, preferencesName); + } + return prefsInstance; + } + + // String related methods + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public String readString(String what) { + return sharedPreferences.getString(what, DEFAULT_STRING_VALUE); + } + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public String readString(int what) { + try { + return sharedPreferences.getString(String.valueOf(what), DEFAULT_STRING_VALUE); + } catch (java.lang.ClassCastException ex) { + return ""; + } + } + + /** + * @param what + * @param defaultString + * @return Returns the stored value of 'what' + */ + public String readString(String what, String defaultString) { + return sharedPreferences.getString(what, defaultString); + } + + /** + * @param where + * @param what + */ + public void writeString(String where, String what) { + sharedPreferences.edit().putString(where, what).apply(); + } + + /** + * @param where + * @param what + */ + public void writeString(int where, String what) { + sharedPreferences.edit().putString(String.valueOf(where), what).apply(); + } + + // int related methods + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public int readInt(String what) { + return sharedPreferences.getInt(what, DEFAULT_INT_VALUE); + } + + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public int readInt(int what) { + try { + return sharedPreferences.getInt(String.valueOf(what), DEFAULT_INT_VALUE); + } catch (java.lang.ClassCastException ex) { + return 0; + } + } + + /** + * @param what + * @param defaultInt + * @return Returns the stored value of 'what' + */ + public int readInt(String what, int defaultInt) { + return sharedPreferences.getInt(what, defaultInt); + } + + /** + * @param where + * @param what + */ + public void writeInt(String where, int what) { + sharedPreferences.edit().putInt(where, what).apply(); + } + + /** + * @param where + * @param what + */ + public void writeInt(int where, int what) { + sharedPreferences.edit().putInt(String.valueOf(where), what).apply(); + } + + // double related methods + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public double readDouble(String what) { + if (!contains(what)) + return DEFAULT_DOUBLE_VALUE; + return Double.longBitsToDouble(readLong(what)); + } + + /** + * @param what + * @param defaultDouble + * @return Returns the stored value of 'what' + */ + public double readDouble(String what, double defaultDouble) { + if (!contains(what)) + return defaultDouble; + return Double.longBitsToDouble(readLong(what)); + } + + /** + * @param where + * @param what + */ + public void writeDouble(String where, double what) { + writeLong(where, Double.doubleToRawLongBits(what)); + } + + // float related methods + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public float readFloat(String what) { + return sharedPreferences.getFloat(what, DEFAULT_FLOAT_VALUE); + } + + /** + * @param what + * @param defaultFloat + * @return Returns the stored value of 'what' + */ + public float readFloat(String what, float defaultFloat) { + return sharedPreferences.getFloat(what, defaultFloat); + } + + /** + * @param where + * @param what + */ + public void writeFloat(String where, float what) { + sharedPreferences.edit().putFloat(where, what).apply(); + } + + // long related methods + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public long readLong(String what) { + return sharedPreferences.getLong(what, DEFAULT_LONG_VALUE); + } + + /** + * @param what + * @param defaultLong + * @return Returns the stored value of 'what' + */ + public long readLong(String what, long defaultLong) { + return sharedPreferences.getLong(what, defaultLong); + } + + /** + * @param where + * @param what + */ + public void writeLong(String where, long what) { + sharedPreferences.edit().putLong(where, what).apply(); + } + + // boolean related methods + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public boolean readBoolean(String what) { + return sharedPreferences.getBoolean(what, DEFAULT_BOOLEAN_VALUE); + } + + /** + * @param what + * @return Returns the stored value of 'what' + */ + public boolean readBoolean(int what) { + return sharedPreferences.getBoolean(String.valueOf(what), DEFAULT_BOOLEAN_VALUE); + } + + /** + * @param what + * @param defaultBoolean + * @return Returns the stored value of 'what' + */ + public boolean readBoolean(String what, boolean defaultBoolean) { + /*if (defaultBoolean == true && !sharedPreferences.contains(what)) + writeBoolean(what, true);*/ + return sharedPreferences.getBoolean(what, defaultBoolean); + } + + /** + * @param what + * @param defaultBoolean + * @return Returns the stored value of 'what' + */ + public boolean readBoolean(int what, boolean defaultBoolean) { + /*if (defaultBoolean == true && !sharedPreferences.contains(String.valueOf(what))) + writeBoolean(what, true);*/ + try { + return sharedPreferences.getBoolean(String.valueOf(what), defaultBoolean); + } catch (java.lang.ClassCastException ex) { + return defaultBoolean; + } + } + + /** + * @param where + * @param what + */ + public void writeBoolean(String where, boolean what) { + sharedPreferences.edit().putBoolean(where, what).apply(); + } + + /** + * @param where + * @param what + */ + public void writeBoolean(int where, boolean what) { + sharedPreferences.edit().putBoolean(String.valueOf(where), what).apply(); + } + + // String set methods + + /** + * @param key + * @param value + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void putStringSet(final String key, final Set value) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + sharedPreferences.edit().putStringSet(key, value).apply(); + } else { + // Workaround for pre-HC's lack of StringSets + putOrderedStringSet(key, value); + } + } + + /** + * @param key + * @param value + */ + public void putOrderedStringSet(String key, Set value) { + int stringSetLength = 0; + if (sharedPreferences.contains(key + LENGTH)) { + // First read what the value was + stringSetLength = readInt(key + LENGTH); + } + writeInt(key + LENGTH, value.size()); + int i = 0; + for (String aValue : value) { + writeString(key + "[" + i + "]", aValue); + i++; + } + for (; i < stringSetLength; i++) { + // Remove any remaining values + remove(key + "[" + i + "]"); + } + } + + /** + * @param key + * @param defValue + * @return Returns the String Set with HoneyComb compatibility + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public Set getStringSet(final String key, final Set defValue) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return sharedPreferences.getStringSet(key, defValue); + } else { + // Workaround for pre-HC's missing getStringSet + return getOrderedStringSet(key, defValue); + } + } + + /** + * @param key + * @param defValue + * @return Returns the ordered String Set + */ + public Set getOrderedStringSet(String key, final Set defValue) { + if (contains(key + LENGTH)) { + LinkedHashSet set = new LinkedHashSet<>(); + int stringSetLength = readInt(key + LENGTH); + if (stringSetLength >= 0) { + for (int i = 0; i < stringSetLength; i++) { + set.add(readString(key + "[" + i + "]")); + } + } + return set; + } + return defValue; + } + + // end related methods + + /** + * @param key + */ + public void remove(final String key) { + if (contains(key + LENGTH)) { + // Workaround for pre-HC's lack of StringSets + int stringSetLength = readInt(key + LENGTH); + if (stringSetLength >= 0) { + sharedPreferences.edit().remove(key + LENGTH).apply(); + for (int i = 0; i < stringSetLength; i++) { + sharedPreferences.edit().remove(key + "[" + i + "]").apply(); + } + } + } + sharedPreferences.edit().remove(key).apply(); + } + + /** + * @param key + * @return Returns if that key exists + */ + public boolean contains(final String key) { + return sharedPreferences.contains(key); + } + + /** + * Clear all the preferences + */ + public void clear() { + sharedPreferences.edit().clear().apply(); + } +} diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk index e0404db..fcfe6dc 100644 --- a/app/src/main/jni/Android.mk +++ b/app/src/main/jni/Android.mk @@ -1,20 +1,23 @@ LOCAL_PATH := $(call my-dir) -MAIN_LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE := nativelgl +# Here is the name of your lib. +# When you change the lib name, change also on System.loadLibrary("") under OnCreate method on StaticActivity.java +# Both must have same name +LOCAL_MODULE := LGL -LOCAL_CFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w -LOCAL_CFLAGS += -fno-rtti -fno-exceptions -fpermissive -LOCAL_CPPFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w -Werror -s -std=c++17 -LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fms-extensions -fno-rtti -fno-exceptions -fpermissive -LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all, -llog +# -std=c++17 is required to support AIDE app with NDK +LOCAL_CFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -fpermissive -fexceptions +LOCAL_CPPFLAGS := -w -s -Wno-error=format-security -fvisibility=hidden -Werror -std=c++17 +LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fpermissive -Wall -fexceptions +LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all,-llog +LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 LOCAL_ARM_MODE := arm -LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH) +LOCAL_C_INCLUDES += $(LOCAL_PATH) +# Here you add the cpp file to compile LOCAL_SRC_FILES := Main.cpp \ - JavaGPP/Interface/Interface.cpp \ Substrate/hde64.c \ Substrate/SubstrateDebug.cpp \ Substrate/SubstrateHook.cpp \ @@ -26,6 +29,4 @@ LOCAL_SRC_FILES := Main.cpp \ KittyMemory/KittyUtils.cpp \ And64InlineHook/And64InlineHook.cpp \ -LOCAL_LDLIBS := -llog -landroid -lGLESv2 - include $(BUILD_SHARED_LIBRARY) diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk index b80731c..1b6ff66 100644 --- a/app/src/main/jni/Application.mk +++ b/app/src/main/jni/Application.mk @@ -1,4 +1,6 @@ -APP_ABI := arm64-v8a armeabi-v7a x86 x86_64 +# To AIDE Users: If you are using 32-bit/ARMv7 phone, please remove arm64-v8a +APP_ABI := armeabi-v7a arm64-v8a x86 +# APP_PLATFORM := android-18 #APP_PLATFORM does not need to be set. It will automatically defaulting APP_STL := c++_static APP_OPTIM := release APP_THIN_ARCHIVE := true diff --git a/app/src/main/jni/Includes/Dex.h b/app/src/main/jni/Includes/Dex.h new file mode 100644 index 0000000..c2c9a7d --- /dev/null +++ b/app/src/main/jni/Includes/Dex.h @@ -0,0 +1 @@ +#define hexdex "6465780A3033390088AFB5BBB2B8D5D302A3CF4C6C34DBEBC380D7DA27757F8304B200007000000078563412000000000000000034B10000E80200007000000096000000100C0000B3000000680E000091000000CC16000086010000541B0000230000008427000020860000E42B0000087400000A7400000D74000013740000197400002C74000038740000437400004C740000557400005E740000677400007074000079740000827400008B740000947400009F740000AA740000B3740000B7740000BA740000BF740000C4740000CB740000CE740000D7740000DA740000E7740000EA740000FB7400000275000008750000117500001B7500005E750000667500006A7500006F750000757500007F7500008A7500009275000099750000A1750000AD750000BA750000C2750000CC750000D8750000E1750000EB750000FA75000004760000127600001E760000217600002F760000467600005C760000717600008476000098760000AE760000B2760000B6760000BB760000BE760000C4760000CC760000D0760000D5760000E2760000F27600000477000007770000137700001E77000022770000287700002C77000031770000367700003C7700006C7700007D77000083770000917700009D770000A7770000B2770000BE770000C1770000C5770000C9770000CE770000D1770000D9770000DE770000E2770000E6770000EB770000F0770000F6770000FB77000000780000067800000C78000011780000297800004C7800006778000082780000B5780000D8780000F27800001E79000043790000697900008A790000A5790000C7790000E1790000057A0000227A0000487A0000767A0000897A00009E7A0000B47A0000C97A0000E27A0000F77A0000207B0000387B00005D7B0000777B0000A07B0000C37B0000DA7B0000F97B00000D7C0000287C0000447C0000697C0000947C0000BD7C0000E27C0000F77C00001E7D00004B7D0000627D00008D7D0000AB7D0000DA7D0000F47D0000297E0000477E0000657E0000867E0000A57E0000BE7E0000D97E0000127F0000337F00004E7F00006C7F0000927F0000AE7F0000DA7F0000F97F000017800000348000006280000083800000A0800000D2800000EC8000000681000027810000408100005B8100007381000097810000B6810000D5810000F48100001382000032820000538200007482000095820000B4820000D5820000F68200001783000036830000558300007483000093830000B1830000CF830000ED8300000B84000029840000478400006584000083840000A1840000BD840000E0840000FF84000021850000418500006185000081850000A0850000B9850000DD8500000286000022860000458600006B8600008A860000A1860000BB860000CE860000E486000004870000188700003B870000508700007287000095870000A9870000BF870000D3870000EE870000028800001D880000398800004D880000658800007B88000096880000C5880000DD880000EF88000015890000268900003B8900004C8900005D890000828900008B8900009A890000A7890000BE890000CB890000D7890000E1890000F4890000018A00000E8A0000198A0000238A0000338A0000378A00003F8A0000468A00004D8A00005F8A00006C8A0000788A0000808A00008E8A00009B8A0000A58A0000AE8A0000BC8A0000D28A0000EC8A0000FA8A0000048B00000D8B0000158B00001A8B0000268B0000348B00003E8B0000468B0000518B00005B8B00005E8B0000628B0000668B00006B8B0000728B00007C8B0000818B0000868B00008A8B00008F8B0000948B0000998B00009F8B0000A58B0000AC8B0000B48B0000BC8B0000C58B0000CC8B0000D48B0000DB8B0000E18B0000E68B0000EB8B0000F18B0000F88B0000FF8B0000058C00000C8C0000168C00001C8C0000218C0000298C0000318C0000358C0000428C0000458C0000498C00004E8C0000528C0000588C00005D8C0000628C0000678C00006A8C00006E8C0000728C00008F8C0000A38C0000B88C0000CD8C0000D28C0000D58C0000D88C0000DF8C0000E88C0000F68C0000FE8C0000028D00000E8D00001A8D0000268D0000328D00003E8D00004B8D0000578D0000618D0000708D0000758D00007E8D0000878D0000928D0000AE8D0000CA8D0000D48D0000DC8D0000E38D0000F38D0000048E0000088E0000108E0000148E00001B8E0000218E0000328E0000388E0000408E00004E8E00005A8E00006D8E00007F8E0000948E00009E8E0000A58E0000AF8E0000B98E0000C68E0000D58E0000DC8E0000EC8E0000F68E0000FF8E0000138F00001B8F0000248F00003B8F00003E8F0000468F0000578F0000618F0000718F0000808F00008E8F00009A8F0000A78F0000B68F0000BF8F0000C78F0000DC8F0000E08F0000EA8F0000F08F0000FA8F00000290000006900000109000001E90000028900000319000003A9000004790000054900000609000006B9000007A9000009090000099900000AD900000B7900000C3900000C8900000D3900000EA900000F990000005910000119100001B91000027910000399100004C9100005F91000069910000769100007E9100008F91000098910000A7910000BC910000CC910000E1910000EA910000F39100000192000012920000289200003392000041920000539200005C9200006692000078920000889200009A920000A9920000B4920000C6920000CF920000D8920000E2920000EB920000F5920000FD9200000693000009930000169300002E93000046930000599300005D93000062930000699300007793000086930000959300009F930000A9930000B7930000BF930000C7930000D2930000E0930000E9930000F5930000FB9300000C940000169400001B9400002C9400003C94000044940000509400005E9400006D9400007D9400008894000096940000A5940000AB940000B3940000BA940000C1940000CB940000D8940000E2940000F0940000FD9400000D950000199500002B95000038950000439500004F9500005A9500006A95000075950000859500008F950000949500009D950000A2950000AC950000B2950000B7950000BF950000C5950000D2950000D8950000DF950000E5950000EA950000FC950000059600000F9600001A960000299600003996000046960000599600006C9600008296000097960000A0960000B1960000B6960000C7960000CF960000DB960000E2960000EE960000F8960000009700000A970000109700001D9700002E9700003D97000046970000529700005C970000649700006D970000829700008D9700009B970000A7970000B2970000B8970000BE970000CB970000D7970000E2970000EB970000F597000001980000099800001998000021980000319800003D98000046980000549800006298000066980000729800007D98000082980000969800009E980000AE980000B8980000C4980000CD980000DF980000E4980000F3980000FF9800000B99000015990000299900003C990000489900005299000062990000739900007C99000095990000A3990000AF990000B9990000C7990000D3990000DC990000EC990000FA9900000A9A00001B9A0000279A00003E9A0000469A00004E9A0000619A00007D9A0000919A0000AB9A0000C69A0000DE9A0000FA9A00000E9B00001E9B00002A9B00003D9B00004A9B0000589B0000659B0000739B0000829B00008D9B0000969B0000A49B0000B19B0000BB9B0000C89B0000D29B0000DB9B0000E89B0000FC9B0000059C0000149C00001E9C00002C9C00003F9C0000459C00004B9C0000549C00005E9C0000659C0000749C0000809C00008E9C0000939C00009D9C0000A59C0000B69C0000BD9C0000C69C0000D09C0000D79C0000E09C0000EC9C0000F29C0000FD9C0000079D00000F9D0000179D00001E9D0000299D0000339D0000449D00004F9D0000619D0000669D00006D9D0000709D00007C9D0000889D0000969D0000A79D0000B59D0000C39D0000D19D0000DE9D0000ED9D0000009E00000E9E0000179E0000279E0000369E0000439E0000509E00005A9E0000689E0000719E0000789E0000819E0000899E00008F9E00009B9E0000A59E0000AC9E0000B49E0000BA9E0000C19E0000CE9E0000D59E0000DB9E0000E99E0000F69E0000029F00000C9F0000179F0000249F0000279F00002B9F00002F9F0000339F0000369F0000399F0000A19F00008FA5000095A500009BA5000037000000420000004A0000005B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F5000000F6000000F8000000FA0000002401000048010000510100005201000053010000540100005501000056010000570100003F000000000000006C70000040000000000000007470000041000000000000007C7000004200000001000000000000004300000001000000847000004500000001000000747000004600000001000000907000004A00000002000000000000004D00000002000000987000004F00000002000000A07000004F00000002000000747000005000000002000000A87000005100000002000000B07000005C00000003000000B87000005D00000003000000747000005E00000003000000C07000005F00000004000000000000006300000005000000A07000006300000005000000C87000006800000005000000D07000005F00000006000000000000005F0000000700000000000000620000000A00000098700000630000000A000000D87000005F0000000B00000000000000630000000B00000074700000640000000B00000090700000650000000B000000A8700000670000000B000000C0700000680000000B000000B0700000680000000B000000E07000006B0000000B000000E8700000650000000C000000A8700000620000000D000000987000005F0000000E00000000000000660000000F000000F07000005F00000014000000000000006300000016000000747000005F00000019000000000000005F0000001A00000000000000630000001D000000747000006300000020000000747000005F00000023000000000000005F0000002A00000000000000620000002B000000987000005F0000002C000000000000005F0000002E000000000000005F0000003000000000000000690000004B000000FC7000005F00000066000000000000006300000066000000087100006300000067000000107100006800000067000000187100006A00000067000000207100006B000000670000002C7100005F00000077000000000000006300000077000000747000005F0000007E00000000000000620000007E00000098700000630000007E00000034710000680000007E0000003C710000630000007E000000747000005F00000080000000000000006200000080000000987000006800000080000000447100006300000080000000347100006300000080000000747000006500000080000000A87000006800000080000000B070000062000000810000009870000063000000810000007470000063000000830000007470000068000000840000004C7100005F00000086000000000000005F0000008700000000000000630000008A00000054710000680000008C000000E0700000240100008D00000000000000250100008D0000005C710000260100008D00000098700000270100008D00000064710000280100008D0000006C710000290100008D000000787100002A0100008D0000008C7100002A0100008D000000947100002B0100008D0000009C7100002C0100008D000000107100002F0100008D000000A4710000350100008D000000AC710000310100008D000000BC7100003F0100008D000000C87100003B0100008D000000187100002F0100008D000000D47100002C0100008D000000DC7100002C0100008D000000E47100002C0100008D000000EC7100002C0100008D000000F47100002F0100008D000000FC7100002C0100008D000000047200002C0100008D0000000C7200002C0100008D000000147200002C0100008D0000001C7200002C0100008D0000002C7000002C0100008D0000003C7000002C0100008D000000547000002C0100008D000000647000002C0100008D000000A07000003B0100008D00000024720000430100008D0000002C7200002C0100008D000000347200002C0100008D000000347000002C0100008D0000003C7200003D0100008D000000447200002C0100008D0000004C700000430100008D000000507200002C0100008D00000058720000310100008D00000060720000320100008D0000006C720000330100008D00000078720000360100008D00000088720000380100008D000000947200003B0100008D000000A07200003F0100008D000000A8720000420100008D000000B47200002C0100008D000000247000002C0100008D000000C0720000390100008D000000C87200002C0100008D000000D47200002C0100008D000000DC7200003B0100008D000000E47200002C0100008D000000EC7200003B0100008D000000F47200002C0100008D00000008710000370100008D000000FC720000310100008D0000000C730000340100008D00000018730000400100008D00000028730000400100008D000000347300003C0100008D00000040730000410100008D0000004C7300003B0100008D000000607300003E0100008D00000068730000450100008D00000074730000440100008D000000847300003F0100008D000000947300002C0100008D000000C87000002C0100008D000000747000002D0100008D0000007C7000002E0100008D000000907000002F0100008D000000A8700000300100008D000000A0730000310100008D000000AC730000390100008D000000B87300003A0100008D000000C07000003B0100008D000000B07000003F0100008D000000C47300003B0100008D000000E0700000430100008D000000E87000002C0100008D000000D0730000460100008D000000D87300002C0100008D000000E07300003B0100008D000000E87300003B0100008D000000F0730000480100008E00000000000000490100008E000000987000004A0100008E0000009C7100004B0100008E000000A07000004E0100008E000000F87300004B0100008E000000087100004B0100008E000000C87000004B0100008E000000347100004B0100008E0000005C7000004D0100008E000000007400004B0100008E000000747000004C0100008E000000B87300004F0100008E000000E8700000650000008F000000A87000005F0000009400000000000000630000009400000074700000120012001401000013001300380000001E001E00FD00000023000100980100002C000200D90100002C000200D50200002D000200B20200002F000200D40100002F000200DD0200002F000200E10200003C003C00440000003E000100D10200004D006600AC0200004D008000BD0200004D000200BE0200004D000200C20200004D004A00C80200004E006600AC0200004E008000BD0200004E000200BE0200004F006600AC0200004F008000C902000050008E00EF01000050006600AC02000050003600B802000050000200BE02000050008E00BF02000050008000C002000051006600AC02000051000200BE02000051004700C502000052005500AD02000053005500AD02000053003A00BB02000054005500AD02000055006600AC02000055003600B802000055008000BD02000055000200BE02000055000200C102000056005900AD02000057005900AD02000057003A00BB02000058005900AD02000059006600AC02000059003600B802000059008000BD02000059000200BE0200005A006600AC0200005A003700B90200005A008000BD0200005A000200BE0200005B006600AC0200005B004000B70200005B000200BE0200005B008000C00200005B004100C30200005B008000C40200005B004A00C80200005C008E00EB0100005C006600AC0200005C003F00BA0200005C008E00BC0200005C008000C70200005C004A00C80200005D006600AC0200005E008E00950200005E006600AC0200005F006600AC02000060006600AC02000061006600AC02000063006600AC02000063008E00CE02000064002B008501000064002B00A201000064000100E401000064000100E501000064000200E601000064000200E701000064006600AC02000065006600AC02000065008000BD02000065000200BE02000065004900C602000066000200280000006600020029000000660002002A00000066000200300000006600020033000000660001004B000000660002004C00000066000200FE00000066000100FF0000006600020000010000660002000101000066000200020100006600800009010000660002000C010000660002000D010000660002001001000066000200160100006600020017010000660080001D010000660002001E010000660002001F0100006600020022010000660002002301000066000700B701000066003F000A020000660043000B02000066003F000C020000660043000D02000066003F000E020000660030000F020000660066001502000066003F001802000066008E002C02000066003B005402000066003E005702000066003E0058020000660044005A02000066003D009D02000066008E009E02000066002F00CF02000067008E0039000000670000003A000000670001003B000000670002003C000000670003003D000000670080003E0000006700800060000000670007008901000067008E00EE01000067008E0003020000670067003702000067000C0096020000680002007801000068000200DD01000069000200DE0100006A000200670100006B000200DC0100006B000200DF0100006C0002006E0100006D00020027000000820075002B02000004004D002300000004002F00D3010000040062002002000004004F008C0200000500560023000000050014008B01000005001300780200000500130082020000050012008E0200000500110092020000050014009702000006002E00D201000006004D009702000007001500B201000007003E00C201000007002200C601000007002000C801000007003D00CB01000007005D009C0200000A009200230000000A001700680200000A0016006C0200000B004D00700100000B001800810100000B001F00390200000B001A003A0200000B001B003B0200000B001C003C0200000B001D003E0200000B001E003F0200000B0019004C0200000C00AD00880100000C0018009D0100000C00AF00B40100000C000600BB0100000C000B00BD0100000C000F00BF0100000C004400C90100000C004C00CA0100000D00A200230000000D002100CB0200000E002A00BA010000100023009001000011000A0030020000140053006602000014005E008D02000015004D002300000015004F006502000015004E00670200001500500088020000160025002F02000018004D002300000018006300230000001800AB00340200001800AC003502000019002600C00100001B002800AE0100001C004F00230000001F00A900EC0100001F00A900ED01000020002900BC0100002200B0008F01000024000C008E010000250004007101000026000700B101000026000300C401000026000300C50100002B001500B70100002B004F00930200002E004F008F0200002F0052002300000030006B006A01000030006A004E02000030006B00B302000031005000B1020000320056002300000032002D00BE01000032009B000102000032004E006102000032004F006202000032006D0073020000320069007F020000320051008102000034002C00B5010000350059002300000035004F0069020000360056002300000036009F006002000036004F006202000036006D0073020000360066007A020000360068007D020000360091008902000036004F008A02000037005600230000003700A300EB01000037005E006302000037009F00640200003700710079020000370091008902000037004F008A0200003A005600230000003A002700CC0100003A00A300510200003A00A0006B0200003A009F006D0200003A0091006F0200003A004F00710200003A006500720200003A0067007B0200003B005600230000003B006A006A0100003B006A004E0200003B0069007F0200003B004F00930200003D005600230000003D002D00BE0100003D005F00700200003D006D00730200003D0066007A0200003D0069007F0200003D007300840200003E005000230000003E006D00230000003E005100740200003F005600230000003F006A006A0100003F002D00BE0100003F004D004D0200003F004E00610200003F004F00620200003F004F006E0200003F006D00730200003F004F00800200003F005100810200003F004F00910200003F004F0093020000400056002300000040005E006302000040009F0064020000400066007A020000400091008902000040004F008A020000410056002300000041006A006A01000041002C00B501000041000900E301000041004F00800200004100510081020000420050002300000042004F0069010000430056002300000043006A006A01000043000700D101000043004E0061020000430051008102000043004F009102000043004F0093020000440056002300000044006A006A01000044006A004E020000440050005902000044004F006202000044006D0073020000460056002300000046002400C301000046002400CD01000046004F007602000046004F007702000046007C007E020000460051008102000046004F0083020000470057002300000047002400B301000047003900C701000047007F005F02000047006D007302000047006E007C02000047004F0086020000490056002300000049001500B701000049002400CE01000049002400D001000049009F006402000049007100790200004900510081020000490091008902000049004F008A0200004A005600230000004A004F00620200004A0064006A0200004A004F006E0200004A006D00730200004A004F00750200004A0066007A0200004A005100810200004A009F00850200004A009F00870200004A009100890200004A004F008A0200004A004E008B0200004A006000900200004A006100900200004B003000100200004B004D00970200004C004D00210000004C004D00230000004C006200200200004D008700230000004D007E00260200004D007D00270200004D007D00280200004E008600230000004E006A001F0200004F008C00230000004F006A001F02000050008F002300000050006A001F02000051008A0023000000510070002302000051006F0025020000520080002300000052006C0022020000530081002300000053005C001F020000540080002300000054005C001F020000550085002300000055006A001F020000560082002300000056006C0022020000570083002300000057005C001F020000580082002300000058005C001F020000590088002300000059006A001F0200005A008900230000005A0072001E0200005B008B00230000005B006A001F0200005C008E00230000005C006A001F0200005D008400230000005D006A001F0200005E008400230000005E006A001F0200005F008400230000005F006A001F02000060008400230000006000A60024020000610084002300000061006A001F02000062004D002300000062004D0055020000630084002300000063004D005502000064008400230000006400A7002902000065008D0023000000650072001E0200006600560023000000660074002B00000066007A002C000000660078002D000000660079002F0000006600580031000000660078003200000066007B003400000066005600360000006600B1004800000066003E005200000066003E005400000066005A005500000066007500580000006600740059000000660077000F010000660076001501000066004D00180100006600B1001901000066004D001A010000660077001B010000660078001C01000066007900200100006600790047010000660010005F0100006600310060010000660032006101000066009000620100006600A80063010000660008008A010000660008009B0100006600A100A601000066001000CF0100006600A300F001000066004D002102000066002B002A02000066004F0093020000670056002300000067005B0023000000670098007D010000670096007E010000670097007F01000067004D00810100006700AD008801000067004C00C101000067004C00CA0100006700AE000402000067000B0005020000670043000602000067009C003D02000067009C003F0200006700A400440200006700A500440200006700AD00440200006700AF00440200006700010045020000670002004502000067000500460200006700060046020000670008004702000067000A004702000067000B004702000067000E004802000067000F004802000067003F004902000067004200490200006700440049020000670092004C02000067003300D602000067003400D602000067003500D602000067003600D602000067005500D702000067009D00D702000067009300D802000067009400D902000067005000DA02000067009500DA02000067009900DB02000067005400DC02000067009A00DC02000068004D002300000069004D00230000006A004D00230000006B004D00230000006C004D00230000006D004D00230000006E004D0023000000750092003802000077003800AC01000077004700B801000077004800B901000079000D009A01000079000000080200007B000A00310200007E004D00230000007E003700B60100007E003E00B00200008000A900880100008000AA009F01000080000700D80100008000AD0012020000800040004F02000080004400500200008000B2009B02000080003F00CB02000080004100CB02000081004D0023000000810045006F010000810046006F01000081003E00B0020000820092000202000083003B00B00100008300AA00B401000083009F005E02000084003C00EA01000084009F005E02000085004B007401000086004A00F10100008700A300D7010000870039001C02000088004D00230000008800AA006801000089009E00230000008A003A00B00100008A000700980200008B004900CC0200008C004A00F10100008C000700980200004C000000010000000400000000000000040100000000000081A70000000000004D000000000000007E000000247000000701000034AE000097A70000000000004E000000000000007E0000002C700000070100004CAE0000BEA70000000000004F000000000000007E0000002C7000000701000064AE0000D7A700000000000050000000000000007E0000002C700000070100007CAE0000EDA700000000000051000000000000007E000000347000000701000094AE00000EA800000000000052000000000000007E0000003C70000007010000BCAE00002BA800000000000053000000000000007E0000004470000007010000D4AE00003EA800000000000054000000000000007E0000004470000007010000ECAE000054A800000000000055000000000000007E0000002C7000000701000004AF000067A800000000000056000000000000007E0000003C700000070100001CAF000086A800000000000057000000000000007E000000447000000701000034AF000099A800000000000058000000000000007E00000044700000070100004CAF0000AFA800000000000059000000000000007E0000002C7000000701000064AF0000C2A80000000000005A000000000000007E0000004C700000070100007CAF0000DEA80000000000005B000000000000007E0000002C7000000701000094AF0000FAA80000000000005C000000000000007E0000002C70000007010000ACAF00001FA90000000000005D000000000000007E0000002C70000007010000C4AF000040A90000000000005E000000000000007E0000002C70000007010000DCAF000053A90000000000005F000000000000007E0000002C70000007010000F4AF000068A900000000000060000000000000007E00000054700000070100000CB000007BA900000000000061000000000000007E0000002C7000000701000024B000008EA900000000000062000000000000007E0000005C700000070100003CB00000A1A900000000000063000000000000007E0000005C700000070100004CB00000B1A900000000000064000000000000007E000000647000000701000064B00000C6A900000000000065000000000000007E0000004C700000070100007CB00000E5A900000000000066000000010000007E00000000000000070100000000000001AA000070AC000067000000010000007E000000000000000E01000094B0000008AB000074AC000068000000110000007E00000000000000FFFFFFFFC4B0000006AC000083AC000069000000110000007E00000000000000FFFFFFFFD4B0000017AC00008EAC00006A000000110000007E00000000000000FFFFFFFFE4B0000026AC000094AC00006B000000110000007E00000000000000FFFFFFFFF4B0000035AC00009AAC00006C000000110000007E00000000000000FFFFFFFF04B1000046AC0000A5AC00006D000000110000007E00000000000000FFFFFFFF14B1000055AC0000ABAC00006E000000110000007E00000000000000FFFFFFFF24B1000064AC000000000000010000000100000084640000060000001A0061007110740100000E00010001000100000089640000040000007010000000000E0002000200020000008D640000040000006F20020010000E000600060001000000946400000E0000005B010C0059020F005B030D0059040E005B0510007010640100000E0007000400030000009F6400005300000052300F003505050052300F00280201506E20AB00040054300D0052310E0052320F003525050052320F002802015271302D011002543010002201810070107001010054320D006E20720121000C011A021D006E20720121000C0154320C00542260006E20720121000C011A0213006E20720121000C0152320F003525050052320F00280201526E20710121000C016E10730101000C017110380001000C016E20C60010000E0000000200020000000000AF640000010000000E0000000200020000000000B6640000010000000E0000000400040001000000BD6400000A0000005B011100590213005B0312007010640100000E000500020003000000C664000036000000523013002C002A000000281D543011005400780054311100541170006E20A0001000543011005400780054311100541173006E209F00100028065430110012115C017A005430120052311300120271302D0110020E000000000202009CFFFFFFFAFFFFFF1B000000040000000300030001000000D3640000080000005B0114005B0215007010640100000E000400020002000000DB6400001D00000022000A001A016D01702013001000150100106E2015001000542115007110320001000C016E20140010005421140054116B006E20120001000E0000000600060001000000EB640000120000005B0117005C021A005B031B00590419005B05180070106401000055021A005C0216000E000500020003000000F76400006300000054301B00523119005532160071302C0110025530160038002D00543018002201810070107001010054321B006E20720121000C011A021F006E20720121000C016E10730101000C017110380001000C016E205C0010005430180054311700521156006E205800100012005C301600282B543018002201810070107001010054321B006E20720121000C011A021E006E20720121000C016E10730101000C017110380001000C016E205C0010005430180054311700521155006E205800100012105C3016000E00000004000400010000000A6500000A0000005B011C005B021E0059031D007010640100000E000800060003000000136500001E00000054201E006E10AE0000000C006E10660100000C0052211D0071302D01100512006E20530003000C001F004A0054211C00521168006E20C70010000E00020002000000000028650000010000000E000000020002000100000035650000060000005B011F007010640100000E0006000300030000003C6500002100000054301F005400230054006B0054311F005411230054116B001A01E8016E20110010000C001F00310012113805070012226E304A002001280512026E304A0010020E000000030003000100000050650000080000005B0120005B0221007010640100000E0007000300030001005865000092000000544021006E10660000000C006E10660100000C0071103B0000000A00380005001A001A00280B544021006E10660000000C006E10660100000C007110630100000A00544120005211270038010D005441200052112700341007005441200052112700011028120D005441200052112700380108005441200052112700011028051401F8FFFF7F011054412000541124002202810070107001020054432000543325006E20720132000C021A031D006E20720132000C025443200054332300543360006E20720132000C021A0313006E20720132000C026E20710102000C021A0320006E20720132000C026E10730102000C027110380002000C026E205C0021005441200054112500544220005222260071302D0121005441210012026E20690021000E00000000003100010001017D3302000200010000008C650000060000005B0122007010640100000E000600030003000000936500001A000000543022005400230054006B00543122005411230054116B001A01E8016E20110010000C001F003100121112026E304A0010020E000600060001000000A56500000E0000005B012300590227005B0324005B042500590526007010640100000E000900020003000000B06500009F000000220005005471230054116B0070200400100022013A005472230054226B007020650021005272270038021A00220281007010700102001A0305016E20720132000C02527327006E20710132000C026E10730102000C026E206A00210012226E206B0021001A021B0071103C0002000C026E206C00210012122323910022041C0013050A0070203900540012054D0403056E2068003100220452007020DD0074006E206D0041006E10670001001A0456006E20080040006E200900100022043F005475230054556B0070207D0054006E20850024006E207E0014006E2009004000220253007030DF0072011A050A016E3007005002220254007020E10072001A052E006E30060050025472230055227400380213006E10050000000C026E100B0002000C051306F6076E20450065006E100C00020028046E100A0000000E0000000200020001000000F1650000060000005B0128007010640100000E000600030003000000F8650000210000005430280054002C0054006B005431280054112C0054116B001A01E8016E20110010000C001F00310012113805070012226E304A002001280512026E304A0010020E00000003000300010000000C660000080000005B0129005B022A007010640100000E000700030003000000146600005800000054402A006E10660000000C006E10660100000C005441290054112D00220281007010700102005443290054332E006E20720132000C021A031D006E20720132000C025443290054332C00543360006E20720132000C021A0313006E20720132000C026E20720102000C021A0320006E20720132000C026E10730102000C027110380002000C026E205C0021005441290054112E005442290052222F0071302E01210054412A0012026E20690021000E00020002000100000029660000060000005B012B007010640100000E000600030003000000306600001A00000054302B0054002C0054006B0054312B0054112C0054116B001A01E8016E20110010000C001F003100121112026E304A0010020E000500050001000000426600000C0000005B012C005B022D005B032E0059042F007010640100000E0008000200030000004C660000670000002200050054612C0054116B0070200400100022013A0054622C0054226B00702065002100220256007020E50062006E206D0021006E10670001001A0257006E20080020006E200900100022023F0054632C0054336B0070207D00320012136E20850032006E207E0012006E2009002000220357007030E70063011A040A016E3007004003220358007020E90063001A042E006E300600400354632C0055337400380313006E10050000000C036E100B0003000C041305F6076E20450054006E100C00030028046E100A0000000E00000005000500010000007D6600000C0000005B0130005B0231005B033200590433007010640100000E0005000300030000008766000018000000542031006E105F0000000A0038000A00542032005221330071302C0110042808542032005221330071302C0110040E00080008000100000093660000120000005B0134005B023A005B0337005B043900590536005B0638005B0735007010640100000E000600020003000000A06600004200000054403A0022018100701070010100544237006E20720121000C011A021D006E20720121000C0154423400542260006E20720121000C011A0213006E20720121000C01544239006E20720121000C016E10730101000C017110380001000C016E20C6001000544037005241360054423800544335006E20920032000A0271302D0110020E000600060001000000AB660000120000005B013C005C023E005B033D005B0440005B053F0070106401000055023E005C023B000E000600020002000000B76600005700000055403B00DF0000015C403B003800290054413D0012026E208800210054414000220281007010700102001A03E5026E20720132000C0254433F006E20720132000C021A0302006E20720132000C026E10730102000C026E20C60021000E0054413D00130208006E208800210054414000220281007010700102001A03E6026E20720132000C0254433F006E20720132000C021A0303006E20720132000C026E10730102000C026E20C60021000E0000000200020001000000D0660000060000005B0141007010640100000E000400020002000000D7660000120000005420410054006D00130108006E209D0010005420410054006E0012016E20880010000E000200020001000000E0660000060000005B0143007010640100000E000500020003000100E766000045000000553042001201390004001210280201105C3042005530420038002000543043005400780054324300542273006E20A0002000543043005400780054324300542270006E209F00200054304300540078006E30A10010012817543043005400780054314300541170006E20A0001000543043005400780054314300541173006E209F00100028020D000E000000000000004200010001017A430200020001000000F7660000060000005B0144007010640100000E000500020003000000FE660000280000005430440054006D0012016E209D0010005430440054006D0012016E209A0010005430440054006E00130108006E20880010006E10430004000C001A01530012127130CB0010020C006E10CC0000000E00050002000300000009670000260000006E10430004000C001A01060112127130CB0010020C006E10CC00000054304500540075005431450054116F006E20700010005430450054007100543145005411750072204800100012000F00020002000100000013670000060000005B0145007010640100000E0002000200010000001A670000060000005B0146007010640100000E000400020002000000216700001D0000005420460054006D0012016E209D0010005420460054006D0054214600521159006E209A0010005420460054006E00130108006E20880010000E00000001000100010000002B670000040000007010640100000E000300010002000000306700002300000071001D0100000C0038001E001401240203016E20030010002201660070200501010071101F01010071001E0100000C016E101601010071001E0100000C016E10180101000E000000030002000100000040670000090000005B12470070106401010012005C1048000E0000000400010003000000486700001700000054304700540073006E108000000054304700543147006E100E0101000C0154324700542273007130200110020E00000009000300030001004F670000B00000006E10400008000A00120112122B00A00000000F0154604F0054006E001501003F6E208100100054604F0054006D006E209A00100054604F0054007B0052614D006E10410008000A0352644B00C7438733B0315901080054604F0054007B0052614E006E10420008000A0352644C00C7438733B0315901090054604F005400710054614F005411750054634F0054337B007230490010030F026E10410008000A0052634B00C73087006E10420008000A0352644C00C743873354644F0054446E001505803F6E208100540054644F0054446D006E209A00540013040A0035401A003543180054644F007110210104000A043804100054644900130508006E204400540054644A006E204400140028020D010F0254604F0054007B005200080059604D0054604F0054007B005200090059604E006E10410008000A0059604B006E10420008000A0059604C000F0200010300000000008300000046000000040000007A0000000C00010001017C8701000000030002000100000088670000120000005B124F0070106401010054104F0054006D005B10490054104F0054006E005B104A000E000500050001000000916700000C0000005B0150005B025100590352005B0453007010640100000E0005000300030000009B67000048000000542051005221520071302C011004522052002B00350000002831542053006E10B40000000C007110490100000C0012F16E304D01100439042200542053006E10B40000000C007110490100000C006E102F01000028136A04840054205000540078005421500038040500541177002803541176006E20A30010000E0000010300FDFFFFFF2200000003000000040000000100000000000000AD670000050000007100250100000C00110000000C00000003000100B16700006300000012001A016C0171105E0101000C011A028D011203233492006E30600121040C0212146E2079014200233393006E30780102030C031A0509026E205F0151000C056E20770145006E20750135000C061F068B007210830106000C0772107B0107000C0772107C0107000A0838082A0072107D0107000C086E10650108000C091A0A32026E205F01A9000C0A6E2077014A006E2076018A000A0B390B12001A0766016E205F0179000C076E20770147006E20750187000C041F040400110428D328020D01000011000000010000005C000100010060000200010002000000166800000600000022006400702001011000110002000100010000001B680000050000007010260101000A000F000000020001000100000021680000110000005410750038000D0054106D006E10990000000A003900030028031200280212100F0000000100000000000000AD67000003000000620072001100000001000100000000001B68000003000000690072001100000004000200010000002668000013000000823054216B006E100F0001000C016E10290001000C0152110300C8101501003FC61087000F00000005000200030000002D68000012000000824054316B006E100F0001000C016E10290001000C01121271303F0002010A0087000F001600020005000000346800007E03000008001400080115007010640100001A020F0071102B0002000A02590267001A02120071102B0002000A03590368001A03070071102B0003000A03590354001A03110071102B0003000A0359035B001A03100071102B0003000A0359035D001303220159035F001303D20059035E0012035903610013046400590462001504804059045C0013042D0059045A0014043333333F59045900140400FF00FF59046A001504FFFF590469001A04080071102B0004000A04590456001A040D0071102B0004000A04590455001A040A0071102B0004000A04590457001A040E0071102B0004000A055905640071102B0004000A055905650071102B0004000A045904580071102B0002000A02590263001A020C005B0260005B016B006901830022023B0070206E0012005B027500540275007010280100000C046E2071004200220243007020970012005B026F00220243007020970012005B026D0054026D006E209D00320054026D00520459006E209A00420022023F0070207D0012005B026E0054026E00130408006E208800420054026E0052045B006E208200420054026E0012146E208500420054026E0022053E0052065F007020230160000A0612E770307A0065076E20840052002202150070102E00020052055C006E203000520052055B006E202F0052001A050B0071102B0005000A056E303100420522053D007020730015005B05790054057900220642007030950076076E207600650052055A0082556E100F0001000C066E10290006000C0671303F0054060A058755540679006E10740006000C0659650400540679006E10740006000C06596505005406790062080A006E20790086006E100F0100000C0671203D0036000C0654087900216971302A0036090C096E2075009800540879006E10740008000C081F082D0013090A007020220190000A0A598A0600540879007010280100000C0A6E207800A80054087900220A5D007020F3000A006E207700A8002208320070204B001800220A4200703095007A076E205000A800520A5A0082AA6E100F0001000C0B6E1029000B000C0B71303F00A40B0A0A87AA6E104C0008000C0B59BA04006E104C0008000C0B59BA0500220B8100701070010B001A0C22006E207201CB000C0B6E10100100000C0C6E207201CB000C0B1A0C06006E207201CB000C0B520C5A006E207101CB000C0B1A0C05006E207201CB000C0B520C5A006E207101CB000C0B1A0C04006E207201CB000C0B6E1073010B000C0B1A0CAA021A0DB5026E404D00B8DC6E204F003800520B59006E204E00B8007010280100000C0B6E205100B800220B4A007020BC001B001A0CE7026E20C600CB00520C67006E20C700CB00620C01006E20C900CB00150CA0416E20C800CB00220C4200703095007C07130D0B006E209600DC006E20C000CB00220E5E007020F5000E006E20C200EB00220E3F0070207D001E005B0E7000540E70006E2085004E006E10170100000C0E540F700070302401E00F220E4300702097001E00125F6E5F9B009E9F130D10006E209C00DE00220D4A007020BC001D00520967006E20C7009D00150990416E20C8009D00130911006E20BF009D002203420070309500730713070E006E20960073006E20C0003D0022074A007020BC001700620F02006E20BE00F70012FF6E20C100F7006E20C50047006E20C4004700520467006E20C7004700150420416E20C80047006E20BF009700125412096E54C30097992204440070209E0014005B04780022043E0052095E007020230190000A0970307A00F4095B04760022043E0054096E006E107F0009000C0970207B0094005B047700540477001509803F59490B00540478006309840038090500540977002803540976006E20A30094005404780052095D006E20A200940022043F0070207D0014005B0473005404730012196E2085009400220443007020970014001239130F0A006E599B00F4F9130911006E209C0094002209420012EF70309500F90F130F09006E209600F900220F3600702056001F006E2059009F000811020012026E2058002F001A0249006E205C002F00520267006E205D002F0022025F007020F70002006E205A002F00220260007020F90002006E205B002F00220242000813030012E370309500320313030B006E2096003200220336007020560013006E20590023000810020012026E20580023001A0203016E205C002300520267006E205D002300220261007020FB0002006E205A00230054026F000212050054056D006E209800520054026F0054056E006E20980052006E10100100000C023802080054026D006E2098008200280854026D00540579006E20980052006E209800DE006E209800BE0054026E006E207E00E20054026E006E207E00720054027800540573006E209F00520054026E00540578006E207E0052006E209800F4006E209800340054026E006E207E0042006E401101107D0E00080004000500000043690000360000002200360054416B0070205600100022013E0012F270307A002102127212536E537C0021236E2059001000524268006E205D00200012026E20570020007110380007000C026E205C002000524254006E205800200022024E007040D40042766E205A0020006E207E0005000E00080004000500000064690000360000002200360054416B0070205600100022013E0012F270307A002102127212536E537C0021236E205900100012026E2057002000524268006E205D0020007110380006000C026E205C002000524254006E205800200022024F007030D60042076E205A0020006E207E0005000E000D00050006000000836900007D0000002200360054816B00702056001000070722003E0012F170307A001001127112526E527C0010126E2059000700528168006E205D00170012016E20570017001A010B011A0200006E306B011B020C0571303301AB0C0A0138012300220281007010700102006E20720152000C021A031F006E20720132000C026E10730102000C027110380002000C026E205C002700528256006E205800270012012821220281007010700102006E20720152000C021A031E006E20720132000C026E10730102000C027110380002000C026E205C002700528255006E20580027001211011422025000078301A67606D80002006E205A0027006E207E0079000E0000000600030005000000CD6900002B00000022004A0054316B007020BC001000523157006E20BD0010007110380005000C016E20C6001000130111006E20BF001000523168006E20C7001000120112126E30CA001002120112526E52C30010126E207E0004000E0000000700050005000000E36900002C0000002200370054216B0070205E0010006E2063005000522168006E20640010000000522158007110280001000C016E20600010007130330145060A016E206100100022015A007054ED0021506E20620010006E207E0003000E000E00040006000000FD690000B300000022003E0012F270307A0020020706120012526E507C00060222033F0054A46B0070207D00430007376E2084006700130310006E208700370012146E208500470022083F0054A96B0070207D0098006E20870038006E52860008026E20850048001A02090071102B0002000A026E2082002800130208006E20880028005BA86C0022024A0054A36B007020BC00320052A357006E20BD003200220381007010700103001A09E6026E20720193000C036E207201C3000C031A0903006E20720193000C036E10730103000C036E20C6003200130311006E20BF00320052A368006E20C700320012036E30CA003204130314006E53C3000203380D21006E2088000800220081007010700100001A03E5026E20720130000C006E207201C0000C001A0302006E20720130000C006E10730100000C006E20C600020022005C0007A107C50724078301D27606F10000006E20C20004006E207E0047006E207E0037006E207E007B000E00000003000100020000004D6A0000340000002020040039001400220018007100370000000C01702034001000220162007010FD0001006E2035001000281E07201F0004001401240203016E20030010002200660007211F01040070200501100069007200620072006E1016010000620072006E10180100000E000F00050006000000656A00007700000022003F0054A16B0070207D00100022013E0012F270307A002102127212536E537C0021232202360054A36B00702056003200072771203401CD000A02220381007010700103006E207201D3000C031A041D006E20720143000C0354A460006E20720143000C031A0413006E20720143000C03390204001214280201246E20710143000C031A0420006E20720143000C036E10730103000C037110380003000C036E205C00370012036E20570037006E205900170052A354006E205800370052A368006E205D0037002204550007A501C907D801E67606E30004006E205A0047006E207E0070006E207E000B000E0000000A00040005000000B06A00006D00000022003F0054616B0070207D00100022013E0012F270307A002102127212536E537C0021232202360054636B007020560032007120350189000C03220481007010700104006E20720194000C041A051D006E20720154000C04546560006E20720154000C041A0513006E20720154000C046E20720134000C041A0520006E20720154000C046E10730104000C047110380004000C046E205C00420012046E20570042006E2059001200526454006E2058004200526468006E205D004200220459007058EB0064926E205A0042006E207E0020006E207E0007000E0000001300050008000000E16A0000DD00000008001100220189001A021800080312006E206D0123000C0271107A0102000C0270208001210022024A0054E46B007020BC0042000727220281007010700102006E20720102000C021A041C006E20720142000C026E10730102000C026E20C600270052E268006E20C7002700220B410054E26B0070208F002B0013020A0012546E5494002B2412126E2093002B006E2090007B0012047210820101000A0535544700220C400054E56B00702089005C00080811007220810141000C0507591F09800022055B0007E6020A10007608EF000500620A90007220810141000C0D1F0D80006E205D01DA007220810141000C0A1F0A76006E208D00AC00140ACCCCCCFF6E208E00AC00000052EA6300711028000A000C0A6E208A00AC006E208C005C006E209000CB00D804040128B6020A100071203401A0000A043D043D00220581007010700105006E20720105000C051A081D006E20720185000C0554E860006E20720185000C051A0813006E20720185000C05D80804FF7220810181000C081F0880006E20720185000C056E10730105000C057110380005000C056E20C60057006E2091004B000C051F0540006E208B0025006E207E00BF000E0000001100060006000000516B0000A200000071203401DE000A0022013F0054B26B0070207D0021001252120313040A006E528600413212126E2085002100130211006E208300210022024A0054B36B007020BC003200072A220281007010700102006E207201E2000C021A031D006E20720132000C0254B360006E20720132000C021A0313006E20720132000C023900040001F3280201036E20710132000C026E10730102000C027110380002000C026E20C6002A0052B268006E20C7002A002202460054B36B007020A400320013031900130523006E54AA003254020310006E20A700320000006E20A800F2003900040001F4280201046E20AB0042006E10A60002000C0452B56400620600006E302C0054066E10A50002000C0452B56500620600006E302C00540622054D0007B601D907E801F77606D00005006E20A90052006E207E00A1006E207E0021006E207E001C000E0009000100080000008C6B00003800000022002F00528361005284620014060801800212E712E112E212257608460000005B807B0054807B00130133005901070054807B00528161005901080054807B00528162005901090054806B001F0004006E10010000000C005B807100548071005481750054827B007230470010020E0005000100040000009B6B0000170000005440750054416F006E206F00100022001800701033000000220163007020FF0041001602F4016E40360010320E0000000C00050005000000A86B000091000000220081007010700100001A019A026E20720110000C006E20710190000C001A0101006E20720110000C006E207201A0000C006E20720110000C006E207201B0000C006E10730100000C001A01080171203E000100220089001A0118006E206D011B000C0171107A0101000C0170208001100022013F0054726B0070207D00210022023E0012F312E470307A003204127312246E547C00323412136E2085003100527454006E20820041006E20840021002204470054756B007030AC0054036E20B00024006E10AD0004000C05620600006E302C0035062203350054756B001406090009017040540053066E20550063006E20AF003400712034019A000A056E20B2005400220551007040DA0075946E20B10054006E207E0041006E207E0018000E0000000C00050005000100E76B0000670000002200490054716B007020B300100022010D00140262FFFEFE2410900002000C021403A00001012410900003000C031204234590002430950032050C0252736A00527569001406FF0000FF2430900036050C0370302700210300006E10B50000000C026E202D0012006E10B60000000C026E202D001200280B0D021A03080171106F0102000C0571203E0053006E20BA00A000527268006E20BB00200013020A0012536E53B9002043713033019A0B0A026E20B70020002202650070500301729A6E20B80020006E207E0008000E0000002D0000000E00010001017C3C0600030005000000196C00001D00000022004A0054316B007020BC0010007110380005000C016E20C6001000523168006E20C700100013010A0012526E52C30010126E207E0004000E00000006000300050000002C6C00001A0000002200320054316B0070204B0010001A01AA021A02B5026E404D00502112016E204F00100012526E52520010126E207E0004000E0003000300030000003F6C0000040000007030240110020E001400030006000000496C00001002000008001100080612001201080713001202012801120801130021633538A8011203460406081A055A016E20670154000A091A0A00003809090012136E306C01540A0C0401392802013907711A0335006E20670134000A053805080054016C006E306C01340A0C041A0359016E206D0134000C0B1205460C0B0571103A000C000A0C390C1400460C0B051A0D19006E206A01DC000A0C380C03002808910A080201AC012A01C2074C2823460C0B05711063010C000A0C220D8100701070010D00460E0B056E207201ED000C0D6E2072013D000C0D6E1073010D000C0D6E306C01D40A0C04D8020201012A01C2074C6E206D013C000C0D46030D056E10690103000A04123E122F131001002C043201000029009A001A042B006E20680143000A033803F8FF01F3290090001A0432006E20680143000A033803EDFF1273290085001A040F016E20680143000A033803E2FF13030800290079001A0413016E20680143000A033803D6FF13030D0029006D001A042F006E20680143000A033803CAFF13030B00290061001A0412016E20680143000A033803BEFF13030C0028551A042D006E20680143000A033803B3FF01E3284B1A041B016E20680143000A033803A9FF124328411A0434006E20680143000A0338039FFF1303090028361A0459006E20680143000A03380394FF1253282C1A0415016E20680143000A0338038AFF0203100028211A045A006E20680143000A0338037FFF126328171A0421016E20680143000A03380375FF0153280D1A042C006E20680143000A0338036BFF13030A00280212F32B03CE00000029008B00D80A0A0146030D1070301C01100329008200D80A0A0146030D1070301B01100329007900D80A0A0146030D1070300901100329007000D80A0A0146030D1046040D0F704007011043286546030D1070400C011093D80A0A01285D46030D1046040D0F705414011032285546030D1070590B011032284F21D333E30D0046030D0F46040D107110630104000A0470541201103221D333F33F0046030D10705512011032283846030D10704013011032283246030D1070301B01100346030D1046040D0F705419011032282546030D10705908011032281F46030D10704006011032281946030D1046040D0F7110630104000A0446050D0E7110630105000A05760615010000280746030D1070591A0110320000D808080101A2290059FE0E0000020E006C3E2D8C74A7A395E773F1C85B9ABFD8F73B30DDCD872DDEF949BFEBDEA6A6F98E1AF1041E21DD067D177719EDA6462EC307755F5213477792000000880000007E00000073000000690000005E000000540000004A0000003F00000033000000270000001B000000100000000500000000010E00000000008800000076000000700000006A0000005D00000057000000400000003A000000320000002A00000020000000170000000E0000000500000003000100020000001D6D00000C000000542075003800090054207100542175007220480010000E000300020002000000246D00000A0000005410750038000700541075006E20720020000E0003000200020000002D6D0000070000006200870072201F0020000A000F0000000A00030006000000346D000029000000620083007110490100000C006E30390180090A0012F1331804006A00850012D1331804006A00840063018500390107003B0803002803019528030109019562018300120412060773018277060A0101000F0500000500020003000000656D00000C0000006200870071106E0104000C0112027230210010020A000F0005000300030001006C6D00000D0000006200870071106E0103000C017230210010040A000F000D000F040000000000000A0001000101780B04000200030000007C6D0000080000006200870012017230210030010A000F000400030003000000836D000007000000620087007230210020030A000F00000002000100020000008C6D00000E00000062008600390009002200670070202A011000690086006200860011000300020002000000946D00000C000000380209002200670070202A0110006900860062008600110003000200030000009E6D00000E00000062008600390009002200670070302B011002690086006200860011000400030003000000A86D00000C000000380309002200670070302B011002690086006200860011000400020002000000B56D0000120000006E20300132000A00390005001600000010006E20430132000B007120620110000B0010000600040002000000BE6D0000100000006E20300132000A003900030010046E20430132000B007120620110000B0010000400020003000000C96D0000080000006200870012017230220030010A000F000400030003000000D06D000007000000620087007230220020030A000F0000000900020006000000D96D00001B0000006300850038001600620083007110490100000C006E20400180000A0462018300120512060773018277060A0101000F04077312070F07000005000200030001000B6E00000E00000012006201870071106E0104000C027230230021000A000F000D010F00010000000A0001000101780C0400020003000000196E0000080000006200870012017230230030010A000F000400030003000000206E000007000000620087007230230020030A000F0000000900020006000000296E00001E00000063008500390008003C08030028041A0000001100620083007110490100000C006E20450180000C0662018300120412050773018277060A010100110605000200030001004C6E00000F0000001A0000006201870071106E0104000C027230250021000C0011000D0111000000020000000A0001000101780D04000200030000005A6E000009000000620087001A0100007230250030010C00110000000400030003000000616E000007000000620087007230250020030C001100000008000300020000006A6E000061000000220081007010700100006E20720160000C001A015B016E20720110000C006E10730100000C006E20300105000A00380049002200880070107E010000220281007010700102006E20720162000C026E20720112000C016E10730101000C016E20410115000A013A012C00120235122900220381007010700103006E20720163000C031A0450016E20720143000C036E20710123000C031A0458016E20720143000C036E10730103000C036E20460135000C036E207F013000D802020128D81100110700000400030003000000A26E0000080000000000620087007230260020030C0011000500020004000000B36E00000900000062008700160100007240240040210B00100000000600040004000000BA6E000007000000620087007240240030540B00100000000500020003000000C36E0000260000007010640103006E100D0004000C00220181007010700101006E100E0004000C026E20720121000C011A025C016E20720121000C016E10730101000C0112026E30100010020C00690087000E000500030003000000CF6E00000F0000007010640102006E100D0003000C0012016E30100040010C00690087000E0000000A00030006000000D96E000014000000620083007110490100000C006E304D018009620183001204120607730182019577060A0101000E000A00030006000000FE6E000014000000620083007110490100000C006E3051018009620183001205120607730182019477060A0101000E000A00030006000000226F000014000000620083007110490100000C006E3054018009620183001204120507730182079677060A0101000E000200010001000000476F00000E000000620087007210200000000C007210170000000C007210160000000E000A000300030000004D6F0000A0000000120062018700220281007010700102006E20720182000C021A035B016E20720132000C026E10730102000C0272201F0021000A0138011700220181007010700101006E20720181000C016E20720131000C016E10730101000C016E20410117000A00220181007010700101006E20720181000C016E20720131000C016E10730101000C017210850109000A026E305201170212017210840109000C0272107C0102000A031A0458011A0550013803280072107D0102000C031F038000220681007010700106006E20720186000C066E20720156000C056E20710115000C056E20720145000C046E10730104000C046E30550147030000D801010128D135012100220281007010700102006E20720182000C026E20720152000C026E20710112000C026E20720142000C026E10730102000C026E2048012700D801010128E00E000400030003000000896F00000F0000000000620087007210200000000C0072301D0020030C007210160000000E00000007000200020000009B6F00008C000000220081007010700100006E20720160000C001A015B016E20720110000C006E10730100000C006E20300105000A0038006700220081007010700100006E20720160000C006E20720110000C006E10730100000C006E20410105000A003A005000620287007210200002000C02220381007010700103006E20720163000C036E20720113000C016E10730101000C0172201E0012000C01721016000100120135012F00620287007210200002000C02220381007010700103006E20720163000C031A0450016E20720143000C036E20710113000C031A0458016E20720143000C036E10730103000C0372201E0032000C02721016000200D801010128D2620087007210200000000C0072201E0060000C007210160000000E000500030003000000C26F000012000000620087007210200000000C0071106E0103000C017230180010040C007210160000000E000400030003000000CE6F00000E000000620087007210200000000C007230180020030C007210160000000E000600040004000000D86F0000080000007120610154000B006E40530132100E000400030003000000E26F00000E000000620087007210200000000C007230190020030C007210160000000E000500030003000000EC6F000012000000620087007210200000000C0071106E0103000C0172301A0010040C007210160000000E000400030003000000F86F00000E000000620087007210200000000C0072301A0020030C007210160000000E000500040004000000027000000E000000620087007210200000000C0072401B0020430C007210160000000E0005000300030000000C70000012000000620087007210200000000C0071106E0103000C0172301C0010040C007210160000000E000400030003000000187000000E000000620087007210200000000C0072301C0020030C007210160000000E00010001000100000000000000040000007010640100000E00010001000100000000000000040000007010640100000E00010001000100000000000000040000007010640100000E00010001000100000000000000040000007010640100000E00010001000100000000000000040000007010640100000E00010001000100000000000000040000007010640100000E00010001000100000000000000040000007010640100000E0009000E5A0006000E000F01D7040E3D00EC0405AD05000000000E00F50403DC04DC03E3050EB4F001380F00EE0401DC040E00F10401DC040E00890503AD0500000E008B0501B7050E6BB4B41F5C8700A50502AD05000E00A70501B7050E780300EA030B5A967800C40505AD05000000000ED200C80501B7050E974B011E0F964C011E0F963D00EE0503AD0500000E00F1050400DD04B404E1030E0403AF04359F01F0E100F70501000E0401AE04359F0100950601AE050E00980602B705D7030E01140F0300E203323C5B4C00A90602AE05000E00AD06029A03D5050E01210F03009E0403C35F027B1D05001E0300A1037E69010503019E04031F05014D03009E0403013C0FB56900BE0601AE050E00C106029A03D5050E01140F0300E203325A00890605AD05000000000E008C0601CE050E960300EC02069603019F033B4B01180F4B963C0303489201A53C020B863D5A3C960304F703403C3C3D0215A4AC694B03029A0307963C05021E3D00E80601AE050E00EB0602B705D7030E01140F0300E203323C5B4C00FC0602AE05000E00FE06029A03D5050EA50300A0058101013C0FB46900850701AE050E008807029A03D5050E01140F0300E203325A00E20604AD050000000E00E50601CE050E970300EC02069603019F033B020B863D5A3C960302F703404B3C3DADAD694B03039A0307963C05031E3D00A30704AD050000000E00A60702FD02EC030E87887900C00707AD050000000000000E00C20701B7050E01320FF000F50705AD05000000000ED200FB0701B7050E4B0300E3058F012D2D6901200F1F7801200F00A40101AD050E00A60101CE050E968700C40101AD050E00CA0101B7050EA54BB4B488B4B61C1F008E0201AD050E00900201CE050E878796E100980201CE050EE1B4B400960201AD050E00A80201AD050E00AA0201CE050E87B49600CB02000E00CE02000E4B0300E702052D6987787900FD0201AD050E5A008203000E78F100A80302CE059A040E02249502771D967901110F011110F002661D870300C30403870303C40403967AE5785C1B2102691D050005038787696900A10301AD050E5A6900C50404AD050000000E00C704028803FA020E786AE12DE32D0110110045000E00E102000E780401F60278E3019603028D0385014B6A0303F7027F690305E60284013C6A040692048C01FA0101120F0308CB047F4B0409F40278E30169030AB30484013C69690307E70284013C79050705080509050A02771D05010502050305050506272D00A103000E004501DF050E00A708000E00AC0801DC030E00B00801DC030E007F018A030E024C7787878787874B4B3C4C4B4B5A5A4B8787878769696902204A2D2D789678785A7A7878786A01110F5A0302B003165A5A9978A5FF0305F2020387887887030690039001A501101096AC5A0308D1053387FF030AF302036969B6012A0B7D3C5A7A5A030B95054B5A5A5A5A5A030CD404435A3C021586785A985A030EB005444B5B5A030DAF054B5A5A5A5A0303D304435A3E5A0307A6054B5A4B3C3C5A5A3C5C79D2D269E178786B5A0304CC0444695C690309F503435B5A030FDB03373C010305020311B003163C5A5A8E90010505030313D304433C0302F403435B5A03038303373C010305020310F403433C5A5A8F010405050312F202035A78696A793C3C5A5A78783C3C5B3C00810503FB03A503A4030E780300FB0237690301F8033F5A3C5A4B785A0210863C009D0503FB03A403B5050E780300FB0237690301F8033F5A3C4B5A785A8E3C00B10504FB03A503A403A9050E870307FB0237690300F8033F5A3C5A4C870305AB0381014B0301F0038F012D011A0F5A2E011A0F5A1F1E0304AA038F010104050A0306A503030211683C008C0802FB03AA050E780300AC054B5A785A5A5A5A3C009D0704FB03A503A403A9050E7803008103383C5A1E9678903C00D80703FB03AA05A2030E780306FA033F5B8703078403403C5A4C7803088503403C3C3C965A2E780302AC054B5A011C0F5A5A4B5B2D3C011C1101070502050803038503400304AC054B0211683C3C3C00C902018A030E4B960300D60319020C8605001E96A55A5B00FE0504FB03A503A40395040E780300FC0340690301F8033F5B870307FB02374B03029E040301350F4B3C5A5A0106050C050D050E03069504030308A40381010309A5030302C700683C3C00D50603FB03A503A4030E780300FC0340690301F8033F5B790302FB02374B0303A20581010130104B3C5A5A0236863C3C00B20704FB03A503A403FE030E011310040180048B01F801870307AC054B01160F5B78030BC10442694B3D01010304DC03036978030C92024101020308AB038101780309C20481018C0305AC0328B496691E963C02713B050505080509050C02123B0504690304E303032D01320F973C00DA0405FB03A503A403970494040E4B0300880403780301FC0340784B5B87030AAC054B012F0F5B780302DC0447785A1E3C87B4B4020EC23C3D3C008C03000E020C01120E69696AA59600FA02000E795A0300D60319AE00D90504FB03A503A403FE030E012A0FF3040080048B01F801780301FD0340780302F9033F5A4B5A3D7803049A05483C97A50303DF02363D3C78020B863C3C00AB0404FB03A503A403A7050E780300A8054A020D01250E0301FC020E1F787A1B1E0302A1037D9805023C5A69780211863C00970802FB03AA050E780300AC054B785A693C009F0802FB03AA050E780300D10533784B4B3C004503DF05E005E1050E00D40302FF03FC030E5A0301A505032E0307810440010505130301FC03400302A505030308DC03033C1F0303A9058F012D0304A6038101A51E662205030309A9058F011E882D4C6B030BA00595010114140106030AA50303027B1D050A69030CA5030301170F5E05040302A50303030AA50503030CA60381014B030DA1059501023101AD010E2D027B772D5A027A2C2D5A027A2C2D78027A1D5A2D027B1D78195A02791D3CB43C027A685A027B1D5A78027B1D5A195A1901110F195A02621D0509050B050C050D02D100590508050A0302A5050300BA08000E4B7900B40801CE050E4B5B00DA0301F3030E003303A803A903F8020EA50300FA028F013C2E3C2E962F05090305F8028F010106050705080302A903030303A80381013C00CD0201D3050E00E40202D30593030EB41E0300A1037900C50201D3050E00D80202D30593030E005E018A030E4B79006A028A03AE030E2D790076028A03B7040E4B79008401038A03B704AE030E2D7900F00101D3050E693C00FB0102D30594030E691E008F0201D3050E00980202D30595030E002A02A803A9030E4BA50304DC03030106050705080302A903030303A80381013C1F0502050305040607060801010507060300CA0101D3050EC31E0301A1037900C00101D3050E00D60102D30596030E004302A803A9030E7C37A50306A00581010106050705080302A903030303A80381013C009A0101D3050ED21E0301A1037900910101D3050E00A60102D30598030E00B50302F303000E040792038D01FD0101190F5A0400DE048901F50101150F0301A305032D01010302DC03032D01240D3F05021F0500050100A70302F303000E040392038D01FD011E00AA0201D3050E00B30202D30597030E004B018A030E3C9601120D7B0052028A03B7040E3CB7002503A803A903FA020E9601070507050805090302A903030303A80381010305FA028F013C001B03A803A903CB050E9601070507050805090302A903030303A80381010304CB05033C002003A803A903A0050E9601070507050805090302A903030303A80381010306A00581013C00E103000ED2008F0302F303000E0409CB058D01FD011E0300A30503011B1001151001180F1E0301DC030301140F0303DE028101011C0F010105032D1E2E011C0C3F00820302F303000E0403CB058D01FD011ED600C80301F3030E01191001150F0300A305032D011E0F01010301DC03032D012A0D4005000501D200F70202D405D3050E01110F00EF0202D405D3050ED200850202D405D3050E7800A00202D405D3050ED200E60102D405D3050E01110F00DE0102D405D3050ED200BB0202D405D3050ED200B60102D405D3050E01110F00AE0102D405D3050ED20000000100000045000000010000002700000001000000330000000100000028000000010000000800000001000000380000000100000029000000010000007F000000010000002A00000001000000030000000100000080000000020000008000000003000000020001002300000002000000800001000100000002000000010000002B00000002000000800002000200000080008000010000000000000002000000800003000100000076000000020000007600080001000000160000000200000080008C000200000080008E00030000008F0002000200000003000000070076000200000001000000660000000100000007000000020000000700800003000000070080008E0000000200000007008E00010000007E000000020000007E009300020000007600760002000000800092000100000093000000010000000100000002000000020002000400000002000200020002000700000002000200020002000200020002000000020000000200120002000000020080000200000002008E0002000000070002000600000007000200800002008E00800003000000070002008A0000000300000007004A004A0000000200000009000200010000000A000000010000000D000000010000000F0000000100000013000000020000001300020001000000170000000100000019000000010000001E0000000100000021000000020000002B002C00020000002B008E00010000002C00000001000000340000000400000034002B00020003000200000039008E00010000003C000000030000003F00020080000000040000003F00020080000200050000003F0002008000020002000000040000003F00020080008000040000003F00020080008E00020000003F008000030000003F00800080000000030000003F0080008E000000010000004600000003000000460002008E000000010000004800000001000000550000000200000055003A0001000000590000000200000059003A00050000006600020036008000020000000300000066000200800000000500000066000200800002004A0000000400000066003600800002000400000066003700800002000300000066004700020000000700000066004A0080008000020041004000000002000000660080000400000066008000020049000500000066008E003F004A00800000000500000066008E00800002003600000003000000660094003F00000003000000800002000200000003000000800002008000000003000000800002008E0000000300000080008000800000000100000086000000010000008E00000001000000910000000200000094003F000200000095009000020000002B002600020000007F00030000000120000220E296B3000220E296BD001122203E3C2F626F64793E3C2F68746D6C3E000A22206865696768743D220009222077696474683D22000723314332363244000723316235653230000723323232443338000723324633443443000723333263623030000723343163333030000723376630303030000723383043424334000723383243414644000923444431343143323200092345453143324133350007234646464646460002273E000128000328295600032A3E3B00052A3E3B295600012C00072D5B302D395D2A000130000B303132333435363738392D00013A000F3A203C666F6E7420636F6C6F723D2700053A204F464600043A204F4E00073C2F666F6E743E00083C636C696E69743E00413C68746D6C3E3C686561643E3C2F686561643E3C626F6479207374796C653D226D617267696E3A20303B2070616464696E673A2030223E3C696D67207372633D2200063C696E69743E00023E3B00033E3B2900043E3B295600084170705468656D65000942544E5F434F4C4F52000642746E4F4646000542746E4F4E0006427574746F6E000A427574746F6E4C696E6B000B427574746F6E4F6E4F6666000643616E63656C000843617465676F7279000A43617465676F7279424700074368616E6765730008436865636B426F78000D436865636B426F78436F6C6F720008436F6C6C61707365000C436F6C6C617073654164645F000A4372656174654D656E75000144000C44454641554C545F424F4C44001544454641554C545F424F4F4C45414E5F56414C5545001444454641554C545F444F55424C455F56414C5545001344454641554C545F464C4F41545F56414C5545001144454641554C545F494E545F56414C5545001244454641554C545F4C4F4E475F56414C5545001444454641554C545F535452494E475F56414C55450002444A0002444C0003444C4400014600044649464C00064649545F58590002464C0003464C46000B46696C7465724172726179000E476574466561747572654C6973740010484944452F4B494C4C2028486F6C6429000149000A49434F4E5F414C504841000949434F4E5F53495A45000249490004494A29560002494C0003494C490003494C4C000449636F6E002E49636F6E2068696464656E2E2052656D656D626572207468652068696464656E2069636F6E20706F736974696F6E000F49636F6E57656256696577446174610004496E6974000C496E707574206E756D626572000A496E70757420746578740008496E7075744E756D0009496E70757454657874000A496E70757456616C756500014A00024A4400024A4C00034A4C4A00014C00064C454E47544800034C474C00024C4900024C4C00034C4C4600034C4C4900044C4C494900034C4C4A00034C4C4C00044C4C4C4900044C4C4C5A00034C4C5A00164C616E64726F69642F6170702F41637469766974793B00214C616E64726F69642F6170702F416C6572744469616C6F67244275696C6465723B00194C616E64726F69642F6170702F416C6572744469616C6F673B00194C616E64726F69642F636F6E74656E742F436F6E746578743B00314C616E64726F69642F636F6E74656E742F4469616C6F67496E74657266616365244F6E436C69636B4C697374656E65723B00214C616E64726F69642F636F6E74656E742F4469616C6F67496E746572666163653B00184C616E64726F69642F636F6E74656E742F496E74656E743B002A4C616E64726F69642F636F6E74656E742F536861726564507265666572656E63657324456469746F723B00234C616E64726F69642F636F6E74656E742F536861726564507265666572656E6365733B00244C616E64726F69642F636F6E74656E742F7265732F436F6C6F7253746174654C6973743B001F4C616E64726F69642F636F6E74656E742F7265732F5265736F75726365733B00194C616E64726F69642F67726170686963732F4269746D61703B00204C616E64726F69642F67726170686963732F4269746D6170466163746F72793B00184C616E64726F69642F67726170686963732F436F6C6F723B00224C616E64726F69642F67726170686963732F506F7274657244756666244D6F64653B001B4C616E64726F69642F67726170686963732F54797065666163653B00244C616E64726F69642F67726170686963732F6472617761626C652F4472617761626C653B002C4C616E64726F69642F67726170686963732F6472617761626C652F4772616469656E744472617761626C653B00114C616E64726F69642F6E65742F5572693B00134C616E64726F69642F6F732F42756E646C653B00144C616E64726F69642F6F732F48616E646C65723B00134C616E64726F69642F6F732F4C6F6F7065723B00174C616E64726F69642F746578742F4564697461626C653B00134C616E64726F69642F746578742F48746D6C3B00274C616E64726F69642F746578742F496E70757446696C746572244C656E67746846696C7465723B00164C616E64726F69642F746578742F5370616E6E65643B00234C616E64726F69642F746578742F546578745574696C73245472756E6361746541743B00184C616E64726F69642F746578742F546578745574696C733B00274C616E64726F69642F746578742F6D6574686F642F4469676974734B65794C697374656E65723B00214C616E64726F69642F746578742F6D6574686F642F4B65794C697374656E65723B00154C616E64726F69642F7574696C2F4261736536343B001D4C616E64726F69642F7574696C2F446973706C61794D6574726963733B00124C616E64726F69642F7574696C2F4C6F673B00194C616E64726F69642F7574696C2F547970656456616C75653B001A4C616E64726F69642F766965772F4D6F74696F6E4576656E743B00234C616E64726F69642F766965772F56696577244F6E436C69636B4C697374656E65723B00294C616E64726F69642F766965772F56696577244F6E466F6375734368616E67654C697374656E65723B00274C616E64726F69642F766965772F56696577244F6E4C6F6E67436C69636B4C697374656E65723B00234C616E64726F69642F766965772F56696577244F6E546F7563684C697374656E65723B00134C616E64726F69642F766965772F566965773B00254C616E64726F69642F766965772F5669657747726F7570244C61796F7574506172616D733B002B4C616E64726F69642F766965772F5669657747726F7570244D617267696E4C61796F7574506172616D733B00154C616E64726F69642F766965772F57696E646F773B00294C616E64726F69642F766965772F57696E646F774D616E61676572244C61796F7574506172616D733B001C4C616E64726F69642F766965772F57696E646F774D616E616765723B002D4C616E64726F69642F766965772F696E7075746D6574686F642F496E7075744D6574686F644D616E616765723B00184C616E64726F69642F7765626B69742F576562566965773B00334C616E64726F69642F7769646765742F4164617074657256696577244F6E4974656D53656C65637465644C697374656E65723B001C4C616E64726F69642F7769646765742F41646170746572566965773B001C4C616E64726F69642F7769646765742F41646170746572566965773C001F4C616E64726F69642F7769646765742F41646170746572566965773C2A3E3B001D4C616E64726F69642F7769646765742F4172726179416461707465723B00174C616E64726F69642F7769646765742F427574746F6E3B00194C616E64726F69642F7769646765742F436865636B426F783B00374C616E64726F69642F7769646765742F436F6D706F756E64427574746F6E244F6E436865636B65644368616E67654C697374656E65723B001F4C616E64726F69642F7769646765742F436F6D706F756E64427574746F6E3B00194C616E64726F69642F7769646765742F45646974546578743B001C4C616E64726F69642F7769646765742F4672616D654C61796F75743B00244C616E64726F69642F7769646765742F496D61676556696577245363616C65547970653B001A4C616E64726F69642F7769646765742F496D616765566965773B002A4C616E64726F69642F7769646765742F4C696E6561724C61796F7574244C61796F7574506172616D733B001D4C616E64726F69642F7769646765742F4C696E6561724C61796F75743B001C4C616E64726F69642F7769646765742F526164696F427574746F6E3B001B4C616E64726F69642F7769646765742F526164696F47726F75703B002C4C616E64726F69642F7769646765742F52656C61746976654C61796F7574244C61796F7574506172616D733B001F4C616E64726F69642F7769646765742F52656C61746976654C61796F75743B001B4C616E64726F69642F7769646765742F5363726F6C6C566965773B00304C616E64726F69642F7769646765742F5365656B426172244F6E5365656B4261724368616E67654C697374656E65723B00184C616E64726F69642F7769646765742F5365656B4261723B00184C616E64726F69642F7769646765742F5370696E6E65723B001F4C616E64726F69642F7769646765742F5370696E6E6572416461707465723B00174C616E64726F69642F7769646765742F5377697463683B00194C616E64726F69642F7769646765742F54657874566965773B00164C616E64726F69642F7769646765742F546F6173743B00224C636F6D2F616E64726F69642F737570706F72742F4D61696E41637469766974793B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431303B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431313B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431323B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431333B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431343B001F4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313524313B001F4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313524323B001F4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313524333B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431353B001F4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313624313B001F4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313624323B001F4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313624333B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431363B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431373B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431383B001D4C636F6D2F616E64726F69642F737570706F72742F4D656E752431393B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524313B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524323B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524333B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524343B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524353B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524363B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524373B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524383B001C4C636F6D2F616E64726F69642F737570706F72742F4D656E7524393B001A4C636F6D2F616E64726F69642F737570706F72742F4D656E753B00214C636F6D2F616E64726F69642F737570706F72742F507265666572656E6365733B001D4C636F6D2F616E64726F69642F737570706F72742F5224636F6C6F723B00204C636F6D2F616E64726F69642F737570706F72742F52246472617761626C653B001E4C636F6D2F616E64726F69642F737570706F72742F52246C61796F75743B001E4C636F6D2F616E64726F69642F737570706F72742F52246D69706D61703B001E4C636F6D2F616E64726F69642F737570706F72742F5224737472696E673B001D4C636F6D2F616E64726F69642F737570706F72742F52247374796C653B00174C636F6D2F616E64726F69642F737570706F72742F523B00224C64616C76696B2F616E6E6F746174696F6E2F456E636C6F73696E67436C6173733B00234C64616C76696B2F616E6E6F746174696F6E2F456E636C6F73696E674D6574686F643B001E4C64616C76696B2F616E6E6F746174696F6E2F496E6E6572436C6173733B00214C64616C76696B2F616E6E6F746174696F6E2F4D656D626572436C61737365733B00244C64616C76696B2F616E6E6F746174696F6E2F4D6574686F64506172616D65746572733B001D4C64616C76696B2F616E6E6F746174696F6E2F5369676E61747572653B00154C6A6176612F696F2F5072696E7453747265616D3B00184C6A6176612F6C616E672F4368617253657175656E63653B00114C6A6176612F6C616E672F436C6173733B00144C6A6176612F6C616E672F436C6173733C2A3E3B001E4C6A6176612F6C616E672F436C61737343617374457863657074696F6E3B00124C6A6176612F6C616E672F446F75626C653B00214C6A6176612F6C616E672F496C6C6567616C5374617465457863657074696F6E3B00134C6A6176612F6C616E672F496E74656765723B00204C6A6176612F6C616E672F4E756C6C506F696E746572457863657074696F6E3B00214C6A6176612F6C616E672F4E756D626572466F726D6174457863657074696F6E3B00124C6A6176612F6C616E672F4F626A6563743B00144C6A6176612F6C616E672F52756E6E61626C653B00124C6A6176612F6C616E672F537472696E673B00194C6A6176612F6C616E672F537472696E674275696C6465723B00124C6A6176612F6C616E672F53797374656D3B00194C6A6176612F6C616E672F7265666C6563742F4669656C643B001A4C6A6176612F6C616E672F7265666C6563742F4D6574686F643B00124C6A6176612F7574696C2F4172726179733B00164C6A6176612F7574696C2F436F6C6C656374696F6E3B00144C6A6176612F7574696C2F4974657261746F723B00194C6A6176612F7574696C2F4C696E6B6564486173685365743B002D4C6A6176612F7574696C2F4C696E6B6564486173685365743C4C6A6176612F6C616E672F537472696E673B3E3B00164C6A6176612F7574696C2F4C696E6B65644C6973743B00104C6A6176612F7574696C2F4C6973743B00244C6A6176612F7574696C2F4C6973743C4C6A6176612F6C616E672F537472696E673B3E3B000F4C6A6176612F7574696C2F4D61703B00134C6A6176612F7574696C2F4D61703C2A2A3E3B000F4C6A6176612F7574696C2F5365743B000F4C6A6176612F7574696C2F5365743C00234C6A6176612F7574696C2F5365743C4C6A6176612F6C616E672F537472696E673B3E3B00074D415251554545000D4D454E555F42475F434F4C4F52000B4D454E555F434F524E455200154D454E555F464541545552455F42475F434F4C4F52000B4D454E555F484549474854000A4D454E555F574944544800084D494E494D495A4500114D61696E41637469766974792E6A617661000B4D61782076616C75653A20000B4D656E75206B696C6C656400094D656E752E6A61766100084D6F645F4D656E75000E4E756D626572547874436F6C6F7200024F4B00064F6E4F66665F0005504F535F580005504F535F590010507265666572656E6365732E6A617661000B526164696F427574746F6E000A526164696F436F6C6F720006526164696F6F000C526963685465787456696577000B526963685765625669657700085352435F41544F5000075365656B426172000C5365656B426172436F6C6F7200145365656B42617250726F6772657373436F6C6F72001853657457696E646F774D616E616765724163746976697479000C53657474696E67734C697374000853686F774D656E7500075370696E6E657200065377697463680003544147000A544558545F434F4C4F52000C544558545F434F4C4F525F32000854657874566965770006546F67676C650009546F67676C654F46460008546F67676C654F4E000156000256460002564900035649490005564949494900085649494949494949000356494C000356495A0002564C0003564C440003564C460003564C490004564C49490004564C494C0005564C494C490006564C494C49490006564C494C494C0007564C494C495A4C0005564C494C4C0006564C494C4C490005564C494C5A0004564C495A0003564C4A0003564C4C0004564C4C490005564C4C494A0005564C4C494C0004564C4C4C0005564C4C4C490008564C4C4C4C494C4C0004564C4C5A0003564C5A0006564C5A4C494C0006564C5A4C4C4C0002565A000B576562546578745669657700015A00025A4900035A495A00025A4C00045A4C495A00035A4C4A00035A4C4C00035A4C5A00015B00025B4200025B49001B5B4C616E64726F69642F746578742F496E70757446696C7465723B00125B4C6A6176612F6C616E672F436C6173733B00135B4C6A6176612F6C616E672F4F626A6563743B00135B4C6A6176612F6C616E672F537472696E673B00035B5B4900015D00015F00055F5472756500075F6C656E677468000C5F707265666572656E63657300066156616C756500026161000A61636365737324303030000A61636365737324313030000A61636365737324313032000A61636365737324323030000A61636365737324333030000B616363657373466C616773000A6163746976697469657300086163746976697479000D61637469766974795F6D61696E0003616464000761646452756C650007616464566965770009616C6572744E616D65001A616E64726F69642E6170702E4163746976697479546872656164001A616E64726F69642E696E74656E742E616374696F6E2E5649455700086170705F6E616D650006617070656E6400056170706C79000E6170706C7944696D656E73696F6E000F6170706C7944696D656E73696F6E3200026172000661734C69737400026174000561744F626A000462446566000F6261636B67726F756E64436F6C6F720004626F6F6C0006627574746F6E000C627574746F6E537461746573000A627574746F6E5669657700116368616E676546656174757265426F6F6C00106368616E676546656174757265496E7400136368616E676546656174757265537472696E670008636865636B426F780005636C6561720008636C6F736542746E0008636F6C6C61707365000B636F6C6C61707365537562000D636F6C6C6170736564566965770005636F6C6F72000E636F6D706F756E64427574746F6E0008636F6E7461696E730007636F6E746578740012636F6E76657274446970546F506978656C730006637265617465000763757272656E74001563757272656E74416374697669747954687265616400016400066465636F6465000F6465636F6465427974654172726179000864656656616C7565000E64656661756C74426F6F6C65616E000D64656661756C74446F75626C65000C64656661756C74466C6F6174000A64656661756C74496E74000B64656661756C744C6F6E67000D64656661756C74537472696E67000764656E7369747900066469616C6F670013646F75626C65546F5261774C6F6E67426974730002647000086472617761626C65000465646974000865646974546578740006657175616C73000265780008657870616E646564000C657870616E646564566965770008666561744E616D650007666561744E756D000766656174757265000B666561747572654C697374000B666561747572654E616D65000A666561747572654E756D000966696E616C49734F6E000D66696E616C666561744E616D65001466697273745F726164696F5F6C697374656E65720007666F724E616D650012666F726365496E7374616E74696174696F6E000866726F6D48746D6C000A67644D656E75426F647900036765740009676574416374696F6E00156765744170706C69636174696F6E436F6E74657874000D6765744261636B67726F756E64000A676574426F6F6C65616E000A6765744368696C6441740008676574436C617373000A676574436F6E7465787400106765744465636C617265644669656C6400116765744465636C617265644D6574686F640011676574446973706C61794D6574726963730008676574466C6F6174000B676574496E7374616E63650006676574496E74000F6765744C61796F7574506172616D7300076765744C6F6E67000D6765744D61696E4C6F6F70657200136765744F726465726564537472696E67536574000E6765745061636B6167654E616D65001367657450726F67726573734472617761626C65000767657452617758000767657452617759000C6765745265736F7572636573000F67657453656C65637465644974656D0014676574536861726564507265666572656E6365730009676574537472696E67000C676574537472696E67536574001067657453797374656D5365727669636500076765745465787400086765745468756D6200106765745468756D624472617761626C65000E676574546F7041637469766974790010676574547261636B4472617761626C65000D6765745669736962696C697479000967657457696E646F77001067657457696E646F774D616E61676572000767726176697479000768616E646C65720008686173466F63757300076861734E657874000868617368436F6465000668656967687400076869646542746E000169000B69635F6C61756E63686572001669635F6C61756E636865725F6261636B67726F756E64001669635F6C61756E636865725F666F726567726F756E64001169635F6C61756E636865725F726F756E64000269640003696D6D0005696E646578000C696E6465784F664368696C64000D696E697469616C546F75636858000D696E697469616C546F756368590008696E697469616C580008696E697469616C59000C696E7075745F6D6574686F640006696E74656E740006696E766F6B6500096973436865636B6564000C69734469676974734F6E6C7900076973456D707479000A6973457870616E646564000469734F6E000F697356696577436F6C6C617073656400086974657261746F7200036B6579000F6C506172616D73436C6F736542746E000E6C506172616D734869646542746E00066C61796F7574000A6C61796F75744E616D65000C6C61796F7574506172616D73000D6C61796F7574506172616D7332000E6C61796F7574506172616D734C4C00096C696E4C61796F7574000C6C696E6561724C61796F7574000D6C696E6561724C61796F75743200046C69737400066C697374465400056C6973747300056C6C42616B00086C6F616444617461000B6C6F61644C69627261727900086C6F616450726566000C6C6F616450726566426F6F6C000B6C6F616450726566496E74000E6C6F616450726566537472696E67000A6C6F6164656450726F6700106C6F6E6742697473546F446F75626C65000B6D4163746976697469657300096D436F6C6C61707365000A6D436F6C6C617073656400096D457870616E646564000E6D526F6F74436F6E7461696E657200096D53657474696E6773000E6D57696E646F774D616E6167657200086D616B655465787400036D617000076D61746368657300036D617800086D617856616C756500046D656E7500036D696E00066D69706D617000046D6F6473000B6D6F74696F6E4576656E7400046E616D6500056E616D657300046E65787400036E756D00106F6E436865636B65644368616E67656400076F6E436C69636B00086F6E43726561746500096F6E44657374726F79000D6F6E466F6375734368616E6765000E6F6E4974656D53656C6563746564000B6F6E4C6F6E67436C69636B00116F6E4E6F7468696E6753656C656374656400116F6E50726F67726573734368616E67656400146F6E5374617274547261636B696E67546F75636800136F6E53746F70547261636B696E67546F75636800076F6E546F756368000F6F6E546F7563684C697374656E657200036F7574000F6F7665726C617952657175697265640006706172656E74000A706172656E745669657700057061727365000A7061727365436F6C6F7200087061727365496E7400067061757365640008706F736974696F6E0004706F7374000B706F737444656C61796564000F707265666572656E6365734E616D65000D7072656673496E7374616E636500077072696E746C6E000A707574426F6F6C65616E0008707574466C6F61740006707574496E7400077075744C6F6E6700137075744F726465726564537472696E675365740009707574537472696E67000C707574537472696E67536574000A726164696F47726F75700009726164696F4E616D65000472617758000472617759000B72656164426F6F6C65616E000A72656164446F75626C65000972656164466C6F6174000772656164496E740008726561644C6F6E67000A72656164537472696E6700067265636F7264000E72656C61746976654C61796F7574000672656D6F7665000E72656D6F7665416C6C5669657773000A72656D6F76655669657700077265706C616365000C7265706C6163654669727374000C72657175657374466F6375730002726C000A726C73657474696E67730009726F6F744672616D65000372756E00127361766564496E7374616E6365537461746500067363726C4C4C000E7363726C4C4C457870616E64656400087363726F6C6C546F000A7363726F6C6C5669657700077365656B426172001073656C65637465644974656D566965770003736574000D73657441636365737369626C65000A73657441646170746572000A736574416C6C436170730008736574416C70686100127365744261636B67726F756E64436F6C6F720011736574427574746F6E54696E744C697374000A736574436865636B65640008736574436F6C6F72000E736574436F6C6F7246696C746572000F736574436F726E6572526164697573000773657444617461001773657444726F70446F776E566965775265736F75726365000C736574456C6C697073697A65000A73657446696C746572730008736574466C616773000C736574466F63757361626C65000A73657447726176697479000773657448696E74000E736574496D6167654269746D6170000C736574496E70757454797065000E7365744B65794C697374656E6572000F7365744C61796F7574506172616D73000A7365744D617267696E7300157365744D6172717565655265706561744C696D697400067365744D617800067365744D696E00117365744E65676174697665427574746F6E001A7365744F6E436865636B65644368616E67654C697374656E657200127365744F6E436C69636B4C697374656E657200187365744F6E466F6375734368616E67654C697374656E657200197365744F6E4974656D53656C65637465644C697374656E657200167365744F6E4C6F6E67436C69636B4C697374656E6572001A7365744F6E5365656B4261724368616E67654C697374656E657200127365744F6E546F7563684C697374656E6572000E7365744F7269656E746174696F6E000A73657450616464696E670011736574506F736974697665427574746F6E000B73657450726F6772657373000C7365745363616C6554797065000B73657453656C6563746564000C73657453656C656374696F6E000D73657453696E676C654C696E6500097365745374726F6B65000773657454657874000C73657454657874436F6C6F72000B7365745465787453697A6500087365745468656D65000B73657454696E744C69737400087365745469746C65000773657454797065000B73657454797065666163650012736574566572746963616C47726176697479000773657456696577000D7365745669736962696C697479000873657474696E6773000C73657474696E67734F70656E0011736861726564507265666572656E636573000473686F77000473697A6500077370696E6E657200087370696E6E657220000573706C6974000D73746172744163746976697479000A7374617274696D616765000C73746F70436865636B696E670003737472000873747253706C69740006737472696E67000F737472696E675365744C656E67746800057374796C6500077375624665617400087375625469746C6500057377694F6E000773776974636852000A73776974636865644F6E0004746578740009746578742F68746D6C000874657874566965770006746869732430000674686973243100057469746C6500097469746C65546578740008746F537472696E67000F746F67676C65536F6674496E7075740009746F704D617267696E0010757064617465566965774C61796F7574000375726C00057574662D38000176000A76616C24526164696F6F000A76616C24627574746F6E000C76616C24636865636B426F78000F76616C24636F6C6C61707365537562000C76616C246564697454657874000C76616C24657870616E646564000C76616C24666561744E616D65000B76616C24666561744E756D000D76616C2466696E616C49734F6E001176616C2466696E616C666561744E616D65000C76616C246D617856616C7565000776616C246D696E000E76616C24726164696F47726F7570000D76616C24726164696F4E616D65000B76616C247370696E6E6572000B76616C2473776974636852000876616C2474657874000C76616C247465787456696577000776616C2475726C000576616C7565000776616C75654F66000676616C756573000476696577000A766965774C6F616465640008766D506172616D7300057756696577000677656967687400047768617400057768657265000B7768696368427574746F6E00057769647468000477697468000C7772697465426F6F6C65616E000B7772697465446F75626C65000A7772697465466C6F617400087772697465496E74000977726974654C6F6E67000B7772697465537472696E6700017800027830000278310002783200017900017A00667E7E44387B226261636B656E64223A22646578222C22636F6D70696C6174696F6E2D6D6F6465223A226465627567222C226861732D636865636B73756D73223A747275652C226D696E2D617069223A32382C2276657273696F6E223A22382E31332E3139227D00EB0B7E7E7E7B224C636F6D2F616E64726F69642F737570706F72742F4D61696E41637469766974793B223A226362316134626130222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431303B223A2262656434663762222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431313B223A226463333663376533222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431323B223A223463353932633361222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431333B223A223136363232663031222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431343B223A223337613631666265222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313524313B223A2264363561643339222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313524323B223A226266343437313764222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313524333B223A223731616263313634222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431353B223A226530666130326332222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313624313B223A2234383331383732222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313624323B223A226431303133343431222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313624333B223A223732393463396363222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431363B223A223936653965326566222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431373B223A223838613364303365222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431383B223A226565383931323033222C224C636F6D2F616E64726F69642F737570706F72742F4D656E752431393B223A223933663065663465222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524313B223A226364343637363063222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524323B223A223364396632373531222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524333B223A226361313837633164222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524343B223A223230623961636262222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524353B223A226132303830643738222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524363B223A223339633561363434222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524373B223A223263393239623231222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524383B223A226333326531353634222C224C636F6D2F616E64726F69642F737570706F72742F4D656E7524393B223A223434313064343764222C224C636F6D2F616E64726F69642F737570706F72742F4D656E753B223A226231366261333637222C224C636F6D2F616E64726F69642F737570706F72742F507265666572656E6365733B223A226164393634346265222C224C636F6D2F616E64726F69642F737570706F72742F5224636F6C6F723B223A223930616230363438222C224C636F6D2F616E64726F69642F737570706F72742F52246472617761626C653B223A223232316434383261222C224C636F6D2F616E64726F69642F737570706F72742F52246C61796F75743B223A223961326164383034222C224C636F6D2F616E64726F69642F737570706F72742F52246D69706D61703B223A223766636136636664222C224C636F6D2F616E64726F69642F737570706F72742F5224737472696E673B223A223334383265656530222C224C636F6D2F616E64726F69642F737570706F72742F52247374796C653B223A223434376666366232222C224C636F6D2F616E64726F69642F737570706F72742F523B223A226462613261316637227D0002E296B3200002E296BD200001E29A9900027302E4021C05441080002410102410102410102410109B041C051E1E1E1E1E027401CA051C011715027001CA053A1501027102E40204009A041E027302E4021C03441080002410102410109B041C031E1E1E027001CA053A0601027302E4021C02441080002410109B041C021E1E027001CA053A0701027001CA053A0801027401CA051C051714179D17161793174E027401CA051C031714179D1717027001CA053A1901027302E4021C01441080009B041C011E027001CA051AE4027001CA053A1201027001CA051AEC027302E4021C04441080002410102410102410109B041C041E1E1E1E027001CA053A1301027001CA053A0B01027302E4021C07441080002410102410102410102410102410102410109B041C071E1E1E1E1E1E1E027001CA053A1401027001CA053A0C01027001CA053A0501027001CA053A0D01027001CA053A1801027001CA053A2801027001CA053A1A01027401CA051C08171417EB17FB17EB172517FB17EB1724027401CA051C05171417EB17FB17EB1726027102E40204199A04378601026F01CA05186E027102E40204199A04379C01027102E40204199A0437F501027102E40204199A04371702027102E40204199A0437A102027102E40204199A0437A302027201CA051C0618681869186A186B186C186D00000201CD01888004E457018180048058CF01049858000501030C9020019020019020019020019020D001808004B058D10101DC580101945A0101A85A00030101119020019020019020D401808004BC5AD50101E05A00020101149020019020D601808004DC5BD70101FC5B000601011600019020019020019020019020019020D801808004C85CD90101FC5C000301021C9020019020019020DA01808004D45EDB0101F85E0101C45F000101011F9020DD01808004D85FDE0101F45F00020101209020019020DF01808004C860E00101E86000010101229020E101808004A863E20101C46300050101239020019020019020019020019020E3018080048864E40101B46400010101289020E5018080048467E60101A06700020101299020019020E701808004F467E801019468000101012B9020E901808004D469EA0101F069000401012C9020019020019020019020EB01808004B46AEC0101DC6A00040101309020019020019020019020ED01808004BC6CEE0101E46C00070101349020019020019020019020019020019020019020EF01808004A46DF00101D86D000601013B00019020019020019020019020019020F101808004EC6EF20101A06F00010101419020F301808004E070F40101FC70000201014200019020F501808004B071F60101CC7100010101449020F701808004F472F80101907300010101459020F901808004CC74FA0101F07300010101469020FB01808004E874FC0101847500000101FD01808004D075FE0101E875000201014790200100FF01808004C076800201E476000701014910011001020102010201020190208102808004A47A820201A477000401015090200190200190200190208302808004D87A840201807B02261C0966190C0A540001000100010001000100010001000100010001000100010001000100010001000100020001000100010001000100010001000100010001000200010001000100010001000100010001008502818004A880010102B48E010102B08F010102AC90010102B89201018902000102A09301010288940101098097010502F897010102F899010102E49B010102B09F010402C4A3010102F8A5010102E4A7010102B0A801018820A07C0188208C7F018820A47F018820F4A801018820BC7E0102BC7F0102F47F01028CA901010ABC7C0102D87E0202A07E8E02800200018002000180020001800200050184A20101800200010184A3010F01BCB1010201E4B1010C000C207C1A011A011A011A011A011A011A010901090109010A010AAA02828004BCBC010182800498BD010109C8BD01010980BE010109B8BE010509A8B2010109F8B6010109B8B8011409ACB401010980B5010109ACB5010109D8B401AF0201F0BE01010188B201010184BA010101D8BB0104019CBF010101ECC10101018CB3010101B4B3010101ECB30101018CB4010101D4B501010188B6010101B8B6010101D8B6010101C0B7010101F8B701010198B8010101F8BB0101019CBC01010184B9010101C0B9010101E4B90101019CC2010501C4C4010101F8C4010101A4C5010101C4C5010101F0C5010101A4C6010101D0C6010101FCC6010101B0C701020001008801090109D602828004DCC701010001008A0109D702828004F4C701010001008B0109D8028280048CC801020001008C01090109D902828004A4C801010001008E0109DA02828004BCC801010001008F0109DB02828004D4C80100000100DC02828004ECC80101370801071F11001000040006001700375B0102640000017F640100017F01640000027F01640000037F02640000047F640100047F01640000057F01640000067F00000002000000A0A50000C0A5000002000000C9A50000D1A5000002000000DBA50000C0A5000002000000F3A50000D1A5000002000000FBA50000C0A50000020000000FA60000D1A500000200000017A60000D1A50000010000001FA600000100000030A60000020000003DA60000D1A500000100000045A600000200000055A60000D1A50000020000005CA60000D1A500000200000064A60000D1A50000020000006BA60000C0A500000200000087A60000D1A50000020000008FA60000D1A500000200000097A60000C0A5000002000000BFA60000D1A5000002000000C7A60000D1A5000002000000CFA60000D1A5000002000000D7A60000D1A5000002000000DFA60000D1A5000002000000E7A60000D1A5000002000000EFA60000D1A5000001000000F7A60000010000000EA70000020000002BA700001FA70000020000002BA7000032A70000020000002BA700003EA70000020000002BA700004AA70000020000002BA7000056A70000020000002BA7000062A70000010000006EA70000C0AC0000000000000100000000000000D0000000B4AC0000D8AC0000000000000100000000000000D4000000CCAC0000F0AC0000000000000100000000000000D6000000E4AC0000FCAC0000000000000100000000000000D8000000B4AC000018AD0000000000000300000000000000DA000000CCAC0000DB00000008AD0000DC00000010AD00002CAD0000000000000100000000000000DD00000024AD00002CAD0000000000000100000000000000DF000000E4AC00002CAD0000000000000100000000000000E100000024AD000038AD0000000000000100000000000000E3000000B4AC000044AD0000000000000100000000000000E500000024AD000044AD0000000000000100000000000000E7000000E4AC000044AD0000000000000100000000000000E900000024AD00005CAD0000000000000100000000000000EB00000050AD000068AD0000000000000100000000000000ED00000050AD000080AD0000000000000100000000000000EF00000074AD00008CAD0000000000000100000000000000F1000000B4AC000098AD0000000000000100000000000000F300000024AD000098AD0000000000000100000000000000F500000024AD000098AD0000000000000100000000000000F700000024AD000098AD0000000000000100000000000000F900000024AD000098AD0000000000000100000000000000FB00000024AD0000A4AD0000000000000000000000000000B0AD0000000000000100000000000000FF00000024AD0000BCAD00000000000001000000000000000101000024AD0000C8AD00000000000001000000000000000301000050AD00000000000000000000040000000000000031010000D4AD000032010000D4AD000036010000DCAD000037010000DCAD0000E4AD0000000000000000000000000000F0AD0000000000000000000000000000FCAD000000000000000000000000000008AE000000000000000000000000000014AE000000000000000000000000000020AE00000000000000000000000000002CAE00000000000000000000000000001100000000000000010000000000000001000000E8020000700000000200000096000000100C000003000000B3000000680E00000400000091000000CC1600000500000086010000541B0000060000002300000084270000012000008A000000E42B000003200000810000008464000001100000670000002470000002200000E8020000087400000420000025000000A0A50000002000002300000081A70000052000000800000070AC00000310000022000000B4AC0000062000002100000034AE0000001000000100000034B10000" diff --git a/app/src/main/jni/Includes/Interface.h b/app/src/main/jni/Includes/Interface.h new file mode 100644 index 0000000..624ea4c --- /dev/null +++ b/app/src/main/jni/Includes/Interface.h @@ -0,0 +1,76 @@ +#include "Dex.h" +#include + +JavaVM *antik = nullptr; +JNIEnv *antikYt = nullptr; + +namespace InterfaceMethods { + void *Icon; + void *IconWebViewData; + void *Init; + void *SettingsList; + void *GetFeatureList; + void *Changes; +} +jclass menuClass; + +static void RegisterMethods(JNIEnv *env) { + JNINativeMethod NativeMethodsClassMethods[] = { + {"Icon", "()Ljava/lang/String;", InterfaceMethods::Icon}, + {"IconWebViewData", "()Ljava/lang/String;", InterfaceMethods::IconWebViewData}, + {"Init", "(Landroid/content/Context;Landroid/widget/TextView;Landroid/widget/TextView;)V", InterfaceMethods::Init}, + {"SettingsList", "()[Ljava/lang/String;", InterfaceMethods::SettingsList}, + {"GetFeatureList", "()[Ljava/lang/String;", InterfaceMethods::GetFeatureList}, + {"Changes", "(Landroid/content/Context;ILjava/lang/String;IZLjava/lang/String;)V", InterfaceMethods::Changes}, + }; + + env->RegisterNatives(menuClass, NativeMethodsClassMethods,sizeof(NativeMethodsClassMethods) / sizeof(NativeMethodsClassMethods[0])); +} + +static jobjectArray HEX(JNIEnv* env, const std::string& hex) { + int len = hex.length() / 2; + jbyteArray arr = env->NewByteArray(len); + jbyte* buf = env->GetByteArrayElements(arr, nullptr); + for (int i = 0; i < len; i++) { + char h = hex[i * 2]; + char l = hex[i * 2 + 1]; + int hi = isdigit(h) ? h - '0' : tolower(h) - 'a' + 10; + int lo = isdigit(l) ? l - '0' : tolower(l) - 'a' + 10; + buf[i] = (jbyte)((hi << 4) | lo); + } + env->ReleaseByteArrayElements(arr, buf, 0); + jclass bbCls = env->FindClass("java/nio/ByteBuffer"); + jmethodID wrap = env->GetStaticMethodID(bbCls,"wrap","([B)Ljava/nio/ByteBuffer;"); + jobject bb = env->CallStaticObjectMethod(bbCls, wrap, arr); + return env->NewObjectArray(1, bbCls, bb); +} + +static void loadDex(JNIEnv* env, jobject context) { + jobjectArray buffers = HEX(env, hexdex); + if (!buffers) return; + jclass classLoaderClass = env->FindClass("java/lang/ClassLoader"); + jmethodID getSystemClassLoader = env->GetStaticMethodID(classLoaderClass,"getSystemClassLoader","()Ljava/lang/ClassLoader;"); + jobject parentCl = env->CallStaticObjectMethod(classLoaderClass, getSystemClassLoader); + jclass imCls = env->FindClass("dalvik/system/InMemoryDexClassLoader"); + jmethodID ctor = env->GetMethodID(imCls,"","([Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); + jobject dexLoader = env->NewObject(imCls, ctor, buffers, parentCl); + + jmethodID loadClass = env->GetMethodID(imCls,"loadClass","(Ljava/lang/String;)Ljava/lang/Class;"); + jstring clsName = env->NewStringUTF("com.android.support.Menu"); + menuClass = (jclass) env->CallObjectMethod(dexLoader, loadClass, clsName); + if (!menuClass) return; + menuClass = (jclass) env->NewGlobalRef(menuClass); + RegisterMethods(env); + jmethodID antikMethod = env->GetStaticMethodID(menuClass,"CreateMenu","(Landroid/content/Context;)V"); + if (!antikMethod) return; + env->CallStaticVoidMethod(menuClass, antikMethod, context); +} + +void binJava() { + if (antik->AttachCurrentThread(&antikYt, nullptr) != JNI_OK) return; + jclass atCls = antikYt->FindClass("android/app/ActivityThread"); + jmethodID curApp = antikYt->GetStaticMethodID(atCls,"currentApplication","()Landroid/app/Application;"); + jobject app = antikYt->CallStaticObjectMethod(atCls, curApp); + if (!app) return; + loadDex(antikYt, app); +} diff --git a/app/src/main/jni/Includes/Logger.h b/app/src/main/jni/Includes/Logger.h index 72021bf..df303d6 100644 --- a/app/src/main/jni/Includes/Logger.h +++ b/app/src/main/jni/Includes/Logger.h @@ -1,21 +1,27 @@ -#ifndef DAWN_LOGGER_H -#define DAWN_LOGGER_H +// +// Logger.h +// +// Created by MJ (Ruit) on 1/1/19. +// +#ifndef Logger_h +#define Logger_h + +#include #include -enum daLogType { - daDEBUG = 3, - daERROR = 6, - daINFO = 4, - daWARN = 5 +enum LogType { + oDEBUG = 3, + oERROR = 6, + oINFO = 4, + oWARN = 5 }; -//Change this to another Log Tag if ya want. IN the batch script I provide you change the log tag then too #define TAG OBFUSCATE("Mod_Menu") -#define LOGD(...) ((void)__android_log_print(daDEBUG, TAG, __VA_ARGS__)) -#define LOGE(...) ((void)__android_log_print(daERROR, TAG, __VA_ARGS__)) -#define LOGI(...) ((void)__android_log_print(daINFO, TAG, __VA_ARGS__)) -#define LOGW(...) ((void)__android_log_print(daWARN, TAG, __VA_ARGS__)) +#define LOGD(...) ((void)__android_log_print(oDEBUG, TAG, __VA_ARGS__)) +#define LOGE(...) ((void)__android_log_print(oERROR, TAG, __VA_ARGS__)) +#define LOGI(...) ((void)__android_log_print(oINFO, TAG, __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(oWARN, TAG, __VA_ARGS__)) -#endif //DAWN_LOGGER_H \ No newline at end of file +#endif /* Logger_h */ diff --git a/app/src/main/jni/Includes/Macros.h b/app/src/main/jni/Includes/Macros.h index e0f9f90..c36d4c8 100644 --- a/app/src/main/jni/Includes/Macros.h +++ b/app/src/main/jni/Includes/Macros.h @@ -1,113 +1,117 @@ +// thanks to shmoo and joeyjurjens for the usefull stuff under this comment. #ifndef ANDROID_MOD_MENU_MACROS_H #define ANDROID_MOD_MENU_MACROS_H -#include -#include -#include -#include - -// thanks to shmoo and joeyjurjens for the usefull stuff under this comment. - #if defined(__aarch64__) //Compile for arm64 lib only #include -#define HOOK(offset, ptr, orig) A64HookFunction((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) -#define HOOK_LIB(lib, offset, ptr, orig) A64HookFunction((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) - -#define HOOK_NO_ORIG(offset, ptr) A64HookFunction((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) -#define HOOK_LIB_NO_ORIG(lib, offset, ptr) A64HookFunction((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) - -#define HOOKSYM(sym, ptr, org) A64HookFunction(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) -#define HOOKSYM_LIB(lib, sym, ptr, org) A64HookFunction(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) - -#define HOOKSYM_NO_ORIG(sym, ptr) A64HookFunction(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, NULL) -#define HOOKSYM_LIB_NO_ORIG(lib, sym, ptr) A64HookFunction(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, NULL) - #else //Compile for armv7 lib only. Do not worry about greyed out highlighting code, it still works - #include #include -#define HOOK(offset, ptr, orig) MSHookFunction((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) -#define HOOK_LIB(lib, offset, ptr, orig) MSHookFunction((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) +#endif + +void hook(void *offset, void* ptr, void **orig) +{ +#if defined(__aarch64__) + A64HookFunction(offset, ptr, orig); +#else + MSHookFunction(offset, ptr, orig); +#endif +} -#define HOOK_NO_ORIG(offset, ptr) MSHookFunction((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) -#define HOOK_LIB_NO_ORIG(lib, offset, ptr) MSHookFunction((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) +#define HOOK(offset, ptr, orig) hook((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) +#define HOOK_LIB(lib, offset, ptr, orig) hook((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, (void **)&orig) -#define HOOKSYM(sym, ptr, org) MSHookFunction(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) -#define HOOKSYM_LIB(lib, sym, ptr, org) MSHookFunction(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) +#define HOOK_NO_ORIG(offset, ptr) hook((void *)getAbsoluteAddress(targetLibName, string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) +#define HOOK_LIB_NO_ORIG(lib, offset, ptr) hook((void *)getAbsoluteAddress(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset))), (void *)ptr, NULL) -#define HOOKSYM_NO_ORIG(sym, ptr) MSHookFunction(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, NULL) -#define HOOKSYM_LIB_NO_ORIG(lib, sym, ptr) MSHookFunction(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, NULL) +#define HOOKSYM(sym, ptr, org) hook(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) +#define HOOKSYM_LIB(lib, sym, ptr, org) hook(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, (void **)&org) -#endif +#define HOOKSYM_NO_ORIG(sym, ptr) hook(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), (void *)ptr, NULL) +#define HOOKSYM_LIB_NO_ORIG(lib, sym, ptr) hook(dlsym(dlopen(OBFUSCATE(lib), 4), OBFUSCATE(sym)), (void *)ptr, NULL) -// Obfuscate offset -#define OBFUSCATEOFFSET(str) string2Offset(OBFUSCATE(str)) // Encrypt offset +std::vector memoryPatches; +std::vector offsetVector; // Patching a offset without switch. -void patchOffset(const char *fileName, uint64_t offset, std::string hexBytes) { +void patchOffset(const char *fileName, uint64_t offset, std::string hexBytes, bool isOn) { + MemoryPatch patch = MemoryPatch::createWithHex(fileName, offset, hexBytes); - if(!patch.isValid()){ - LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex you entered."), offset); - return; - } - if(!patch.Modify()) { - LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), offset); - return; + + //Check if offset exists in the offsetVector + if (std::find(offsetVector.begin(), offsetVector.end(), offset) != offsetVector.end()) { + //LOGE(OBFUSCATE("Already exists")); + std::vector::iterator itr = std::find(offsetVector.begin(), offsetVector.end(), offset); + patch = memoryPatches[std::distance(offsetVector.begin(), itr)]; //Get index of memoryPatches vector + } else { + memoryPatches.push_back(patch); + offsetVector.push_back(offset); + //LOGI(OBFUSCATE("Added")); } -} -void patchOffset(uint64_t offset, std::string hexBytes) { - MemoryPatch patch = MemoryPatch::createWithHex(targetLibName, offset, hexBytes); - if(!patch.isValid()){ - LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex you entered."), offset); + if (!patch.isValid()) { + LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex"), offset); return; } - if(!patch.Modify()) { - LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), offset); - return; + if (isOn) { + if (!patch.Modify()) { + LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), offset); + } + } else { + if (!patch.Restore()) { + LOGE(OBFUSCATE("Something went wrong while restoring this offset: 0x%llu"), offset); + } } } -inline void patchOffsetSym(uintptr_t addr, - const std::string &hex, - bool enable) { - static std::map patchMap; +void patchOffsetSym(uintptr_t absolute_address, std::string hexBytes, bool isOn) { - if (!addr) { - LOGE("patchOffsetSym: NULL address"); - return; - } + MemoryPatch patch = MemoryPatch::createWithHex(absolute_address, hexBytes); - if (!patchMap.count(addr)) { - patchMap[addr] = MemoryPatch::createWithHex(addr, hex); + //Check if offset exists in the offsetVector + if (std::find(offsetVector.begin(), offsetVector.end(), absolute_address) != offsetVector.end()) { + //LOGE(OBFUSCATE("Already exists")); + std::vector::iterator itr = std::find(offsetVector.begin(), offsetVector.end(), absolute_address); + patch = memoryPatches[std::distance(offsetVector.begin(), itr)]; //Get index of memoryPatches vector + } else { + memoryPatches.push_back(patch); + offsetVector.push_back(absolute_address); + //LOGI(OBFUSCATE("Added")); } - MemoryPatch &patch = patchMap[addr]; - if (!patch.isValid()) { - LOGE("patchOffsetSym: invalid patch at %p", (void*)addr); + LOGE(OBFUSCATE("Failing offset: 0x%llu, please re-check the hex"), absolute_address); return; } - - if (enable) { - patch.Modify(); + if (isOn) { + if (!patch.Modify()) { + LOGE(OBFUSCATE("Something went wrong while patching this offset: 0x%llu"), absolute_address); + } } else { - patch.Restore(); + if (!patch.Restore()) { + LOGE(OBFUSCATE("Something went wrong while restoring this offset: 0x%llu"), absolute_address); + } } } -#define PATCHOFFSET(offset, hex) patchOffset(string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex)) -#define PATCHOFFSET_LIB(lib, offset, hex) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex)) +#define PATCH(offset, hex) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), true) +#define PATCH_LIB(lib, offset, hex) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), true) + +#define PATCH_SYM(sym, hex) patchOffset(dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), OBFUSCATE(hex), true) +#define PATCH_LIB_SYM(lib, sym, hex) patchOffset(dlsym(dlopen(lib, 4), OBFUSCATE(sym)), OBFUSCATE(hex), true) + +#define PATCH_SWITCH(offset, hex, boolean) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), boolean) +#define PATCH_LIB_SWITCH(lib, offset, hex, boolean) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), OBFUSCATE(hex), boolean) + +#define PATCH_SYM_SWITCH(sym, hex, boolean) patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), OBFUSCATE(hex), boolean) +#define PATCH_LIB_SYM_SWITCH(lib, sym, hex, boolean) patchOffsetSym((uintptr_t)dlsym(dlopen(lib, 4), OBFUSCATE(sym)), OBFUSCATE(hex), boolean) -#define PATCH_SYM_SWITCH(sym, hex, state) \ -patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, RTLD_NOW), OBFUSCATE(sym)), \ - OBFUSCATE(hex), state) +#define RESTORE(offset) patchOffset(targetLibName, string2Offset(OBFUSCATE(offset)), "", false) +#define RESTORE_LIB(lib, offset) patchOffset(OBFUSCATE(lib), string2Offset(OBFUSCATE(offset)), "", false) -#define PATCH_LIB_SYM_SWITCH(lib, sym, hex, state) \ -patchOffsetSym((uintptr_t)dlsym(dlopen(OBFUSCATE(lib), RTLD_NOW), OBFUSCATE(sym)), \ - OBFUSCATE(hex), state) - -#endif //ANDROID_MOD_MENU_MACROS_H +#define RESTORE_SYM(sym) patchOffsetSym((uintptr_t)dlsym(dlopen(targetLibName, 4), OBFUSCATE(sym)), "", false) +#define RESTORE_LIB_SYM(lib, sym) patchOffsetSym((uintptr_t)dlsym(dlopen(lib, 4), OBFUSCATE(sym)), "", false) +#endif //ANDROID_MOD_MENU_MACROS_H \ No newline at end of file diff --git a/app/src/main/jni/Includes/Utils.h b/app/src/main/jni/Includes/Utils.h index 24cb311..c703500 100644 --- a/app/src/main/jni/Includes/Utils.h +++ b/app/src/main/jni/Includes/Utils.h @@ -12,7 +12,7 @@ typedef unsigned long DWORD; static uintptr_t libBase; -bool isGameLibLoaded = false; +bool libLoaded = false; DWORD findLibrary(const char *library) { char filename[0xFF] = {0}, @@ -51,22 +51,20 @@ DWORD getAbsoluteAddress(const char *libraryName, DWORD relativeAddr) { return (reinterpret_cast(libBase + relativeAddr)); } -extern "C" { -JNIEXPORT jboolean JNICALL -Java_uk_lgl_modmenu_FloatingModMenuService_isGameLibLoaded(JNIEnv *env, jobject thiz) { - return isGameLibLoaded; -} + +jboolean isGameLibLoaded(JNIEnv *env, jobject thiz) { + return libLoaded; } bool isLibraryLoaded(const char *libraryName) { - //isGameLibLoaded = true; + //libLoaded = true; char line[512] = {0}; FILE *fp = fopen(OBFUSCATE("/proc/self/maps"), OBFUSCATE("rt")); if (fp != NULL) { while (fgets(line, sizeof(line), fp)) { std::string a = line; if (strstr(line, libraryName)) { - isGameLibLoaded = true; + libLoaded = true; return true; } } @@ -75,35 +73,6 @@ bool isLibraryLoaded(const char *libraryName) { return false; } -//Credit: Octowolve -void MakeToast(JNIEnv *env, jobject thiz, const char *text, int length) { - //Add our toast in here so it wont be easy to change by simply editing the smali and cant - //be cut out because this method is needed to start the hack (Octowolve is smart) - jstring jstr = env->NewStringUTF(text); //Edit this text to your desired toast message! - jclass toast = env->FindClass(OBFUSCATE("android/widget/Toast")); - jmethodID methodMakeText = - env->GetStaticMethodID( - toast, - OBFUSCATE("makeText"), - OBFUSCATE( - "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;")); - if (methodMakeText == NULL) { - LOGE(OBFUSCATE("toast.makeText not Found")); - return; - } - //The last int is the length on how long the toast should be displayed - //0 = Short, 1 = Long - jobject toastobj = env->CallStaticObjectMethod(toast, methodMakeText, - thiz, jstr, length); - - jmethodID methodShow = env->GetMethodID(toast, OBFUSCATE("show"), OBFUSCATE("()V")); - if (methodShow == NULL) { - LOGE(OBFUSCATE("toast.show not Found")); - return; - } - env->CallVoidMethod(toastobj, methodShow); -} - uintptr_t string2Offset(const char *c) { int base = 16; // See if this function catches all possibilities. @@ -123,9 +92,9 @@ uintptr_t string2Offset(const char *c) { return strtoull(c, nullptr, base); } -namespace Toast { +namespace ToastLength { inline const int LENGTH_LONG = 1; inline const int LENGTH_SHORT = 0; } -#endif +#endif \ No newline at end of file diff --git a/app/src/main/jni/Main.cpp b/app/src/main/jni/Main.cpp index 85c92c7..698a0a4 100644 --- a/app/src/main/jni/Main.cpp +++ b/app/src/main/jni/Main.cpp @@ -1,13 +1,8 @@ -// -// Created by aantik on 2/1/2026. -// - -//Main.cpp - #include #include -#include +#include #include +#include #include #include #include @@ -17,28 +12,16 @@ #include "Includes/Logger.h" #include "Includes/obfuscate.h" #include "Includes/Utils.h" - #include "KittyMemory/MemoryPatch.h" -#include "And64InlineHook/And64InlineHook.hpp" -#include "Menu.h" +#include "Menu/Setup.h" +#include "Includes/Interface.h" +//Target lib here #define targetLibName OBFUSCATE("libFileA.so") #include "Includes/Macros.h" -#include "JavaGPP/Interface/Interface.h" - - - -// fancy struct for patches for kittyMemory -struct My_Patches { - // let's assume we have patches for these functions for whatever game - // like show in miniMap boolean function - MemoryPatch GodMode, GodMode2, SliderExample; - // etc... -} hexPatches; - bool feature1, feature2, featureHookToggle, Health; int sliderValue = 1, level = 0; void *instanceBtn; @@ -81,7 +64,6 @@ void FunctionExample(void *instance) { return old_FunctionExample(instance); } - // we will run our hacks in a new thread so our while loop doesn't block process main thread void *hack_thread(void *) { LOGI(OBFUSCATE("pthread created")); @@ -100,18 +82,6 @@ void *hack_thread(void *) { LOGI(OBFUSCATE("%s has been loaded"), (const char *) targetLibName); #if defined(__aarch64__) //To compile this code for arm64 lib only. Do not worry about greyed out highlighting code, it still works - // New way to patch hex via KittyMemory without need to specify len. Spaces or without spaces are fine - // ARM64 assembly example - // MOV X0, #0x0 = 00 00 80 D2 - // RET = C0 03 5F D6 - hexPatches.GodMode = MemoryPatch::createWithHex(targetLibName, - string2Offset(OBFUSCATE("0x123456")), - OBFUSCATE("00 00 80 D2 C0 03 5F D6")); - //You can also specify target lib like this - hexPatches.GodMode2 = MemoryPatch::createWithHex("libtargetLibHere.so", - string2Offset(OBFUSCATE("0x222222")), - OBFUSCATE("20 00 80 D2 C0 03 5F D6")); - // Hook example. Comment out if you don't use hook // Strings in macros are automatically obfuscated. No need to obfuscate! HOOK("str", FunctionExample, old_FunctionExample); @@ -124,23 +94,12 @@ void *hack_thread(void *) { HOOKSYM_LIB_NO_ORIG("libFileB.so", "__SymbolNameExample", FunctionExample); // Patching offsets directly. Strings are automatically obfuscated too! - PATCHOFFSET("0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); - PATCHOFFSET_LIB("libFileB.so", "0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); + PATCH("0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); + PATCH_LIB("libFileB.so", "0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); AddMoneyExample = (void(*)(void *,int))getAbsoluteAddress(targetLibName, 0x123456); #else //To compile this code for armv7 lib only. - // New way to patch hex via KittyMemory without need to specify len. Spaces or without spaces are fine - // ARMv7 assembly example - // MOV R0, #0x0 = 00 00 A0 E3 - // BX LR = 1E FF 2F E1 - hexPatches.GodMode = MemoryPatch::createWithHex(targetLibName, //Normal obfuscate - string2Offset(OBFUSCATE("0x123456")), - OBFUSCATE("00 00 A0 E3 1E FF 2F E1")); - //You can also specify target lib like this - hexPatches.GodMode2 = MemoryPatch::createWithHex("libtargetLibHere.so", - string2Offset(OBFUSCATE("0x222222")), - OBFUSCATE("01 00 A0 E3 1E FF 2F E1")); // Hook example. Comment out if you don't use hook // Strings in macros are automatically obfuscated. No need to obfuscate! @@ -154,22 +113,39 @@ void *hack_thread(void *) { HOOKSYM_LIB_NO_ORIG("libFileB.so", "__SymbolNameExample", FunctionExample); // Patching offsets directly. Strings are automatically obfuscated too! - PATCHOFFSET("0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); - PATCHOFFSET_LIB("libFileB.so", "0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); + PATCH("0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); + PATCH_LIB("libFileB.so", "0x20D3A8", "00 00 A0 E3 1E FF 2F E1"); + + //Restore changes to original + RESTORE("0x20D3A8"); + RESTORE_LIB("libFileB.so", "0x20D3A8"); AddMoneyExample = (void (*)(void *, int)) getAbsoluteAddress(targetLibName, 0x123456); LOGI(OBFUSCATE("Done")); #endif + //Anti-leech + /*if (!iconValid || !initValid || !settingsValid) { + //Bad function to make it crash + sleep(5); + int *p = 0; + *p = 0; + }*/ + return NULL; } +// Do not change or translate the first text unless you know what you are doing +// Assigning feature numbers is optional. Without it, it will automatically count for you, starting from 0 +// Assigned feature numbers can be like any numbers 1,3,200,10... instead in order 0,1,2,3,4,5... +// ButtonLink, Category, RichTextView and RichWebView is not counted. They can't have feature number assigned +// Toggle, ButtonOnOff and Checkbox can be switched on by default, if you add True_. Example: CheckBox_True_The Check Box +// To learn HTML, go to this page: https://www.w3schools.com/ -jobjectArray getFeatureList(JNIEnv *env, jobject context) { +jobjectArray GetFeatureList(JNIEnv *env, jobject context) { jobjectArray ret; - const char *features[] = { OBFUSCATE("Category_The Category"), //Not counted OBFUSCATE("Toggle_The toggle"), @@ -193,10 +169,11 @@ jobjectArray getFeatureList(JNIEnv *env, jobject context) { OBFUSCATE("CollapseAdd_Toggle_The toggle"), OBFUSCATE("CollapseAdd_Toggle_The toggle"), OBFUSCATE("123_CollapseAdd_Toggle_The toggle"), + OBFUSCATE("122_CollapseAdd_CheckBox_Check box"), OBFUSCATE("CollapseAdd_Button_The button"), //Create new collapse again - OBFUSCATE("Collapse_Collapse 2"), + OBFUSCATE("Collapse_Collapse 2_True"), OBFUSCATE("CollapseAdd_SeekBar_The slider_1_100"), OBFUSCATE("CollapseAdd_InputValue_Input number"), @@ -211,40 +188,49 @@ jobjectArray getFeatureList(JNIEnv *env, jobject context) { "") }; - + //Now you dont have to manually update the number everytime; int Total_Feature = (sizeof features / sizeof features[0]); - ret = (jobjectArray) env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")),env->NewStringUTF("")); - for (int i = 0; i < Total_Feature; i++) env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i])); - pthread_t ptid; + ret = (jobjectArray) + env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")), + env->NewStringUTF("")); + + for (int i = 0; i < Total_Feature; i++) + env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i])); return (ret); } -void Changes(JNIEnv *env, jclass clazz, jobject obj, jint featNum, jstring featName, jint value, jboolean boolean, jstring str) { +void Changes(JNIEnv *env, jclass clazz, jobject obj, + jint featNum, jstring featName, jint value, + jboolean boolean, jstring str) { LOGD(OBFUSCATE("Feature name: %d - %s | Value: = %d | Bool: = %d | Text: = %s"), featNum, env->GetStringUTFChars(featName, 0), value, boolean, str != NULL ? env->GetStringUTFChars(str, 0) : ""); + //BE CAREFUL NOT TO ACCIDENTLY REMOVE break; + switch (featNum) { case 0: - feature2 = boolean; - if (feature2) { - // To print bytes you can do this - //if (hexPatches.GodMode.Modify()) { - // LOGD(OBFUSCATE("Current Bytes: %s"), - // hexPatches.GodMode.get_CurrBytes().c_str()); - //} - hexPatches.GodMode.Modify(); - hexPatches.GodMode2.Modify(); - //LOGI(OBFUSCATE("On")); - } else { - hexPatches.GodMode.Restore(); - hexPatches.GodMode2.Restore(); - //LOGI(OBFUSCATE("Off")); - } + // A much simpler way to patch hex via KittyMemory without need to specify the struct and len. Spaces or without spaces are fine + // ARMv7 assembly example + // MOV R0, #0x0 = 00 00 A0 E3 + // BX LR = 1E FF 2F E1 + PATCH_LIB_SWITCH("libil2cpp.so", "0x100000", "00 00 A0 E3 1E FF 2F E1", boolean); break; case 100: + //Reminder that the strings are auto obfuscated + //Switchable patch + PATCH_SWITCH("0x400000", "00 00 A0 E3 1E FF 2F E1", boolean); + PATCH_LIB_SWITCH("libil2cpp.so", "0x200000", "00 00 A0 E3 1E FF 2F E1", boolean); + PATCH_SYM_SWITCH("_SymbolExample", "00 00 A0 E3 1E FF 2F E1", boolean); + PATCH_LIB_SYM_SWITCH("libNativeGame.so", "_SymbolExample", "00 00 A0 E3 1E FF 2F E1", boolean); + + //Restore patched offset to original + RESTORE("0x400000"); + RESTORE_LIB("libil2cpp.so", "0x400000"); + RESTORE_SYM("_SymbolExample"); + RESTORE_LIB_SYM("libil2cpp.so", "_SymbolExample"); break; case 110: break; @@ -257,29 +243,13 @@ void Changes(JNIEnv *env, jclass clazz, jobject obj, jint featNum, jstring featN switch (value) { //For noobies case 0: - hexPatches.SliderExample = MemoryPatch::createWithHex( - targetLibName, string2Offset( - OBFUSCATE("0x100000")), - OBFUSCATE( - "00 00 A0 E3 1E FF 2F E1")); - hexPatches.SliderExample.Modify(); + RESTORE("0x0"); break; case 1: - hexPatches.SliderExample = MemoryPatch::createWithHex( - targetLibName, string2Offset( - OBFUSCATE("0x100000")), - OBFUSCATE( - "01 00 A0 E3 1E FF 2F E1")); - hexPatches.SliderExample.Modify(); + PATCH("0x0", "01 00 A0 E3 1E FF 2F E1"); break; case 2: - hexPatches.SliderExample = MemoryPatch::createWithHex( - targetLibName, - string2Offset( - OBFUSCATE("0x100000")), - OBFUSCATE( - "02 00 A0 E3 1E FF 2F E1")); - hexPatches.SliderExample.Modify(); + PATCH("0x0", "02 00 A0 E3 1E FF 2F E1"); break; } break; @@ -311,32 +281,29 @@ void Changes(JNIEnv *env, jclass clazz, jobject obj, jint featNum, jstring featN level = value; break; case 8: - //MakeToast(env, obj, TextInput, Toast::LENGTH_SHORT); break; case 9: break; } +} +__attribute__((constructor)) +void lib_main() { + // Create a new thread so it does not block the main thread, means the game would not freeze + pthread_t ptid; + pthread_create(&ptid, NULL, hack_thread, NULL); } -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *) { antik = vm; - InterfaceMethods::Icon = (void*) Icon; + InterfaceMethods::Icon = (void*) Icon; InterfaceMethods::IconWebViewData = (void *) IconWebViewData; + InterfaceMethods::Init = (void *) Init; + InterfaceMethods::SettingsList = (void *) SettingsList; + InterfaceMethods::GetFeatureList = (void *) GetFeatureList; InterfaceMethods::Changes = (void *) Changes; - InterfaceMethods::getFeatureList = (void *) getFeatureList; - InterfaceMethods::settingsList = (void *) settingsList; - InterfaceMethods::setTitleText = (void *) setTitleText; - InterfaceMethods::setHeadingText = (void *) setHeadingText; - binJava(); return JNI_VERSION_1_6; } - - -__attribute__((constructor)) -void lib_main() { - pthread_t ptid; - pthread_create(&ptid, NULL, hack_thread, NULL); -} diff --git a/app/src/main/jni/Menu/Menu.h b/app/src/main/jni/Menu/Menu.h new file mode 100644 index 0000000..4529339 --- /dev/null +++ b/app/src/main/jni/Menu/Menu.h @@ -0,0 +1,68 @@ +bool iconValid, settingsValid, initValid; + +//Big letter cause crash +void setText(JNIEnv *env, jobject obj, const char* text){ + //https://stackoverflow.com/a/33627640/3763113 + //A little JNI calls here. You really really need a great knowledge if you want to play with JNI stuff + //Html.fromHtml(""); + jclass html = (*env).FindClass(OBFUSCATE("android/text/Html")); + jmethodID fromHtml = (*env).GetStaticMethodID(html, OBFUSCATE("fromHtml"), OBFUSCATE("(Ljava/lang/String;)Landroid/text/Spanned;")); + + //setText(""); + jclass textView = (*env).FindClass(OBFUSCATE("android/widget/TextView")); + jmethodID setText = (*env).GetMethodID(textView, OBFUSCATE("setText"), OBFUSCATE("(Ljava/lang/CharSequence;)V")); + + //Java string + jstring jstr = (*env).NewStringUTF(text); + (*env).CallVoidMethod(obj, setText, (*env).CallStaticObjectMethod(html, fromHtml, jstr)); +} + +jstring Icon(JNIEnv *env, jobject thiz) { + iconValid = true; + + //Use https://www.base64encode.org/ to encode your image to base64 + return env->NewStringUTF( + OBFUSCATE("iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAADeUExURUdwTAC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwC8DwAAAAC8D2XRAEiaABIyADl6AGDJACNSAD6FACthAAYcAE6kAAEQADNtAFi3AACyDVzAAAglAABCAQC3DQAIAACgClKtAACTCAAwAWPNAABLAgBnBBxCAABzBQCoCwBbAwB8BgBSAl/EAAAZAACZCUyfAAA6AQCOCECJAACGB0aVAEOQADVzABg7AC5nAChbACleAGmQvrQAAAAZdFJOUwDwCxYgcZUr3/nosNDHBKSHVP1jM7lIe0FRwZXpAAAbvElEQVR42u2deX/iqhrH475vUdtJWp06NlXjrlat3Zdpz3n/b+je9qgGAgmJBFD5/XPu59apwLfwLDyAohyg8pHEWTlWjBcy1Ww2mQ6FQvq3QqFQOpnNVjOFeDFWPktE8opUoApXSrF4Jpv+GX5dVXWcNj9K5zLxWKkSlkNHW5FfsXgurfuQ+h+YeOwsKoeRyvKUKBWrSZ2GQrl4uSKXsX3mRSmeS+l0lcrFSxE5tN6VKBeSeiBSdT1ZKCfkEHuAEcuE9KAVysQkFKJlqpDWWSldkMuX89Q4z6k6W6m5czlR0KoUk2svlS0RXU8WK3L4YRrxpM5TybhkYlmpinxprJkU5dr1Y8Vj2T1Hsv1/LQaL7//s+ZuysVO38fmzTMq73egNRm/z2ar7bD4YGizjwXzurmbzt9Gg59meqKnM2QnH8pFzb2a8N3ibL7tmXyNV3+wu52+ewKh68vxEp8mvDHlapPc4X40Nza+M8Wr+SI4llfl1cjTCZVLL0X6ZdR9+/ty1PfXQnb2QWpls+aRy9pEiWTS+mE+bGl01p/MFWRRfPJmVKxonWasG866hBSOjOx+QrFzxk9hCqRTczXj7LjAYOyh37suXWjj6cLGSccXxODM1NjJnj65IMpXTxvGyMjSWMqYvp4sk4YbjbdrX2Ks/fXNDcpQ5laiL7RiteNBYM1mNXGzJ0Zn3cNHRs1osDY2vjKWjN5wqHlVcko85bcn27saaCBrfOQXzodjxJLlKTtn1Acelyr50OcUnydKR2PKqQwJRkMlhnSYOecdq4riNR3tmaOLJmLWP2JSU8EmrxUoTVSu8gU8f9LoVzeDj8a4msrr4GD5zsC6wg281Gmuiazw6Nn8rkTtgHM5Icgdo3PPnqcPG4YgkdX5okySB2xAcPGuHpGdcYJI9rEkSw0yPRVc7NHXRHpeaih2Qc1XFxB1L7RC1xMQl1UNxt0oY52re1w5T/TnG3TqImCQcx9jypna4amKsezx8qNb8AI0HkSkR3raX0dZ8ph2+ZmgHuCz4coVK7D6a2jHIfESmgAVetqLI5aq30o5FK+QOVlZUb+sM6V29PGjHIwNZoxI6EzMYRK1W7ZV2XFqhghJVwCAxXED6uoZ2bDKQHnBBNEMSQaV2e0vtGLVEWZKcWKXZCVQZw6CpHaeaqIxjMiG6OZ9rx6u52Ka9jDDn7a52zOoibLsqSoxYRMWChnbcMlBRYlGIrUGUe3WnHb9QBVwF/huJ4epRx+Ze4/Yqb/c3jHB3F6Z2GjIXiLts+BKJILJXL33tVNRHZFKyPAOSaPI4M+375OTVZFQkHr2pdlqa9sQhguDRHmunprE9IuFEJGGvox48aKenB3siJZ0QY36M+topqj8SYY4geLxpp6o3/kQQPOba6WrOm0gkeeLurrv7m2QZj4Tt8eBSO20t7REiu5gdkS+ZaqeuqX0TkRWRvD2f2NWkurYIscoo91uQPMiI6AU++1G9ZwnjR889HjtWZdvfgeSxJWIbm+B3dUuqXK+82JGgj5AkQpKHJyKhBOOAUPq7Lt5voAGiPQBZSgRuEWKQ4UhB5kt8ZFGCc35jMp/oK9MYVG38mSrz7b6y8WowRaZR2MEayaHHCN6xCgWRi7dleAd9OfIY9QcMMr/w8fP2gxx4rB7gyod44BmT3lgOu4PGvYBzKImUDAj3ChBTiWANiAxAvIYjdM0IbEBe5IB7dn5pmpESXN8uHSwfrlYpsAikJx0sIlerF1Q0UpUZd1+Cc/HVgFJYMoPlN6sVC8TjfZQDTazHAHzfPOTxtg05zsQyoIg9S6Ew6FwaEIpm5Jz6giUNyF5mZO9FKw9t2g7kEHsUFI3k8lQ9rF5TjrBHNXs0PS04JJQ1Dd61pBkeZuQe4f6C9g8z9HJY0uOl4vv6z2mFoXO2wV1h0qxZhTBUZg0l0yD62H+yf8ZANoH+X90KOqPrOxFfZJJzv3pvXUCatF4/wQ9dXqB1/3RjEHzsW/bPNKzfUN/8v1f0u/hCpyYeCkF6gSxYtSFm/N4NjWyk7//xC6TFCojRoxKMVBksWLV77AC2SP/0L758ArkwGQGBF60qDYseTE6x5TCCH6RAJjWfQG5YAYGzjH7seh4qdA/kEqw/ZOPsAuTi0ieQJ2ZATOh+mvzeMXowVQ3XjuNcJwXy2yeQ331WQOCaB+/xegSM0RfBeFj3juP8RArk4tYfEOvgBwykD94+F/J8aiTOIuluWEz4+2vjW6+XHZQXtB3F+8ZGH9d2s7792KRhEwrIKzMgcCLeaw1KNMUiZ2JuR2ZoobQl0kEAsbqqX9t//hf+2G/8l1qBtNgBgTIoKY8pLehoTkBJ3hoyRntHjCoSSNNmbbwCuaixA9Lc5xhPQmWyK1Wz/Yl/65UUiLY/kL/sgEB7VWrCf5a33Q8ciDUiaDAEcs0QSL/tO+tbUdnsgvAHMjHYAYF2RtSK3wmy0I4XyMU/DIFoC59TBJog3WMG8sESSNfnFMmwqmsQAEiHJRCo4iHjb4I8HzWQi0+WQJ59TZECs310EYDUWQKBosOCnyB9fLRA7oEcARsgY3CKRL1nsQItNOELZP0/miyBQFOEJKMVYTdBOANZb8b8YQoEnCKpiNfKhmArsfgCMX9bd7cYAYGmSNFr6c/4iIE0/8vf37MFMvZYElRmeTiHM5Ab6+4WKyDQ9rrrhQJZlodBOAMxral/ZkDAcD3rwuMXoyyWEEDWNS8ttkCgjNYvL1mT1ZEDaVjKs9gBAYq01IwHn7etHSyQSR3QDRrIleXL2QHR2uSe7znbC02CAwKpgwayrnp5YgxkRnzsECyO6xlHD+RyV57FEAhY6utUNHfG+EHbPYHU9gbytWPAEAj0jO4ZaZ53LDqQV9s/9wqkuSvPYglkTLgtApp0BgdufQD5fb3RcFdRt8lHeQaiDbeUWQIBN6rwZj3G1Of1BwStml8g9e2/ZwpkRVboC0TpPe1wgHQ0v0But+VZTIFoPZJoPcH8jXpaQOx1u5NbQJ84IFpnU57FFgho1hMkiffx4QDpPGj+InVtU7c6MTS2QMYkSfgkyzQWRSD3n5p/IP9uyrPYAgETWklkUFhhf2cDFSBPprYHEGOyLs9iDASsYqy476UbggKZdCxqDS//1pCDTQxk7fh2WAMx3PfWk+yvjds3dYIfbHIgaxCfjIGAW7moNavCOggRBMi6DXXWQKZua1aR/YolBJD1LtWQNZB+z8XPSnK49kcIIB/rWIYxEPDm66RLVLg6ISDrXaohayBT59jwnMOKJQaQ/m/QjWYFpO+8TZXjcde+EEC0Jz5AwDuCcnDmXeWwYgkC5IYTEGDNUiNON80YJwXE5AQEiA3VssNeIbPLxMUAAl1JxAwIWMMInRVJc3k+RxAgDU5AgOqTtIPTa54YkCtOQEy84xtjWh8nGhDwUiJ2QMCKuRj2Nr+7kwNyyQnIHe7ev3yIz4t4+951QgvIFycggOMbyuMyvQYHIA2XUQ0WSJMTEAOX8Y1xegBhFwG0dvfbNO9J78uiBkQb8gEC1mfFMIcQGL4Q0rdsjA8vf/Q0/O14oxwhkMmlTXUHIHVOQOaYCsY0ryd0vN+5SAgEoaEDkFtOQLroSCTByYTY8nqQ/jIDonX4ADHQkUiZ2xs6V4739prsgLzzAQIakTKy3oTtI1NDknpEBkD+5QRkjqw9yfJ7l9vE3zV+3WcIZF2exRzIFFXjm08xuIAUpyZmDCcN9EgHBMQyVZkCAa4qTeURYWFPY63PxvB+AsLoPNVNjS2QOh8gYBl8BWHT5UvpbPWCsOpxLnshUj+aIax6Tr6syk9dRKUDkOqVb9ez1QOQ8P3vSj++Nv3UBVj1qO1wunwsnbVGtiPrMfkYNE/NbRn4OI8SOamNrCek1YLNyRrLEWKssc3NSvPKvUt9y5qBV7+3RMLSyRLIzQpDu1MDOT7MNYCyWUCZ9ZscH+Z6g54AjclMFl/NIL83zm93SupbUyi9mJFerzh+r5pRlJxMLfLVAxSIAGFIX44Pe4G1WXmVy0EEqZ2shxJUJSLDEKECEbDCYSRHh4OAbXVwN0TGhTwEHNsBS07kbgj3yFAG6vwFXC4H3sokt6e4h+pg5kTWAPEQ8PwneIXDsxwdzrkTHUxlmXJ0OAi4P0CmsvjrAQ9EprJ4CDjXBh7WkYPDRQCQpAQiFpC0BCIWkJDMvnNXWwKRQKRIgaQkEO6yviWiMH/ERUoCkUCk/AORNkQwINLLkm6vlARyQEBkLou/ZLZXZCByP0QwIDl5Bpe3DLmnLpYeZNWJWDLxdVnyRBsPjfGVi7JQjoee8bW98hAuD03x1e9LOToctMSfD5HHEXhohj9BdSdHh4Pu8GcM5aW9PASeMZSncLkLPIUrz6lzF3hOnfwmB7O2ESag3/68hsiJNWtWNd0+4PhRGg0za3jZP2MgW2ogvsLaBMNpQHaCXtkhTmbtLrq/R/7c8jjLH+gn77ZHKSat10/wQ3XsLfqtj1tHIL4a5nRtv/0zDWRLLdf2bx/OurR88A/RBf/wXSfEtwFZuoAcoFcMkBru0ZZ3gwzI92tUTdoN8wakFSCQMfQwGPF9WZYu1FE/b6GB1PAPf7UMUiAXrSblhnkDcmEGBwS+L4v4oPql/SkOYCW/QANpOfT8gxiI9cU2Kg3zCOQmOCDwjXLEdy5amjdBGKkvNJA/jsNcIwZy8Um3YR6BPAUHBL5zsUIaiFi78I/zjy1Arh1HuU4OpEG3YR6B/O4HBgS+lZT43t5LzFqz1j0aCPHTkW5AhnQb5hGIdUgpA4Hv7SW+2draPPtLUNa3Mi39Niz/5v218a3Xyw7q9+yA/P2z0dff3QTr0G3Y7pHWhk2oX/waFBDD9tgn6d3vl5jFH/EH/gdhUS1/4UYHMcp19O/e+gQTug3z9Iwx5k+HChD73e+kryNcYl5F/U9DdL/RD3S/I0YDA+TdtpDQaZhXIJZW0QVifx2B9P2QSycv1Ji4AXF7wh4D5NUjENKGeQbyNyAg9vdDzggv+QOaB3fjnws3IFZPvkEOpOERCGnDPAO5DgiI/YUd0jeoQL8E+ooPUYCQNswzkF2IQxeI/Q0q0lfaLp3CgpYwQAgb5hnILsShCgTxShvpO4aXDmFB7UIYIIQN8w7kIxAgqHcMCV/6hEIpINt3Iw4QwoZ5B9IJBAjqpU/Ct3AvcX37v54EAkLWMO9Attk0qkBQb+ESvhYNNe/d+rPfAgEha5gPIPUggKBeiyZ8T33TvJY9lXEF/IQXEE8N8wTkHrBONIEg31MHD+1M3Zp33bHlw9ej9soXiKeGeQJyCVgnmkCsu1Nqds0DtOpz136/21Ln6/TEFWcgXhrmCcgf4F/TBDJH2HTIqg9c+/0Fh67NdejU5wzES8M8ATF/WwebJpABwqZDL+dhM/DbfpubbkJfPNQ4A/HSME9AmtfWohaKQPrAyCc2QMAtka5bvzfR7xWUka3zBuKlYd6A3FiLWigC6SLi9G9lSIzIrt+v0J5NZ9Nc3kA8NMwbENOalqEIZA6VAG0UIzEiu35fgXs2n9sqNd5APDTMG5D13GvRBjKw5d4RoSHOiOz6vdljMIGhfOIPxEPDPAJpWH4xPSDA9u0mLPwJDUMEkciu3xtv8gsoLLnhD8RDw3Z76nVAN2ggV5ZO0AMC1MiF8jsgSpXg2I6l33Xrl/cn23HkDoS8Ybiqkw4ayLp25YkuEOCoTtXCAzQibdd+31prm692PeEOhLxhXoFc7sqz6AFpY0wIHImYbv3e1DrdWna9P0QAQt4wr0C+diNLDYiJiUJskcjMtd9PliRFa9dX/kCIG+YVSHPnUVMDsrSVZO0EXOjw6Nrvv7vdOdOyL8QfCHHDvAJZ+wstmkAerYNeAIGU3B1fa79ru43/L8vOKX8gxA3zDKS+bRwtIIDTq5ZBIBHVtVzO2u9NDPzP9v9uiAGEuGGegdxuy7NoAQGcXjUCAgErHV5c+/2+NZj3lq8UAAhpw3ZxyC2gTxyQNeprekBeEPUNO527rllAv/9skhS31gyrAEBIG+YxUt+inhgaJSBgpvccBgI6viu3fjc3g1e37kEIAIS0Yd6B/LtZDCkBmTo4vd9KulWUAv3e+JQ3Q+sunQBASBvmHcg6UfZBCwhwcipp4wHe04Ras8B+r6Ou64l1p0AEIIQN8w5k7fh2KAHpA/UmRTuQituaBfb7CvBN1ntpIgAhbJgPIOsWftIBMsVletFr1qNbv/sTxCEAEYAQNswHkHVf6nSAjFxWLKj2BLFmgf0GD8LciAOEsGE+gKzN05AKEHArJI4CAq5ZS7d+A0fFTIGAkDXMD5D10YYGDSBL1xULWrMWbv2+RRzAEwIIWcP8AFmbpyENIAvXFQv2s8Yu/bYeN/4QCQhZw/wA6UOVwnsAAY56onwse2x459ZvS2H5v0IBIWqYHyBwLf0eQO5cokJEjW/Prd+WoxcPQgEhapgvIDfUgABBSBbDA9zItYUicL9r9kNLYgAhapgvICYtICsdu3kL5OBTTvVZcL93x/caYgEhapgvINCJRf9AgHqsVAQHBKxghM26rd+vnbWuBANC0jB/QBp0gIAmPYPlAR5Zh826rd92CQKEpGH+gFzRAQKa9DM8kDwQivQMCQQ+R3pPA4gBmPRkHg8E2qaaSSAwkEsaQGbOW1N4s96mCST4u05YAPmiAaRNaNLtZn1FEUgD1VOqtwGxANJ0A2JtxF80EMDnVTOOPJRfOtbz9dXvnefe2l2S17xH1HiggfRb7gPHEgiQS7YM87ZHvy1ln7vb126xPq/+yxkIGK0DT+746nffslc0vPzR0/C3LfkHAGnsatFfW8j6HJpAJpc21R2A1NFAdu2cDJ/++y3Dji3p/CPgQR18lI48AArsU/nqN8s7F/0BcfgqFJBbNBDnuz4n2HpFvewGJJzGBYf+gDw5tvQvOZC6GEC0DhJInfiPCQwK02E3IFASfrQvkCvHvxyTHEhNECDvSCDmxKntX7itW1ziHe/5WqaIPyDa0KGhVs/LBciHJgiQf5FArBfM29TCThAXnxe1tz7aF4iJv2v8uk8MZGiIAsRyiaMVSB9vRTo17ASJE/BQoip6ivgEojUxfZ+Ad785AZl8OD1swhaIZcqD4V4Ds2o9mdgJokZJgIBnRXZTxC8QTftsDO/B1k46T3XonBYOyKRzXa9pmjhA6riUoVl/6kDdvB82PvHFP/CZEJwqqi6f/wxGYAyiVsiAQPkT+VIYPQ1IN0Icp0hXDiQldf1NEHiKLORIUtLC3wSxTRH5RC4dLf1OEHiKtPtyMCmo3/Y7QRQlAU6RuRxNCpqDEyThBQgUi+hNOZx7q6n7iUG24XpKJ3w0QYpQYEyYinoDAmW0pOtL2eUly2IBSd+QdH0DdHlDEa9AoEJfxycnpdwFlv7gy3lJi+ZwdzZJkQm8icm5OA4n8D4azBVBUmQCN9L1kqL4UFV3vd1Bikzg8QPwNj8P0SHo+vYMObA+BRbz6qmEPyBQvYPDWy9SznrRvVY2EJUEyUXLp8BLG0hKfwjtelsuWr4WrDYNi47K+soMCoWcibcsry2lBcbrcmfEh8BdED0U3QcIHK/3ZNrXq5q9vWN0IF7P6bLiYS+BdQ16Lr8fEDgYkXtVHgXuSvkPQXDHDmUi3pueodE735uHks9K35eax5vN7w/EtmjJLKPvnCKFBQvhaUkz4teA7Oth4dK+0owQCtq19ZvkdQ8Pew9ysAn00KMaEjrktPSFrJxzVx+KQPbKYbnUoMhMPIHe9D3rTBwT8ZDvK2seXAVVNejZME0gNt8X/8q31I+gPRBaHi/uQgFd743loDtoDBl09wsC9jYjbelqkUfodA0IxowMpKtF7GBRNiDoaETuH2IF7RHSjECAGxlV6Hve5NATObzqmRKM4KSWzGoRZbCopbBcj/HIcIQkAPF6NMeTYc/BXyarHmAt4SHKhYMDokSSugwQPQWEejKiBKkE7GrJXDwgOOOuhxJKsCrBrpa8C8UieAtdV0tK0IJzKJKIA48AMiauNfG63pNE1jzgBJb/Ovf9nN+etCM/9qPH0OEFCoOqurTsBPZcr+bZAEGEI9L7tfu7wQYgLplfeZhnZRuRLDseqADxxLMotnxJ0AGhLRdvJ3LKmca5nUdUUXgTOd1s/Bt/HkoeQWR0mnuI/ZEtPk8z5/Gd1krbiAxOcZ/9YWAbh3RC4SHEHGmfXi3KuC3AeoUn0ju1gGTaE4cHksiJub92d1flyENRIvYIUX85HdPef7F3PxtReAqRRdEXp2LaHxY6z3wJhog903gq2V97dlfXq7x5KEq+YG/WSUTtc0S/C3lFABURLXs89rO6xiOi10VFDJVVe9vax71sPdujD10tK6LoLHRiyxZquQqdKeKogghI9MGx3lTTHCB6m6woIimCcH/13nHWNS4R3pWeiyhiKYxytvTR8dl2Y4TqaCGsCKcYwrTr7WPLbU0R1lxXY4qIQpp2/eWYJonxootuzoFcYxbV3N7x1D+sUNZDz0YVURWOoxqsPx7HvfHmI7J38bAisMopZKOPISc/Q/YsVVbEVgK5bOmLQw/cuwtkv7IJRXRhli19dMhhYnOkH+BytT1CEkK3fn6oO1f9ObpDoZJyGIpW0R1oH2bkvmyju1ONKgejGNq2H6IpwRgPPRVTDkkY267rg8M63fM8wPTjAKw5tJF4jpkk+uhwarfGGFuup87zysEpkdMPGwkWh55LKIeofCx0wEiwONRULK8cqKIZHBH9UWzz3n3EtjwTVQ5YpTS2YwtxM/PTAbbV6ZJy2AoXU9jOtWcipuaNWRvb4lQxrBy8ElUdrzvRjMn4zqG11YRyFColHTo5EGm7ZDVwaGmypByLHPyt7x0sQabJ+K7n0MrQ4fpWyKoUB1PybeCXvK2JsVw4NTBVjChHpmjcEYk+mvJLBvenI8e2peJR5QgVLaiO3dbfuDDpT996js1SC0eJ48fhckOiv0zZrl3G9MWlRWohoRyxEhk3JPrjjFVNhDl7dGuMmjlqHN+quM4SXW/fdYOeKEb3ru3aDrVQUU5AbuZ9HZ/MA4PS784HBC04UlOOdoLTuk4EZUq7NKI5JYKh6+njc3QdU1zlrE6m9susS+cU6UN39tIm/NZsOaycmn5lUjqpeqP5aux/BTPGq/moR/xtqcwv5SQVOU/qXtQbvM2XXZM8WOmb3eX8bdDz9C3J84hyssqfeZgmFjCjt/ls1X02H+xw+g/mc3c1m7+NPIJYT46zvHLaisSy+n5q/1+LweL7P3v+pmwsokgpSqKY1PkrWUxIFLtwMc6XSTJekRAgc1LhNk+SRUkDs3ad51TGMNTcuVypHG18qZBmRiNdKEkrTjJRYtVQ4DBC1ZicGl6glAvBmZRkoSxh+Fq+4rkUZRapXFwuU3s5X4lSsUpnroRy8XIlL4d0byTfc+VXLJ7zb+zTuXjsLCqHkrbClVIsnsmmPYDIxGOlyiFl0v8HKtOuZ5Ocqs4AAAAASUVORK5CYII=")); +} + +jstring IconWebViewData(JNIEnv *env, jobject thiz) { + iconValid = true; + //WebView support GIF animation. Upload your image or GIF on imgur.com or other sites + + // From internet (Requires android.permission.INTERNET) + // return env->NewStringUTF(OBFUSCATE("https://i.imgur.com/SujJ85j.gif")); + + // Base64 html: + // return env->NewStringUTF("data:image/png;base64, "); + + // To disable it, return NULL. It will use normal image above: + // return NULL + + //return env->NewStringUTF(OBFUSCATE_KEY("https://i.imgur.com/SujJ85j.gif", 'u')); + return NULL; +} + +jobjectArray SettingsList(JNIEnv *env, jobject activityObject) { + jobjectArray ret; + + const char *features[] = { + OBFUSCATE("Category_Settings"), + OBFUSCATE("-1_Toggle_Save feature preferences"), //-1 is checked on Preferences.java + OBFUSCATE("-3_Toggle_Auto size vertically"), + OBFUSCATE("Category_Menu"), + OBFUSCATE("-6_Button_Close settings"), + }; + + int Total_Feature = (sizeof features / + sizeof features[0]); //Now you dont have to manually update the number everytime; + ret = (jobjectArray) + env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")), + env->NewStringUTF("")); + int i; + for (i = 0; i < Total_Feature; i++) + env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i])); + + settingsValid = true; + + return (ret); +} diff --git a/app/src/main/jni/Menu/Setup.h b/app/src/main/jni/Menu/Setup.h new file mode 100644 index 0000000..1a9404a --- /dev/null +++ b/app/src/main/jni/Menu/Setup.h @@ -0,0 +1,59 @@ +#include +#include "Menu/Menu.h" +#include "Menu/get_device_api_level_inlines.h" + +//Jni stuff from MrDarkRX https://github.com/MrDarkRXx/DarkMod-Floating +void setDialog(jobject ctx, JNIEnv *env, const char *title, const char *msg){ + jclass Alert = env->FindClass(OBFUSCATE("android/app/AlertDialog$Builder")); + jmethodID AlertCons = env->GetMethodID(Alert, OBFUSCATE(""), OBFUSCATE("(Landroid/content/Context;)V")); + + jobject MainAlert = env->NewObject(Alert, AlertCons, ctx); + + jmethodID setTitle = env->GetMethodID(Alert, OBFUSCATE("setTitle"), OBFUSCATE("(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;")); + env->CallObjectMethod(MainAlert, setTitle, env->NewStringUTF(title)); + + jmethodID setMsg = env->GetMethodID(Alert, OBFUSCATE("setMessage"), OBFUSCATE("(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;")); + env->CallObjectMethod(MainAlert, setMsg, env->NewStringUTF(msg)); + + jmethodID setCa = env->GetMethodID(Alert, OBFUSCATE("setCancelable"), OBFUSCATE("(Z)Landroid/app/AlertDialog$Builder;")); + env->CallObjectMethod(MainAlert, setCa, false); + + jmethodID setPB = env->GetMethodID(Alert, OBFUSCATE("setPositiveButton"), OBFUSCATE("(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;")); + env->CallObjectMethod(MainAlert, setPB, env->NewStringUTF("Ok"), static_cast(NULL)); + + jmethodID create = env->GetMethodID(Alert, OBFUSCATE("create"), OBFUSCATE("()Landroid/app/AlertDialog;")); + jobject creaetob = env->CallObjectMethod(MainAlert, create); + + jclass AlertN = env->FindClass(OBFUSCATE("android/app/AlertDialog")); + + jmethodID show = env->GetMethodID(AlertN, OBFUSCATE("show"), OBFUSCATE("()V")); + env->CallVoidMethod(creaetob, show); +} + +void Toast(JNIEnv *env, jobject thiz, const char *text, int length) { + jstring jstr = env->NewStringUTF(text); + jclass toast = env->FindClass(OBFUSCATE("android/widget/Toast")); + jmethodID methodMakeText =env->GetStaticMethodID(toast,OBFUSCATE("makeText"),OBFUSCATE("(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;")); + jobject toastobj = env->CallStaticObjectMethod(toast, methodMakeText,thiz, jstr, length); + jmethodID methodShow = env->GetMethodID(toast, OBFUSCATE("show"), OBFUSCATE("()V")); + env->CallVoidMethod(toastobj, methodShow); +} + +void Init(JNIEnv *env, jobject thiz, jobject ctx, jobject title, jobject subtitle){ + //Set sub title + setText(env, title, OBFUSCATE("Modded by (yourname)")); + + //Set sub title + setText(env, subtitle, OBFUSCATE("

" + "

Modded by LGL

| " + "https://github.com/LGLTeam | Lorem Ipsum is simply dummy text of the printing and typesetting

" + "
")); + + //Dialog Example + //setDialog(ctx,env,OBFUSCATE("Title"),OBFUSCATE("Message Example")); + + //Toast Example + Toast(env,ctx,OBFUSCATE("Modded by YOU"),ToastLength::LENGTH_LONG); + + initValid = true; +} diff --git a/app/src/main/jni/Menu/get_device_api_level_inlines.h b/app/src/main/jni/Menu/get_device_api_level_inlines.h new file mode 100644 index 0000000..817dd77 --- /dev/null +++ b/app/src/main/jni/Menu/get_device_api_level_inlines.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + + +#include + +__BEGIN_DECLS + +// Avoid circular dependencies since this is exposed from . +int __system_property_get(const char* __name, char* __value); +int atoi(const char* __s) __attribute_pure__; + +int api_level() { + char value[92] = { 0 }; + if (__system_property_get("ro.build.version.sdk", value) < 1) return -1; + int api_level = atoi(value); + return (api_level > 0) ? api_level : -1; +} + +__END_DECLS + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..6429032 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b0fc226..40c9174 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,9 +1,9 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index eca70cf..1f46878 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index eca70cf..1f46878 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index 4726d53..7c66a39 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index dffca36..07fa66d 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index 97f1be4..0908202 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index dae5e08..ce9df10 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 6ebcfbd..d25e23c 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 14ed0af..33c766d 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 040a07c..74f9c60 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index d8ae031..b4f23ee 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 45d47ee..98715ec 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index beed3cd..74f9fde 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index b35a435..3f5b3dc 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,4 +1,4 @@ - - - #202020 - + + + #202020 + diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..8c40f6a --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #0277BD + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a355e2..2f2f6ac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - - LGL Mod Menu - + + LGL Mod Menu + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index d13d67a..303f720 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/build.gradle b/build.gradle index 3756278..e26c896 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - alias(libs.plugins.android.application) apply false +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 4387edc..f9c348f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,21 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. For more details, visit -# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true -# Enables namespacing of each library's R class so that its R class includes only the -# resources declared in the library itself and none from the library's dependencies, -# thereby reducing the size of the R class for that library +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. For more details, visit +# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library android.nonTransitiveRClass=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ceb0910..12255ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,22 @@ -[versions] -agp = "8.13.2" -junit = "4.13.2" -junitVersion = "1.3.0" -espressoCore = "3.7.0" -appcompat = "1.7.1" -material = "1.13.0" -activity = "1.12.2" -constraintlayout = "2.2.1" - -[libraries] -junit = { group = "junit", name = "junit", version.ref = "junit" } -ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } -espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } -appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } -material = { group = "com.google.android.material", name = "material", version.ref = "material" } -activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } -constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } - -[plugins] -android-application = { id = "com.android.application", version.ref = "agp" } - +[versions] +agp = "8.13.2" +junit = "4.13.2" +junitVersion = "1.3.0" +espressoCore = "3.7.0" +appcompat = "1.7.1" +material = "1.13.0" +activity = "1.12.2" +constraintlayout = "2.2.1" + +[libraries] +junit = { group = "junit", name = "junit", version.ref = "junit" } +ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } +activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } +constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fd263c..3e66f1e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,8 @@ -#Sat Jan 31 21:42:02 BDT 2026 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +#Sat Jan 31 21:42:02 BDT 2026 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index ef07e01..c026f59 100644 --- a/gradlew +++ b/gradlew @@ -1,251 +1,251 @@ -#!/bin/sh - -# -# Copyright © 2015 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH="\\\"\\\"" - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index db3a6ac..5eed7ee 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,94 +1,94 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH= - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle index af639b2..abb37eb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,23 +1,23 @@ -pluginManagement { - repositories { - google { - content { - includeGroupByRegex("com\\.android.*") - includeGroupByRegex("com\\.google.*") - includeGroupByRegex("androidx.*") - } - } - mavenCentral() - gradlePluginPortal() - } -} -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} - -rootProject.name = "Native-LGL" -include ':app' +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "Native-LGL" +include ':app'