aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArslaan Pathan <[email protected]>2026-08-13 19:10:04 +1200
committerArslaan Pathan <[email protected]>2026-08-13 19:10:04 +1200
commit93d033a3c6734cf92c32b2219bbb9f8e3aea55bf (patch)
tree0e362221c8d654b02ca22d04ac2b6e8b82d9fcaf
parentc5b510b532ec9464995726ca02288c5edf0d6d2b (diff)
downloadmoku-assistant-93d033a3c6734cf92c32b2219bbb9f8e3aea55bf.tar.xz
moku-assistant-93d033a3c6734cf92c32b2219bbb9f8e3aea55bf.zip
Work on making a proper event loop and implementing more of the engine
-rw-r--r--AndroidManifest.xml2
-rw-r--r--Makefile2
-rw-r--r--jni/Android.mk2
-rw-r--r--jni/Application.mk1
-rw-r--r--jni/main.c132
5 files changed, 135 insertions, 4 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d2399c0..2ff66cb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arslaancodes.mokuassistant">
- <uses-sdk android:minSdkVersion="9" />
+ <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="34"/>
<application android:label="moku Assistant" android:hasCode="false">
<activity android:name="android.app.NativeActivity">
<meta-data android:name="android.app.lib_name"
diff --git a/Makefile b/Makefile
index 7ac6f95..1af4a69 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ moku-assistant.apk: AndroidManifest.xml libs/arm64-v8a/libmoku.so debug.keystore
rm -rf apk
mkdir -p apk/libs/arm64-v8a
cp libs/arm64-v8a/libmoku.so apk/libs/arm64-v8a
- aapt package -f -M AndroidManifest.xml -I ${ANDROID_SDK_ROOT}/platforms/android-34/android.jar -F moku-assistant.apk apk/
+ aapt package -f -M AndroidManifest.xml -I $(ANDROID_SDK_ROOT)/platforms/android-34/android.jar -F moku-assistant.apk apk/
apksigner sign --ks debug.keystore --ks-pass pass:android moku-assistant.apk
libs/arm64-v8a/libmoku.so:
diff --git a/jni/Android.mk b/jni/Android.mk
index b41aa2e..70d03d2 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -3,7 +3,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := moku
LOCAL_SRC_FILES := main.c
-LOCAL_LDLIBS := -llog -landroid
+LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
diff --git a/jni/Application.mk b/jni/Application.mk
index 9ddd3c4..5c3422c 100644
--- a/jni/Application.mk
+++ b/jni/Application.mk
@@ -1 +1,2 @@
APP_ABI := arm64-v8a
+APP_PLATFORM := android-25
diff --git a/jni/main.c b/jni/main.c
index f309e64..12ed679 100644
--- a/jni/main.c
+++ b/jni/main.c
@@ -1,17 +1,147 @@
#include <android_native_app_glue.h>
#include <android/log.h>
+#include <android/sensor.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <android/native_window.h>
+#include <android/set_abort_message.h>
+#include <android/choreographer.h>
+#include <android/hardware_buffer.h>
+#include <time.h>
+
+#define LOG_TAG "moku"
+
+#define _LOG(priority, fmt, ...) \
+ ((void)__android_log_print((priority), (LOG_TAG), \
+ (fmt)__VA_OPT__(, ) __VA_ARGS__))
+
+#define LOGE(fmt, ...) _LOG(ANDROID_LOG_ERROR, (fmt)__VA_OPT__(, ) __VA_ARGS__)
+#define LOGW(fmt, ...) _LOG(ANDROID_LOG_WARN, (fmt)__VA_OPT__(, ) __VA_ARGS__)
+#define LOGI(fmt, ...) _LOG(ANDROID_LOG_INFO, (fmt)__VA_OPT__(, ) __VA_ARGS__)
+
+enum Color {
+ COLOR_RED = 0x000000ff,
+ COLOR_GREEN = 0x0000ff00,
+ COLOR_BLUE = 0x00ff0000
+};
+
+struct engine {
+ struct android_app *app;
+ int window_initialized;
+ int running;
+ int color;
+ uint64_t last_update;
+};
+
+struct engine *engine_new(struct android_app* app) {
+ struct engine engine;
+
+ memset(&engine, 0, sizeof(engine));
+ engine.window_initialized = 0;
+ engine.app = app;
+ engine.running = 0;
+ engine.color = 0;
+ engine.last_update = (uint64_t)0;
+}
+
+uint64_t get_timestamp_ns() {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return (uint64_t)ts.tv_nsec + (uint64_t)ts.tv_sec * 1000000000;
+}
+
+static void engine_schedule_tick(struct engine *engine);
+
+static void engine_real_tick(struct engine *engine) {
+ if (!engine->running) return;
+
+ engine_schedule_tick(engine);
+}
+
+static void engine_tick(long frameTimeNanos, void *data) {
+ struct engine *engine;
+
+ if (!data) return;
+ engine = (struct engine*)data;
+
+ engine_real_tick(engine);
+}
+
+static void engine_schedule_tick(struct engine *engine) {
+ AChoreographer_postFrameCallback(AChoreographer_getInstance(), engine_tick, (void*)engine);
+}
+
+/* TODO implement these stubs */
+void engine_attach_window(struct engine *engine) {
+ if (ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) < 0) {
+ engine->window_initialized = 0;
+ return;
+ }
+ engine->window_initialized = 1;
+ engine->color = COLOR_RED;
+ engine->last_update = get_timestamp_ns();
+};
+
+void engine_detach_window(struct engine *engine) {
+ /* Called when native window for app is destroyed.
+ * Doesn't mean app is being killed, also happens on rotate
+ * Normally, with a traditional OpenGL app, do cleanup here
+ * At the moment, it's fine to just set a flag to disable the rendering loop
+ */
+ engine->window_initialized = 0;
+};
+
+void engine_resume(struct engine *engine) {
+ if (!engine->running) {
+ engine->running = 1;
+ engine_schedule_tick(engine);
+ }
+};
+
+
+void engine_pause(struct engine *engine) {
+
+};
+
+static void engine_handle_cmd(struct android_app *app, int32_t cmd) {
+ struct engine *engine;
+
+ engine = (struct engine *)app->userData;
+
+ switch (cmd) {
+ case APP_CMD_INIT_WINDOW:
+ engine_attach_window(engine);
+ break;
+ case APP_CMD_TERM_WINDOW:
+ engine_detach_window(engine);
+ break;
+ case APP_CMD_GAINED_FOCUS:
+ engine_resume(engine);
+ break;
+ case APP_CMD_LOST_FOCUS:
+ engine_pause(engine);
+ break;
+ }
+}
void android_main(struct android_app *state) {
/* Declarations */
struct android_poll_source *source;
+ struct engine engine;
int events;
/* Code starts here */
app_dummy();
+ memset(&engine, 0, sizeof(engine));
+ state->userData = &engine;
+ state->onAppCmd = engine_handle_cmd;
+
/* do stuff here */
- while (1) {
+ while (!state->destroyRequested) {
if (ALooper_pollAll(-1, NULL, &events, (void**)&source) >= 0) {
if (source) {
source->process(state, source);