├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── reveny
│ │ └── imgui
│ │ └── mod
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── reveny
│ │ │ └── imgui
│ │ │ └── mod
│ │ │ ├── MainActivity.java
│ │ │ └── test
│ │ │ ├── myGlSurfaceView.java
│ │ │ └── myRenderer.java
│ ├── jni
│ │ ├── Build
│ │ │ ├── Android.mk
│ │ │ └── Application.mk
│ │ ├── Include
│ │ │ ├── Dobby
│ │ │ │ ├── arm64-v8a
│ │ │ │ │ └── libdobby.a
│ │ │ │ ├── armeabi-v7a
│ │ │ │ │ └── libdobby.a
│ │ │ │ ├── dobby.h
│ │ │ │ ├── x86
│ │ │ │ │ └── libdobby.a
│ │ │ │ └── x86_64
│ │ │ │ │ └── libdobby.a
│ │ │ ├── Drawing.h
│ │ │ ├── ImGui.h
│ │ │ ├── ImGui
│ │ │ │ ├── backends
│ │ │ │ │ ├── android_native_app_glue.h
│ │ │ │ │ ├── imgui_impl_android.cpp
│ │ │ │ │ ├── imgui_impl_android.h
│ │ │ │ │ ├── imgui_impl_opengl3.cpp
│ │ │ │ │ ├── imgui_impl_opengl3.h
│ │ │ │ │ └── imgui_impl_opengl3_loader.h
│ │ │ │ ├── imconfig.h
│ │ │ │ ├── imgui.cpp
│ │ │ │ ├── imgui.h
│ │ │ │ ├── imgui_demo.cpp
│ │ │ │ ├── imgui_draw.cpp
│ │ │ │ ├── imgui_internal.h
│ │ │ │ ├── imgui_tables.cpp
│ │ │ │ ├── imgui_widgets.cpp
│ │ │ │ ├── imstb_rectpack.h
│ │ │ │ ├── imstb_textedit.h
│ │ │ │ └── imstb_truetype.h
│ │ │ ├── KittyMemory
│ │ │ │ ├── KittyMemory.cpp
│ │ │ │ ├── KittyMemory.h
│ │ │ │ ├── KittyUtils.cpp
│ │ │ │ ├── KittyUtils.h
│ │ │ │ ├── MemoryBackup.cpp
│ │ │ │ ├── MemoryBackup.h
│ │ │ │ ├── MemoryPatch.cpp
│ │ │ │ └── MemoryPatch.h
│ │ │ ├── Logger.h
│ │ │ ├── Math
│ │ │ │ ├── Quaternion.hpp
│ │ │ │ ├── Vector2.hpp
│ │ │ │ └── Vector3.hpp
│ │ │ ├── Obfuscate.h
│ │ │ ├── RemapTools.h
│ │ │ ├── Roboto-Regular.h
│ │ │ ├── Unity.h
│ │ │ ├── Utils.h
│ │ │ ├── json
│ │ │ │ └── json.hpp
│ │ │ └── xdl
│ │ │ │ ├── include
│ │ │ │ └── xdl.h
│ │ │ │ ├── xdl.c
│ │ │ │ ├── xdl_iterate.c
│ │ │ │ ├── xdl_iterate.h
│ │ │ │ ├── xdl_linker.c
│ │ │ │ ├── xdl_linker.h
│ │ │ │ ├── xdl_lzma.c
│ │ │ │ ├── xdl_lzma.h
│ │ │ │ ├── xdl_util.c
│ │ │ │ └── xdl_util.h
│ │ ├── Loader
│ │ │ └── Loader.cpp
│ │ └── Main
│ │ │ └── Main.cpp
│ └── res
│ │ ├── drawable
│ │ ├── ic_launcher_background.xml
│ │ └── ic_launcher_foreground.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ └── ic_launcher_round.webp
│ │ ├── values-night
│ │ └── themes.xml
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ │ └── xml
│ │ ├── backup_rules.xml
│ │ └── data_extraction_rules.xml
│ └── test
│ └── java
│ └── com
│ └── reveny
│ └── imgui
│ └── mod
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── img
├── 264991616-75554869-54d2-4c18-b89b-70958246d300.png
├── 264992884-d8e57355-6f62-427f-97b0-db6aa04f30fb.png
└── ezgif.com-video-cutter (1).gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gradle files
2 | .gradle/
3 | build/
4 |
5 | # Local configuration file (sdk path, etc)
6 | local.properties
7 |
8 | # Log/OS Files
9 | *.log
10 |
11 | # Android Studio generated files and folders
12 | captures/
13 | .externalNativeBuild/
14 | .cxx/
15 | *.apk
16 | output.json
17 |
18 | # IntelliJ
19 | *.iml
20 | .idea/
21 | misc.xml
22 | deploymentTargetDropDown.xml
23 | render.experimental.xml
24 |
25 | # Keystore files
26 | *.jks
27 | *.keystore
28 |
29 | # Google Services (e.g. APIs or Firebase)
30 | google-services.json
31 |
32 | # Android Profiling
33 | *.hprof
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android-ImGui-Mod-Menu
2 | Android Internal ImGui Mod Menu Template with remap hide
3 |
4 | # Features
5 | - [x] Any Android Version
6 | - [x] Any Game Supported
7 | - [x] Arm64 Support
8 | - [x] x86 Support
9 | - [x] Test UI Without having to implement into game
10 |
11 | # Implementation
12 | 1. Build the APK in Android Studio
13 | 2. Open the APK in the zip program of your choice
14 | 3. Copy all the files from /lib/arm64-v8a/ to /lib/arm64-v8a of the game
15 | 
16 | 4. Find the games launcher activity and place the following code in the onCreate method
17 | ```
18 | const-string v0, "Loader"
19 | invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
20 | ```
21 | 
22 | 5. Recompile the apk
23 |
24 |
25 | # Credits
26 | ImGui by ocornut: https://github.com/ocornut/imgui
27 | DobbyHook by jmpwes: https://github.com/jmpews/Dobby
28 | KittyMemory by MJx0: https://github.com/MJx0/KittyMemory
29 | OpenGL Test by JimSeker: https://github.com/JimSeker/opengl/tree/master
30 | ImGui Touch by fedes1to: https://github.com/fedes1to/Zygisk-ImGui-Menu
31 |
32 | # Contact
33 | Telegram Group: https://t.me/reveny1
34 | Telegram Contact: https://t.me/revenyy
35 |
36 | # Preview
37 | .gif)
38 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | namespace 'com.reveny.imgui.mod'
7 | compileSdk 33
8 |
9 | defaultConfig {
10 | applicationId "com.reveny.imgui.mod"
11 | minSdk 24
12 | targetSdk 33
13 | versionCode 1
14 | versionName "1.0"
15 | ndk {
16 | abiFilters "arm64-v8a", "armeabi-v7a"
17 | }
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 |
32 | externalNativeBuild {
33 | ndkBuild {
34 | path file('src/main/jni/Build/Android.mk')
35 | }
36 | }
37 | ndkVersion = '24.0.7856742'
38 | }
39 |
40 | dependencies {
41 | implementation 'androidx.appcompat:appcompat:1.6.1'
42 | implementation 'com.google.android.material:material:1.9.0'
43 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
44 | testImplementation 'junit:junit:4.13.2'
45 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
46 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
47 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/reveny/imgui/mod/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.reveny.imgui.mod;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.reveny.imgui.mod", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/reveny/imgui/mod/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.reveny.imgui.mod;
2 |
3 | import android.app.Activity;
4 | import android.app.ActivityManager;
5 | import android.content.Context;
6 | import android.content.pm.ConfigurationInfo;
7 | import android.os.Bundle;
8 | import android.util.Log;
9 | import android.view.View;
10 |
11 | import com.reveny.imgui.mod.test.myGlSurfaceView;
12 |
13 | public class MainActivity extends Activity {
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_main);
19 |
20 | //Taken from https://github.com/JimSeker/opengl/blob/master/OpenGL30Cube/app/src/main/java/edu/cs4730/opengl30cube/MainActivity.java
21 | if (detectOpenGLES30()) {
22 | //so we know it a opengl 3.0 and use our extended GLsurfaceview.
23 | setContentView(new myGlSurfaceView(this));
24 | } else {
25 | // This is where you could create an OpenGL ES 2.0 and/or 1.x compatible
26 | // renderer if you wanted to support both ES 1 and ES 2.
27 | Log.e("OpenGL", "OpenGL ES 3.0 not supported on device.");
28 | finish();
29 | }
30 |
31 | System.loadLibrary("Loader");
32 | }
33 |
34 | private boolean detectOpenGLES30() {
35 | ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
36 | ConfigurationInfo info = am.getDeviceConfigurationInfo();
37 | return (info.reqGlEsVersion >= 0x30000);
38 | }
39 |
40 | @Override
41 | public void onWindowFocusChanged(boolean hasFocus) {
42 | super.onWindowFocusChanged(hasFocus);
43 | if (hasFocus) {
44 | getWindow().getDecorView().setSystemUiVisibility(
45 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
46 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
47 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
48 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
49 | | View.SYSTEM_UI_FLAG_FULLSCREEN);
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/reveny/imgui/mod/test/myGlSurfaceView.java:
--------------------------------------------------------------------------------
1 | package com.reveny.imgui.mod.test;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLSurfaceView;
5 | import android.view.MotionEvent;
6 |
7 | /*
8 | * simple extention of the GLsurfaceview. basically setup to use opengl 3.0
9 | * and set some configs. This would be where the touch listener is setup to do something.
10 | *
11 | * It also declares and sets the render.
12 | */
13 |
14 | public class myGlSurfaceView extends GLSurfaceView {
15 |
16 | myRenderer myRender;
17 |
18 | public myGlSurfaceView(Context context) {
19 | super(context);
20 | // Create an OpenGL ES 3.0 context.
21 | setEGLContextClientVersion(3);
22 |
23 | super.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
24 |
25 | // Set the Renderer for drawing on the GLSurfaceView
26 | myRender = new myRenderer(context);
27 | setRenderer(myRender);
28 |
29 | // Render the view only when there is a change in the drawing data
30 | setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
31 | }
32 |
33 |
34 | //private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
35 | private static final float TOUCH_SCALE_FACTOR = 0.015f;
36 | private float mPreviousX;
37 | private float mPreviousY;
38 |
39 | @Override
40 | public boolean onTouchEvent(MotionEvent e) {
41 | // MotionEvent reports input details from the touch screen
42 | // and other input controls. In this case, you are only
43 | // interested in events where the touch position changed.
44 |
45 | float x = e.getX();
46 | float y = e.getY();
47 |
48 | switch (e.getAction()) {
49 | case MotionEvent.ACTION_MOVE:
50 |
51 | float dx = x - mPreviousX;
52 | //subtract, so the cube moves the same direction as your finger.
53 | //with plus it moves the opposite direction.
54 | myRender.setX(myRender.getX() - (dx * TOUCH_SCALE_FACTOR));
55 |
56 | float dy = y - mPreviousY;
57 | myRender.setY(myRender.getY() - (dy * TOUCH_SCALE_FACTOR));
58 | }
59 |
60 | mPreviousX = x;
61 | mPreviousY = y;
62 | return true;
63 | }
64 |
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/reveny/imgui/mod/test/myRenderer.java:
--------------------------------------------------------------------------------
1 | package com.reveny.imgui.mod.test;
2 |
3 | import android.content.Context;
4 | import android.opengl.GLES30;
5 | import android.opengl.Matrix;
6 | import android.opengl.GLSurfaceView;
7 | import android.util.Log;
8 |
9 | import javax.microedition.khronos.egl.EGLConfig;
10 | import javax.microedition.khronos.opengles.GL10;
11 |
12 | /**
13 | * Created by Seker on 7/2/2015.
14 | *
15 | *
16 | * Some code is uses from the OpenGL ES 3.0 programming guide second edition book. used under the MIT license.
17 | *
18 | */
19 | public class myRenderer implements GLSurfaceView.Renderer {
20 |
21 | private int mWidth;
22 | private int mHeight;
23 | private static String TAG = "myRenderer";
24 | private float mAngle =0;
25 | private float mTransY=0;
26 | private float mTransX=0;
27 | private static final float Z_NEAR = 1f;
28 | private static final float Z_FAR = 40f;
29 |
30 | // mMVPMatrix is an abbreviation for "Model View Projection Matrix"
31 | private final float[] mMVPMatrix = new float[16];
32 | private final float[] mProjectionMatrix = new float[16];
33 | private final float[] mViewMatrix = new float[16];
34 | private final float[] mRotationMatrix = new float[16];
35 |
36 | //
37 | public myRenderer(Context context) {
38 | //cube can not be instianated here, because of "no egl context" no clue.
39 | //do it in onSurfaceCreate and it is fine. odd, but workable solution.
40 | }
41 | ///
42 | // Create a shader object, load the shader source, and
43 | // compile the shader.
44 | //
45 | public static int LoadShader(int type, String shaderSrc) {
46 | int shader;
47 | int[] compiled = new int[1];
48 |
49 | // Create the shader object
50 | shader = GLES30.glCreateShader(type);
51 |
52 | if (shader == 0) {
53 | return 0;
54 | }
55 |
56 | // Load the shader source
57 | GLES30.glShaderSource(shader, shaderSrc);
58 |
59 | // Compile the shader
60 | GLES30.glCompileShader(shader);
61 |
62 | // Check the compile status
63 | GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compiled, 0);
64 |
65 | if (compiled[0] == 0) {
66 | Log.e(TAG, "Erorr!!!!");
67 | Log.e(TAG, GLES30.glGetShaderInfoLog(shader));
68 | GLES30.glDeleteShader(shader);
69 | return 0;
70 | }
71 |
72 | return shader;
73 | }
74 |
75 | /**
76 | * Utility method for debugging OpenGL calls. Provide the name of the call
77 | * just after making it:
78 | *
79 | *
80 | * mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor");
81 | * MyGLRenderer.checkGlError("glGetUniformLocation");
82 | *
83 | * If the operation is not successful, the check throws an error.
84 | *
85 | * @param glOperation - Name of the OpenGL call to check.
86 | */
87 | public static void checkGlError(String glOperation) {
88 | int error;
89 | while ((error = GLES30.glGetError()) != GLES30.GL_NO_ERROR) {
90 | Log.e(TAG, glOperation + ": glError " + error);
91 | throw new RuntimeException(glOperation + ": glError " + error);
92 | }
93 | }
94 |
95 | ///
96 | // Initialize the shader and program object
97 | //
98 | public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
99 |
100 |
101 | //set the clear buffer color to light gray.
102 | //GLES30.glClearColor(0.9f, .9f, 0.9f, 0.9f);
103 | //set the clear buffer color to a dark grey.
104 | GLES30.glClearColor(0.1f, .1f, 0.1f, 0.9f);
105 | //initialize the cube code for drawing.
106 | //if we had other objects setup them up here as well.
107 | }
108 |
109 | // /
110 | // Draw a triangle using the shader pair created in onSurfaceCreated()
111 | //
112 | public void onDrawFrame(GL10 glUnused) {
113 |
114 | // Clear the color buffer set above by glClearColor.
115 | GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
116 |
117 | //need this otherwise, it will over right stuff and the cube will look wrong!
118 | GLES30.glEnable(GLES30.GL_DEPTH_TEST);
119 |
120 | // Set the camera position (View matrix) note Matrix is an include, not a declared method.
121 | Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
122 |
123 | // Create a rotation and translation for the cube
124 | Matrix.setIdentityM(mRotationMatrix, 0);
125 |
126 | //move the cube up/down and left/right
127 | Matrix.translateM(mRotationMatrix, 0, mTransX, mTransY, 0);
128 |
129 | //mangle is how fast, x,y,z which directions it rotates.
130 | Matrix.rotateM(mRotationMatrix, 0, mAngle, 1.0f, 1.0f, 1.0f);
131 |
132 | // combine the model with the view matrix
133 | Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mRotationMatrix, 0);
134 |
135 | // combine the model-view with the projection matrix
136 | Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
137 |
138 | //change the angle, so the cube will spin.
139 | mAngle+=.4;
140 |
141 | }
142 |
143 | // /
144 | // Handle surface changes
145 | //
146 | public void onSurfaceChanged(GL10 glUnused, int width, int height) {
147 | mWidth = width;
148 | mHeight = height;
149 | // Set the viewport
150 | GLES30.glViewport(0, 0, mWidth, mHeight);
151 | float aspect = (float) width / height;
152 |
153 | // this projection matrix is applied to object coordinates
154 | //no idea why 53.13f, it was used in another example and it worked.
155 | Matrix.perspectiveM(mProjectionMatrix, 0, 53.13f, aspect, Z_NEAR, Z_FAR);
156 | }
157 |
158 | //used the touch listener to move the cube up/down (y) and left/right (x)
159 | public float getY() {
160 | return mTransY;
161 | }
162 |
163 | public void setY(float mY) {
164 | mTransY = mY;
165 | }
166 |
167 | public float getX() {
168 | return mTransX;
169 | }
170 |
171 | public void setX(float mX) {
172 | mTransX = mX;
173 | }
174 |
175 | }
--------------------------------------------------------------------------------
/app/src/main/jni/Build/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 | LOCAL_MODULE := libdobby
5 | LOCAL_SRC_FILES := $(LOCAL_PATH)/../Include/Dobby/$(TARGET_ARCH_ABI)/libdobby.a
6 | include $(PREBUILT_STATIC_LIBRARY)
7 |
8 | MAIN_LOCAL_PATH := $(call my-dir)
9 | LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)/../Include
10 |
11 | include $(CLEAR_VARS)
12 |
13 | LOCAL_MODULE := ModMenu
14 |
15 | # Code optimization
16 | LOCAL_CFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w
17 | LOCAL_CFLAGS += -fno-rtti -fexceptions -fpermissive
18 | LOCAL_CPPFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w -Werror -s -std=c++17
19 | LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fms-extensions -fno-rtti -fexceptions -fpermissive
20 | LOCAL_LDFLAGS += -Wl,--gc-sections, -llog
21 | LOCAL_ARM_MODE := arm
22 |
23 | LOCAL_STATIC_LIBRARIES := libdobby
24 | LOCAL_LDLIBS := -lz
25 | LOCAL_C_INCLUDES += $(LOCAL_PATH)/xdl/include
26 |
27 | LOCAL_SRC_FILES := ../Main/Main.cpp \
28 | ../Include/ImGui/backends/imgui_impl_opengl3.cpp \
29 | ../Include/ImGui/backends/imgui_impl_android.cpp \
30 | ../Include/ImGui/imgui.cpp \
31 | ../Include/ImGui/imgui_draw.cpp \
32 | ../Include/ImGui/imgui_demo.cpp \
33 | ../Include/ImGui/imgui_tables.cpp \
34 | ../Include/ImGui/imgui_widgets.cpp \
35 | ../Include/xdl/xdl.c \
36 | ../Include/xdl/xdl_iterate.c \
37 | ../Include/xdl/xdl_linker.c \
38 | ../Include/xdl/xdl_lzma.c \
39 | ../Include/xdl/xdl_util.c \
40 | ../Include/KittyMemory/KittyMemory.cpp \
41 | ../Include/KittyMemory/MemoryPatch.cpp \
42 | ../Include/KittyMemory/MemoryBackup.cpp \
43 | ../Include/KittyMemory/KittyUtils.cpp \
44 |
45 | LOCAL_LDLIBS := -llog -landroid -lz -lEGL -lGLESv3 -lGLESv2
46 |
47 | include $(BUILD_SHARED_LIBRARY)
48 |
49 | # Loader
50 | include $(CLEAR_VARS)
51 |
52 | LOCAL_MODULE := Loader
53 | LOCAL_CFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w
54 | LOCAL_CFLAGS += -fno-rtti -fexceptions -fpermissive
55 | LOCAL_CPPFLAGS := -Wno-error=format-security -fvisibility=hidden -ffunction-sections -fdata-sections -w -Werror -s -std=c++17
56 | LOCAL_CPPFLAGS += -Wno-error=c++11-narrowing -fms-extensions -fno-rtti -fexceptions -fpermissive
57 | LOCAL_LDFLAGS += -Wl,--gc-sections,--strip-all, -llog
58 | LOCAL_ARM_MODE := arm
59 |
60 | LOCAL_SRC_FILES := ../Loader/Loader.cpp \
61 | LOCAL_LDLIBS := -llog -landroid
62 |
63 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/app/src/main/jni/Build/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := arm64-v8a armeabi-v7a
2 | APP_STL := c++_static
3 | APP_OPTIM := release
4 | APP_THIN_ARCHIVE := true
5 | APP_PIE := true
--------------------------------------------------------------------------------
/app/src/main/jni/Include/Dobby/arm64-v8a/libdobby.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reveny/Android-ImGui-Mod-Menu/bbec8211d85eca58477e9322e6e30c13c205e687/app/src/main/jni/Include/Dobby/arm64-v8a/libdobby.a
--------------------------------------------------------------------------------
/app/src/main/jni/Include/Dobby/armeabi-v7a/libdobby.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reveny/Android-ImGui-Mod-Menu/bbec8211d85eca58477e9322e6e30c13c205e687/app/src/main/jni/Include/Dobby/armeabi-v7a/libdobby.a
--------------------------------------------------------------------------------
/app/src/main/jni/Include/Dobby/dobby.h:
--------------------------------------------------------------------------------
1 | #ifndef dobby_h
2 | #define dobby_h
3 |
4 | // obfuscated interface
5 | #if 0
6 | #define DobbyBuildVersion c343f74888dffad84d9ad08d9c433456
7 | #define DobbyHook c8dc3ffa44f22dbd10ccae213dd8b1f8
8 | #define DobbyInstrument b71e27bca2c362de90c1034f19d839f9
9 | #endif
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | #include
16 | #include
17 |
18 | void log_set_level(int level);
19 | void log_switch_to_syslog();
20 | void log_switch_to_file(const char *path);
21 |
22 | typedef enum {
23 | kMemoryOperationSuccess,
24 | kMemoryOperationError,
25 | kNotSupportAllocateExecutableMemory,
26 | kNotEnough,
27 | kNone
28 | } MemoryOperationError;
29 |
30 | #define PLATFORM_INTERFACE_CODE_PATCH_TOOL_H
31 | MemoryOperationError CodePatch(void *address, uint8_t *buffer, uint32_t buffer_size);
32 |
33 | typedef uintptr_t addr_t;
34 | typedef uint32_t addr32_t;
35 | typedef uint64_t addr64_t;
36 |
37 | #if defined(__arm64__) || defined(__aarch64__)
38 |
39 | #define ARM64_TMP_REG_NDX_0 17
40 |
41 | // float register
42 | typedef union _FPReg {
43 | __int128_t q;
44 | struct {
45 | double d1;
46 | double d2;
47 | } d;
48 | struct {
49 | float f1;
50 | float f2;
51 | float f3;
52 | float f4;
53 | } f;
54 | } FPReg;
55 |
56 | // register context
57 | typedef struct _RegisterContext {
58 | uint64_t dmmpy_0; // dummy placeholder
59 | uint64_t sp;
60 |
61 | uint64_t dmmpy_1; // dummy placeholder
62 | union {
63 | uint64_t x[29];
64 | struct {
65 | uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22,
66 | x23, x24, x25, x26, x27, x28;
67 | } regs;
68 | } general;
69 |
70 | uint64_t fp;
71 | uint64_t lr;
72 |
73 | union {
74 | FPReg q[32];
75 | struct {
76 | FPReg q0, q1, q2, q3, q4, q5, q6, q7;
77 | // [!!! READ ME !!!]
78 | // for Arm64, can't access q8 - q31, unless you enable full floating-point register pack
79 | FPReg q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29,
80 | q30, q31;
81 | } regs;
82 | } floating;
83 | } RegisterContext;
84 | #elif defined(__arm__)
85 | typedef struct _RegisterContext {
86 | uint32_t dummy_0;
87 | uint32_t dummy_1;
88 |
89 | uint32_t dummy_2;
90 | uint32_t sp;
91 |
92 | union {
93 | uint32_t r[13];
94 | struct {
95 | uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
96 | } regs;
97 | } general;
98 |
99 | uint32_t lr;
100 | } RegisterContext;
101 | #elif defined(_M_IX86) || defined(__i386__)
102 | typedef struct _RegisterContext {
103 | uint32_t dummy_0;
104 | uint32_t esp;
105 |
106 | uint32_t dummy_1;
107 | uint32_t flags;
108 |
109 | union {
110 | struct {
111 | uint32_t eax, ebx, ecx, edx, ebp, esp, edi, esi;
112 | } regs;
113 | } general;
114 |
115 | } RegisterContext;
116 | #elif defined(_M_X64) || defined(__x86_64__)
117 | typedef struct _RegisterContext {
118 | uint64_t dummy_0;
119 | uint64_t rsp;
120 |
121 | union {
122 | struct {
123 | uint64_t rax, rbx, rcx, rdx, rbp, rsp, rdi, rsi, r8, r9, r10, r11, r12, r13, r14, r15;
124 | } regs;
125 | } general;
126 |
127 | uint64_t dummy_1;
128 | uint64_t flags;
129 | } RegisterContext;
130 | #endif
131 |
132 | #define RT_FAILED -1
133 | #define RT_SUCCESS 0
134 | typedef enum _RetStatus { RS_FAILED = -1, RS_SUCCESS = 0 } RetStatus;
135 |
136 | typedef struct _HookEntryInfo {
137 | int hook_id;
138 | union {
139 | void *target_address;
140 | void *function_address;
141 | void *instruction_address;
142 | };
143 | } HookEntryInfo;
144 |
145 | // DobbyWrap <==> DobbyInstrument, so use DobbyInstrument instead of DobbyWrap
146 | #if 0
147 | // wrap function with pre_call and post_call
148 | typedef void (*PreCallTy)(RegisterContext *ctx, const HookEntryInfo *info);
149 | typedef void (*PostCallTy)(RegisterContext *ctx, const HookEntryInfo *info);
150 | int DobbyWrap(void *function_address, PreCallTy pre_call, PostCallTy post_call);
151 | #endif
152 |
153 | // return dobby build date
154 | const char *DobbyBuildVersion();
155 |
156 | // replace function
157 | int DobbyHook(void *address, void *replace_call, void **origin_call);
158 |
159 | // dynamic binary instrument for instruction
160 | // [!!! READ ME !!!]
161 | // for Arm64, can't access q8 - q31, unless you enable full floating-point register pack
162 | typedef void (*DBICallTy)(RegisterContext *ctx, const HookEntryInfo *info);
163 | int DobbyInstrument(void *address, DBICallTy dbi_call);
164 |
165 | // destory and restore hook
166 | int DobbyDestroy(void *address);
167 |
168 | // iterate symbol table and find symbol
169 | void *DobbySymbolResolver(const char *image_name, const char *symbol_name);
170 |
171 | // global offset table
172 | int DobbyGlobalOffsetTableReplace(char *image_name, char *symbol_name, void *fake_func, void **orig_func);
173 |
174 | // [!!! READ ME !!!]
175 | // for arm, Arm64, dobby will use b xxx instead of ldr absolute indirect branch
176 | // for x64, dobby always use absolute indirect jump
177 | #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__)
178 | void dobby_enable_near_branch_trampoline();
179 | void dobby_disable_near_branch_trampoline();
180 | #endif
181 |
182 | // register linker load image callback
183 | typedef void (*linker_load_callback_t)(const char *image_name, void *handle);
184 | void dobby_register_image_load_callback(linker_load_callback_t func);
185 |
186 | #ifdef __cplusplus
187 | }
188 | #endif
189 |
190 | #endif
191 |
--------------------------------------------------------------------------------
/app/src/main/jni/Include/Dobby/x86/libdobby.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reveny/Android-ImGui-Mod-Menu/bbec8211d85eca58477e9322e6e30c13c205e687/app/src/main/jni/Include/Dobby/x86/libdobby.a
--------------------------------------------------------------------------------
/app/src/main/jni/Include/Dobby/x86_64/libdobby.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reveny/Android-ImGui-Mod-Menu/bbec8211d85eca58477e9322e6e30c13c205e687/app/src/main/jni/Include/Dobby/x86_64/libdobby.a
--------------------------------------------------------------------------------
/app/src/main/jni/Include/Drawing.h:
--------------------------------------------------------------------------------
1 | //
2 | // Taken from https://github.com/Rev/Among-Us-Android-ESP/blob/main/Drawing.h
3 | //
4 |
5 | #ifndef ImGuiAndroid_ESP
6 | #define ImGuiAndroid_ESP
7 |
8 | #include "ImGui/imgui_internal.h"
9 |
10 | namespace ESP {
11 | void DrawLine(ImVec2 start, ImVec2 end, ImVec4 color) {
12 | auto background = ImGui::GetBackgroundDrawList();
13 |
14 | if(background) {
15 | background->AddLine(start, end, ImColor(color.x, color.y, color.z, color.w));
16 | }
17 | }
18 |
19 | void DrawBox(float x, float y, float z, float w, ImVec4 color) {
20 | ImVec2 v1(x, y);
21 | ImVec2 v2(x + z, y);
22 | ImVec2 v3(x + z, y + w);
23 | ImVec2 v4(x, y + w);
24 |
25 | DrawLine(v1, v2, color);
26 | DrawLine(v2, v3, color);
27 | DrawLine(v3, v4, color);
28 | DrawLine(v4, v1, color);
29 | }
30 |
31 | void DrawCircle(float X, float Y, float radius, bool filled, ImVec4 color) {
32 | auto background = ImGui::GetBackgroundDrawList();
33 |
34 | if(background) {
35 | if(filled) {
36 | background->AddCircleFilled(ImVec2(X, Y), radius, ImColor(color.x, color.y, color.z, color.w));
37 | } else {
38 | background->AddCircle(ImVec2(X, Y), radius, ImColor(color.x, color.y, color.z, color.w));
39 | }
40 | }
41 | }
42 |
43 | void DrawText2(float fontSize, ImVec2 position, ImVec4 color, const char *text) {
44 | auto background = ImGui::GetBackgroundDrawList();
45 |
46 | if(background) {
47 | background->AddText(NULL, fontSize, position, ImColor(color.x, color.y, color.z, color.w), text);
48 | }
49 | }
50 | }
51 |
52 | #endif //ImGuiAndroid_ESP
--------------------------------------------------------------------------------
/app/src/main/jni/Include/ImGui.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Reveny on 2022/12/25.
3 | //
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "ImGui/imgui.h"
11 | #include "Roboto-Regular.h"
12 | #include "ImGui/backends/imgui_impl_opengl3.h"
13 | #include "ImGui/backends/imgui_impl_android.h"
14 | #include "ImGui/backends/android_native_app_glue.h"
15 |
16 | #include "Utils.h"
17 | #include "Dobby/dobby.h"
18 | #include "Obfuscate.h"
19 | #include "Logger.h"
20 |
21 | void menuStyle();
22 | void (*menuAddress)();
23 |
24 | using swapbuffers_orig = EGLBoolean (*)(EGLDisplay dpy, EGLSurface surf);
25 | EGLBoolean swapbuffers_hook(EGLDisplay dpy, EGLSurface surf);
26 | swapbuffers_orig o_swapbuffers = nullptr;
27 |
28 | bool isInitialized = false;
29 | int glWidth = 0;
30 | int glHeight = 0;
31 |
32 | //Taken from https://github.com/fedes1to/Zygisk-ImGui-Menu/blob/main/module/src/main/cpp/hook.cpp
33 | #define HOOKINPUT(ret, func, ...) \
34 | ret (*orig##func)(__VA_ARGS__); \
35 | ret my##func(__VA_ARGS__)
36 |
37 | HOOKINPUT(void, Input, void *thiz, void *ex_ab, void *ex_ac) {
38 | origInput(thiz, ex_ab, ex_ac);
39 | ImGui_ImplAndroid_HandleInputEvent((AInputEvent *)thiz);
40 | return;
41 | }
42 |
43 | HOOKINPUT(int32_t, Consume, void *thiz, void *arg1, bool arg2, long arg3, uint32_t *arg4, AInputEvent **input_event)
44 | {
45 | auto result = origConsume(thiz, arg1, arg2, arg3, arg4, input_event);
46 | if(result != 0 || *input_event == nullptr) return result;
47 | ImGui_ImplAndroid_HandleInputEvent(*input_event);
48 | return result;
49 | }
50 |
51 | //This menu_addr is used to allow for multiple game support in the future
52 | void *initModMenu(void *menu_addr) {
53 | menuAddress = (void (*)())menu_addr;
54 | do {
55 | sleep(1);
56 | } while (!isLibraryLoaded(OBFUSCATE("libEGL.so")));
57 |
58 | auto swapBuffers = ((uintptr_t) DobbySymbolResolver(OBFUSCATE("libEGL.so"), OBFUSCATE("eglSwapBuffers")));
59 | KittyMemory::ProtectAddr((void *)swapBuffers, sizeof(swapBuffers), PROT_READ | PROT_WRITE | PROT_EXEC);
60 | DobbyHook((void *) swapBuffers, (void *) swapbuffers_hook, (void **) &o_swapbuffers);
61 |
62 | //Taken from https://github.com/fedes1to/Zygisk-ImGui-Menu/blob/main/module/src/main/cpp/hook.cpp
63 | void *sym_input = DobbySymbolResolver(OBFUSCATE("/system/lib/libinput.so"), OBFUSCATE("_ZN7android13InputConsumer21initializeMotionEventEPNS_11MotionEventEPKNS_12InputMessageE"));
64 |
65 | if (sym_input != nullptr) {
66 | DobbyHook((void *) sym_input, (void *) myInput, (void **) &origInput);
67 | } else {
68 | sym_input = DobbySymbolResolver(("/system/lib/libinput.so"), ("_ZN7android13InputConsumer7consumeEPNS_26InputEventFactoryInterfaceEblPjPPNS_10InputEventE"));
69 | if(NULL != sym_input) {
70 | DobbyHook(sym_input,(void *) myConsume,(void **) &origConsume);
71 | }
72 | } //c
73 |
74 | LOGI(OBFUSCATE("ImGUI Hooks initialized"));
75 | return nullptr;
76 | }
77 |
78 | void setupMenu() {
79 | if (isInitialized) return;
80 |
81 | auto ctx = ImGui::CreateContext();
82 | if (!ctx) {
83 | LOGI(OBFUSCATE("Failed to create context"));
84 | return;
85 | }
86 |
87 | ImGuiIO& io = ImGui::GetIO();
88 | io.DisplaySize = ImVec2((float)glWidth, (float)glHeight);
89 | io.ConfigWindowsMoveFromTitleBarOnly = true;
90 | io.IniFilename = nullptr;
91 |
92 | // Setup Platform/Renderer backends
93 | ImGui_ImplAndroid_Init();
94 | ImGui_ImplOpenGL3_Init("#version 300 es");
95 |
96 | int systemScale = (1.0 / glWidth) * glWidth;
97 | ImFontConfig font_cfg;
98 | font_cfg.SizePixels = systemScale * 22.0f;
99 | io.Fonts->AddFontFromMemoryTTF(Roboto_Regular, systemScale * 30.0, 40.0f);
100 |
101 | ImGui::GetStyle().ScaleAllSizes(2);
102 |
103 | isInitialized = true;
104 | LOGI("setup done.");
105 | }
106 | void internalDrawMenu(int width, int height) {
107 | if(!isInitialized) return;
108 |
109 | ImGuiIO &io = ImGui::GetIO();
110 |
111 | ImGui_ImplOpenGL3_NewFrame();
112 | ImGui_ImplAndroid_NewFrame(width, height);
113 | ImGui::NewFrame();
114 |
115 | menuAddress();
116 |
117 | ImGui::Render();
118 |
119 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
120 | }
121 |
122 | EGLBoolean swapbuffers_hook(EGLDisplay dpy, EGLSurface surf) {
123 | EGLint w, h;
124 | eglQuerySurface(dpy, surf, EGL_WIDTH, &w);
125 | eglQuerySurface(dpy, surf, EGL_HEIGHT, &h);
126 | glWidth = w;
127 | glHeight = h;
128 |
129 | setupMenu();
130 | internalDrawMenu(w, h);
131 |
132 | return o_swapbuffers(dpy, surf);
133 | }
134 |
--------------------------------------------------------------------------------
/app/src/main/jni/Include/ImGui/backends/android_native_app_glue.h:
--------------------------------------------------------------------------------
1 | #ifndef _ANDROID_NATIVE_APP_GLUE_H
2 | #define _ANDROID_NATIVE_APP_GLUE_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | /**
17 | * The native activity interface provided by
18 | * is based on a set of application-provided callbacks that will be called
19 | * by the Activity's main thread when certain events occur.
20 | *
21 | * This means that each one of this callbacks _should_ _not_ block, or they
22 | * risk having the system force-close the application. This programming
23 | * model is direct, lightweight, but constraining.
24 | *
25 | * The 'threaded_native_app' static library is used to provide a different
26 | * execution model where the application can implement its own main event
27 | * loop in a different thread instead. Here's how it works:
28 | *
29 | * 1/ The application must provide a function named "android_main()" that
30 | * will be called when the activity is created, in a new thread that is
31 | * distinct from the activity's main thread.
32 | *
33 | * 2/ android_main() receives a pointer to a valid "android_app" structure
34 | * that contains references to other important objects, e.g. the
35 | * ANativeActivity obejct instance the application is running in.
36 | *
37 | * 3/ the "android_app" object holds an ALooper instance that already
38 | * listens to two important things:
39 | *
40 | * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
41 | * declarations below.
42 | *
43 | * - input events coming from the AInputQueue attached to the activity.
44 | *
45 | * Each of these correspond to an ALooper identifier returned by
46 | * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
47 | * respectively.
48 | *
49 | * Your application can use the same ALooper to listen to additional
50 | * file-descriptors. They can either be callback based, or with return
51 | * identifiers starting with LOOPER_ID_USER.
52 | *
53 | * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
54 | * the returned data will point to an android_poll_source structure. You
55 | * can call the process() function on it, and fill in android_app->onAppCmd
56 | * and android_app->onInputEvent to be called for your own processing
57 | * of the event.
58 | *
59 | * Alternatively, you can call the low-level functions to read and process
60 | * the data directly... look at the process_cmd() and process_input()
61 | * implementations in the glue to see how to do this.
62 | *
63 | * See the sample named "native-activity" that comes with the NDK with a
64 | * full usage example. Also look at the JavaDoc of NativeActivity.
65 | */
66 |
67 | struct android_app;
68 |
69 | /**
70 | * Data associated with an ALooper fd that will be returned as the "outData"
71 | * when that source has data ready.
72 | */
73 | struct android_poll_source {
74 | // The identifier of this source. May be LOOPER_ID_MAIN or
75 | // LOOPER_ID_INPUT.
76 | int32_t id;
77 |
78 | // The android_app this ident is associated with.
79 | struct android_app* app;
80 |
81 | // Function to call to perform the standard processing of data from
82 | // this source.
83 | void (*process)(struct android_app* app, struct android_poll_source* source);
84 | };
85 |
86 | /**
87 | * This is the interface for the standard glue code of a threaded
88 | * application. In this model, the application's code is running
89 | * in its own thread separate from the main thread of the process.
90 | * It is not required that this thread be associated with the Java
91 | * VM, although it will need to be in order to make JNI calls any
92 | * Java objects.
93 | */
94 | struct android_app {
95 | // The application can place a pointer to its own state object
96 | // here if it likes.
97 | void* userData;
98 |
99 | // Fill this in with the function to process main app commands (APP_CMD_*)
100 | void (*onAppCmd)(struct android_app* app, int32_t cmd);
101 |
102 | // Fill this in with the function to process input events. At this point
103 | // the event has already been pre-dispatched, and it will be finished upon
104 | // return. Return 1 if you have handled the event, 0 for any default
105 | // dispatching.
106 | int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
107 |
108 | // The ANativeActivity object instance that this app is running in.
109 | ANativeActivity* activity;
110 |
111 | // The current configuration the app is running in.
112 | AConfiguration* config;
113 |
114 | // This is the last instance's saved state, as provided at creation time.
115 | // It is NULL if there was no state. You can use this as you need; the
116 | // memory will remain around until you call android_app_exec_cmd() for
117 | // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
118 | // These variables should only be changed when processing a APP_CMD_SAVE_STATE,
119 | // at which point they will be initialized to NULL and you can malloc your
120 | // state and place the information here. In that case the memory will be
121 | // freed for you later.
122 | void* savedState;
123 | size_t savedStateSize;
124 |
125 | // The ALooper associated with the app's thread.
126 | ALooper* looper;
127 |
128 | // When non-NULL, this is the input queue from which the app will
129 | // receive user input events.
130 | AInputQueue* inputQueue;
131 |
132 | // When non-NULL, this is the window surface that the app can draw in.
133 | ANativeWindow* window;
134 |
135 | // Current content rectangle of the window; this is the area where the
136 | // window's content should be placed to be seen by the user.
137 | ARect contentRect;
138 |
139 | // Current state of the app's activity. May be either APP_CMD_START,
140 | // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
141 | int activityState;
142 |
143 | // This is non-zero when the application's NativeActivity is being
144 | // destroyed and waiting for the app thread to complete.
145 | int destroyRequested;
146 |
147 | // -------------------------------------------------
148 | // Below are "private" implementation of the glue code.
149 |
150 | pthread_mutex_t mutex;
151 | pthread_cond_t cond;
152 |
153 | int msgread;
154 | int msgwrite;
155 |
156 | pthread_t thread;
157 |
158 | struct android_poll_source cmdPollSource;
159 | struct android_poll_source inputPollSource;
160 |
161 | int running;
162 | int stateSaved;
163 | int destroyed;
164 | int redrawNeeded;
165 | AInputQueue* pendingInputQueue;
166 | ANativeWindow* pendingWindow;
167 | ARect pendingContentRect;
168 | };
169 |
170 | enum {
171 | /**
172 | * Looper data ID of commands coming from the app's main thread, which
173 | * is returned as an identifier from ALooper_pollOnce(). The data for this
174 | * identifier is a pointer to an android_poll_source structure.
175 | * These can be retrieved and processed with android_app_read_cmd()
176 | * and android_app_exec_cmd().
177 | */
178 | LOOPER_ID_MAIN = 1,
179 |
180 | /**
181 | * Looper data ID of events coming from the AInputQueue of the
182 | * application's window, which is returned as an identifier from
183 | * ALooper_pollOnce(). The data for this identifier is a pointer to an
184 | * android_poll_source structure. These can be read via the inputQueue
185 | * object of android_app.
186 | */
187 | LOOPER_ID_INPUT = 2,
188 |
189 | /**
190 | * Start of user-defined ALooper identifiers.
191 | */
192 | LOOPER_ID_USER = 3,
193 | };
194 |
195 | enum {
196 | /**
197 | * Command from main thread: the AInputQueue has changed. Upon processing
198 | * this command, android_app->inputQueue will be updated to the new queue
199 | * (or NULL).
200 | */
201 | APP_CMD_INPUT_CHANGED,
202 |
203 | /**
204 | * Command from main thread: a new ANativeWindow is ready for use. Upon
205 | * receiving this command, android_app->window will contain the new window
206 | * surface.
207 | */
208 | APP_CMD_INIT_WINDOW,
209 |
210 | /**
211 | * Command from main thread: the existing ANativeWindow needs to be
212 | * terminated. Upon receiving this command, android_app->window still
213 | * contains the existing window; after calling android_app_exec_cmd
214 | * it will be set to NULL.
215 | */
216 | APP_CMD_TERM_WINDOW,
217 |
218 | /**
219 | * Command from main thread: the current ANativeWindow has been resized.
220 | * Please redraw with its new size.
221 | */
222 | APP_CMD_WINDOW_RESIZED,
223 |
224 | /**
225 | * Command from main thread: the system needs that the current ANativeWindow
226 | * be redrawn. You should redraw the window before handing this to
227 | * android_app_exec_cmd() in order to avoid transient drawing glitches.
228 | */
229 | APP_CMD_WINDOW_REDRAW_NEEDED,
230 |
231 | /**
232 | * Command from main thread: the content area of the window has changed,
233 | * such as from the soft input window being shown or hidden. You can
234 | * find the new content rect in android_app::contentRect.
235 | */
236 | APP_CMD_CONTENT_RECT_CHANGED,
237 |
238 | /**
239 | * Command from main thread: the app's activity window has gained
240 | * input focus.
241 | */
242 | APP_CMD_GAINED_FOCUS,
243 |
244 | /**
245 | * Command from main thread: the app's activity window has lost
246 | * input focus.
247 | */
248 | APP_CMD_LOST_FOCUS,
249 |
250 | /**
251 | * Command from main thread: the current device configuration has changed.
252 | */
253 | APP_CMD_CONFIG_CHANGED,
254 |
255 | /**
256 | * Command from main thread: the system is running low on memory.
257 | * Try to reduce your memory use.
258 | */
259 | APP_CMD_LOW_MEMORY,
260 |
261 | /**
262 | * Command from main thread: the app's activity has been started.
263 | */
264 | APP_CMD_START,
265 |
266 | /**
267 | * Command from main thread: the app's activity has been resumed.
268 | */
269 | APP_CMD_RESUME,
270 |
271 | /**
272 | * Command from main thread: the app should generate a new saved state
273 | * for itself, to restore from later if needed. If you have saved state,
274 | * allocate it with malloc and place it in android_app.savedState with
275 | * the size in android_app.savedStateSize. The will be freed for you
276 | * later.
277 | */
278 | APP_CMD_SAVE_STATE,
279 |
280 | /**
281 | * Command from main thread: the app's activity has been paused.
282 | */
283 | APP_CMD_PAUSE,
284 |
285 | /**
286 | * Command from main thread: the app's activity has been stopped.
287 | */
288 | APP_CMD_STOP,
289 |
290 | /**
291 | * Command from main thread: the app's activity is being destroyed,
292 | * and waiting for the app thread to clean up and exit before proceeding.
293 | */
294 | APP_CMD_DESTROY,
295 | };
296 |
297 | /**
298 | * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
299 | * app command message.
300 | */
301 | int8_t android_app_read_cmd(struct android_app* android_app);
302 |
303 | /**
304 | * Call with the command returned by android_app_read_cmd() to do the
305 | * initial pre-processing of the given command. You can perform your own
306 | * actions for the command after calling this function.
307 | */
308 | void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
309 |
310 | /**
311 | * Call with the command returned by android_app_read_cmd() to do the
312 | * final post-processing of the given command. You must have done your own
313 | * actions for the command before calling this function.
314 | */
315 | void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
316 |
317 | /**
318 | * Dummy function you can call to ensure glue code isn't stripped.
319 | */
320 | void app_dummy();
321 |
322 | /**
323 | * This is the function that application code must implement, representing
324 | * the main entry to the app.
325 | */
326 | extern void android_main(struct android_app* app);
327 |
328 | #ifdef __cplusplus
329 | }
330 | #endif
331 |
332 | #endif /* _ANDROID_NATIVE_APP_GLUE_H */
333 |
--------------------------------------------------------------------------------
/app/src/main/jni/Include/ImGui/backends/imgui_impl_android.cpp:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Binding for Android native app
2 | // This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
3 |
4 | // Implemented features:
5 | // [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
6 | // Missing features:
7 | // [ ] Platform: Clipboard support.
8 | // [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 | // [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
10 | // Important:
11 | // - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
12 | // - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
13 |
14 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
15 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
16 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
17 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
18 |
19 | // CHANGELOG
20 | // (minor and older changes stripped away, please see git history for details)
21 | // 2021-03-04: Initial version.
22 |
23 | #include "../imgui.h"
24 | #include "imgui_impl_android.h"
25 | #include
26 | #include