Skip to content
Browse files

New support modules, apkenv 42.3.14

  • Loading branch information...
1 parent ecff1c7 commit 0960ba0b865ff46daaeaa1a5cbb760db0a495ead @thp committed
Showing with 500 additions and 1 deletion.
  1. +1 −1 apkenv.h
  2. +6 −0 debian/changelog
  3. +214 −0 modules/cuttherope.c
  4. +279 −0 modules/worldofgoo.c
View
2 apkenv.h
@@ -34,7 +34,7 @@
#include "jni/jni.h"
#define APKENV_NAME "apkenv"
-#define APKENV_VERSION "42.1.1"
+#define APKENV_VERSION "42.3.14"
#define APKENV_WEBSITE "http://thp.io/2012/apkenv/"
#define APKENV_HEADLINE APKENV_NAME " " APKENV_VERSION " - " APKENV_WEBSITE
#define APKENV_COPYRIGHT "Copyright (c) 2012 Thomas Perl <m@thp.io>"
View
6 debian/changelog
@@ -1,3 +1,9 @@
+apkenv (42.3.15) unstable; urgency=low
+
+ * New Support Modules.
+
+ -- Thomas Perl <m@thp.io> Sun, 23 Dec 2012 15:16:37 +0100
+
apkenv (42.1.1) unstable; urgency=low
* Initial Release.
View
214 modules/cuttherope.c
@@ -0,0 +1,214 @@
+
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ **/
+
+/**
+ * Cut the Rope Lite - incomplete (but loading already works)
+ *
+ * Needs more love. Looks like they are rendering some things in Java,
+ * so in that case, we can't really do much apart from re-implementing
+ * everything from scratch - not something I'd do.
+ **/
+
+#include "common.h"
+
+#include <SDL/SDL.h>
+
+typedef void (*cuttherope_init_t)(JNIEnv *env, jobject obj, jobject resourceLoader, jobject soundManager, jobject preferences,
+ jobject saveManager, jobject flurry, jobject videoPlayer, jobject scorer,
+ jobject billingInterface, jobject remoteDataManager, jint x) SOFTFP;
+typedef void (*cuttherope_resize_t)(JNIEnv *env, jobject object, jint width, jint height, jboolean flag) SOFTFP;
+typedef void (*cuttherope_tick_t)(JNIEnv *env, jobject object, jlong tick) SOFTFP;
+typedef void (*cuttherope_render_t)(JNIEnv *env, jobject object) SOFTFP;
+typedef void (*cuttherope_videobannerfinished_t)(JNIEnv *env, jobject object) SOFTFP;
+
+struct SupportModulePriv {
+ jni_onload_t JNI_OnLoad;
+ cuttherope_init_t nativeInit;
+ cuttherope_resize_t nativeResize;
+ cuttherope_tick_t nativeTick;
+ cuttherope_render_t nativeRender;
+ cuttherope_videobannerfinished_t videoBannerFinished;
+
+ struct GlobalState *global;
+};
+static struct SupportModulePriv cuttherope_priv;
+
+static void
+cuttherope_video_banner_finished()
+{
+ cuttherope_priv.videoBannerFinished(ENV(cuttherope_priv.global),
+ cuttherope_priv.global);
+}
+
+
+static jobject
+cuttherope_CallObjectMethodV(JNIEnv *, jobject, jmethodID, va_list) SOFTFP;
+
+static void
+cuttherope_CallVoidMethodV(JNIEnv *, jobject, jmethodID, va_list) SOFTFP;
+
+static jobject
+cuttherope_CallStaticObjectMethodV(JNIEnv *, jclass, jmethodID, va_list) SOFTFP;
+
+
+static jobject
+cuttherope_CallObjectMethodV(JNIEnv *env, jobject p1, jmethodID p2, va_list p3)
+{
+ if (strcmp(p2->name, "loadData") == 0) {
+ struct dummy_jstring *arg;
+ arg = va_arg(p3, struct dummy_jstring*);
+ jboolean flag = va_arg(p3, jint);
+ (void)flag;
+
+ char *filename = malloc(strlen(arg->data) + strlen("assets/") + 1);
+ sprintf(filename, "assets/%s", arg->data);
+
+ char *buf;
+ size_t buf_size;
+ if (GLOBAL_J(env)->read_file(filename, &buf, &buf_size)) {
+ struct dummy_byte_array *array;
+ array = malloc(sizeof(struct dummy_byte_array));
+ array->data = buf;
+ array->size = buf_size;
+
+ // Poll for events here to avoid "not responding" messages
+ SDL_Event e;
+ while (SDL_PollEvent(&e));
+
+ return array;
+ } else {
+ return GLOBAL_J(env);
+ }
+ } else if (strcmp(p2->name, "getBytesOfBitmap") == 0) {
+ char *buf;
+ size_t buf_size;
+ if (GLOBAL_J(env)->read_file("assets/zeptolab.png", &buf, &buf_size)) {
+ struct dummy_byte_array *array;
+ array = malloc(sizeof(struct dummy_byte_array));
+ array->data = buf;
+ array->size = buf_size;
+ return array;
+ }
+ }
+ return GLOBAL_J(env);
+}
+
+static void
+cuttherope_CallVoidMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3)
+{
+ if (p2 && strcmp(p2->name, "showVideoBanner") == 0) {
+ cuttherope_video_banner_finished();
+ }
+}
+
+static jobject
+cuttherope_CallStaticObjectMethodV(JNIEnv *env, jclass p1, jmethodID p2, va_list p3)
+{
+ if (strcmp(p2->name, "getAppVersion") == 0) {
+ return (*env)->NewStringUTF(env, "1.0.0");
+ }
+ return NULL;
+}
+
+
+
+static int
+cuttherope_try_init(struct SupportModule *self)
+{
+ self->priv->JNI_OnLoad = (jni_onload_t)LOOKUP_M("JNI_OnLoad");
+ self->priv->nativeInit = (cuttherope_init_t)LOOKUP_M("nativeInit");
+ self->priv->nativeResize = (cuttherope_resize_t)LOOKUP_M("nativeResize");
+ self->priv->nativeTick = (cuttherope_tick_t)LOOKUP_M("nativeTick");
+ self->priv->nativeRender = (cuttherope_render_t)LOOKUP_M("nativeRender");
+ self->priv->videoBannerFinished = (cuttherope_videobannerfinished_t)LOOKUP_M("videoBannerFinished");
+
+ self->priv->global = GLOBAL_M;
+
+ self->override_env.CallObjectMethodV = cuttherope_CallObjectMethodV;
+ self->override_env.CallVoidMethodV = cuttherope_CallVoidMethodV;
+ self->override_env.CallStaticObjectMethodV = cuttherope_CallStaticObjectMethodV;
+
+ return (self->priv->JNI_OnLoad != NULL &&
+ self->priv->nativeInit != NULL &&
+ self->priv->nativeResize != NULL &&
+ self->priv->nativeTick != NULL &&
+ self->priv->videoBannerFinished != NULL);
+}
+
+static void
+cuttherope_init(struct SupportModule *self, int width, int height, const char *home)
+{
+ void *resourceLoader = (void*)0xF00;
+ void *soundManager = (void*)0xF01;
+ void *preferences = (void*)0xF02;
+ void *saveManager = (void*)0xF03;
+ void *flurry = (void*)0xF04;
+ void *videoPlayer = (void*)0xF05;
+ void *scorer = (void*)0xF06;
+ void *billingInterface = (void*)0xF07;
+ void *remoteDataManager = (void*)0xF08;
+
+ self->priv->JNI_OnLoad(VM_M, NULL);
+
+ self->priv->nativeInit(ENV_M, GLOBAL_M, resourceLoader, soundManager, preferences,
+ saveManager, flurry, videoPlayer, scorer,
+ billingInterface, remoteDataManager, 0);
+ self->priv->nativeResize(ENV_M, GLOBAL_M, width, height, 1);
+}
+
+static void
+cuttherope_input(struct SupportModule *self, int event, int x, int y, int finger)
+{
+}
+
+static void
+cuttherope_update(struct SupportModule *self)
+{
+ self->priv->nativeTick(ENV_M, GLOBAL_M, SDL_GetTicks());
+ self->priv->nativeRender(ENV_M, GLOBAL_M);
+}
+
+static void
+cuttherope_deinit(struct SupportModule *self)
+{
+}
+
+static void
+cuttherope_pause(struct SupportModule *self)
+{
+}
+
+static void
+cuttherope_resume(struct SupportModule *self)
+{
+}
+
+APKENV_MODULE(cuttherope, MODULE_PRIORITY_GAME)
+
View
279 modules/worldofgoo.c
@@ -0,0 +1,279 @@
+
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ **/
+
+
+/**
+ * World of Goo Demo - currently mostly broken (multi-threading GL issues)
+ *
+ * Use "r" on the hardware keyboard (so N950 only) to switch between
+ * running and paused state, use spacebar to temporarily enable rendering.
+ * If you time it just right (avoid rendering while background loading is
+ * in progress) you can even play the first level. YMMV.
+ **/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <SDL/SDL.h>
+#include <EGL/egl.h>
+
+#include "common.h"
+
+typedef void (*worldofgoo_init_t)(JNIEnv *env, jobject obj) SOFTFP;
+typedef void (*worldofgoo_oncreate_t)(JNIEnv *env, jobject obj, jboolean a, jboolean is_demo, jboolean c) SOFTFP;
+typedef void (*worldofgoo_resize_t)(void *env, jobject obj, jint width, jint height) SOFTFP;
+typedef void (*worldofgoo_render_t)(void *env, jobject obj, jboolean menu_pressed, jboolean back_pressed) SOFTFP;
+typedef void (*worldofgoo_input_t)(void *env, jobject obj, jint event, jfloat x, jfloat y, jint index) SOFTFP;
+
+struct SupportModulePriv {
+ worldofgoo_oncreate_t nativeOnCreate;
+ worldofgoo_init_t nativeOnSurfaceCreated;
+ worldofgoo_resize_t nativeResize;
+ worldofgoo_render_t nativeRender;
+ worldofgoo_input_t nativeTouchEvent;
+
+ const char *home_directory;
+ int running;
+};
+static struct SupportModulePriv worldofgoo_priv;
+
+
+struct ZipFileIndex {
+ char filename[1024];
+ int offset;
+ int length;
+};
+
+struct ZipFileIndex apk_index[2048];
+int apk_index_pos;
+
+void
+build_apk_index(const char *filename)
+{
+ size_t offset = 0;
+ FILE *fp = fopen(filename, "rb");
+
+ int compressed_size;
+ int uncompressed_size;
+ uint16_t filename_length;
+ uint16_t extrafield_length;
+
+ apk_index_pos = 0;
+ while (!feof(fp)) {
+ fseek(fp, offset, SEEK_SET);
+ if (fgetc(fp) != 'P') break;
+ if (fgetc(fp) != 'K') break;
+ if (fgetc(fp) != 3) break;
+ if (fgetc(fp) != 4) break;
+
+ fseek(fp, offset+18, SEEK_SET);
+ fread(&compressed_size, sizeof(int), 1, fp);
+ fread(&uncompressed_size, sizeof(int), 1, fp);
+ fread(&filename_length, sizeof(uint16_t), 1, fp);
+ fread(&extrafield_length, sizeof(uint16_t), 1, fp);
+
+ if (compressed_size == uncompressed_size) {
+ fseek(fp, offset+30, SEEK_SET);
+ fread(apk_index[apk_index_pos].filename, sizeof(char), filename_length, fp);
+ apk_index[apk_index_pos].filename[filename_length] = '\0';
+
+ apk_index[apk_index_pos].offset = offset+30+filename_length+extrafield_length;
+ apk_index[apk_index_pos].length = compressed_size;
+ }
+
+ offset += 30+filename_length+extrafield_length+compressed_size;
+ apk_index_pos++;
+ }
+ fclose(fp);
+ printf("Built APK index: %d entries\n", apk_index_pos);
+}
+
+jobject
+worldofgoo_CallObjectMethodV(JNIEnv *env, jobject p1, jmethodID p2, va_list p3) SOFTFP;
+
+jlong
+worldofgoo_CallLongMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3) SOFTFP;
+
+jboolean
+worldofgoo_CallBooleanMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3) SOFTFP;
+
+jint
+worldofgoo_AttachCurrentThread(JavaVM *, JNIEnv **, void *) SOFTFP;
+
+jint
+worldofgoo_DetachCurrentThread(JavaVM *vm) SOFTFP;
+
+
+jobject
+worldofgoo_CallObjectMethodV(JNIEnv *env, jobject p1, jmethodID p2, va_list p3)
+{
+ if (strcmp(p2->name, "getApkPath") == 0) {
+ return (*env)->NewStringUTF(env, GLOBAL_J(env)->apk_filename);
+ } else if (strcmp(p2->name, "getExternalStoragePath") == 0) {
+ return (*env)->NewStringUTF(env, worldofgoo_priv.home_directory);
+ } else if (strcmp(p2->name, "getInternalStoragePath") == 0) {
+ return (*env)->NewStringUTF(env, worldofgoo_priv.home_directory);
+ } else if (strcmp(p2->name, "getLanguage") == 0) {
+ return (*env)->NewStringUTF(env, "");
+ } else if (strcmp(p2->name, "playSound") == 0) {
+ // TODO: Play sound (doh!)
+ } else {
+ printf("Do not know what to do: %s\n", p2->name);
+ exit(1);
+ }
+ return GLOBAL_J(env);
+}
+
+jlong
+worldofgoo_CallLongMethodV(JNIEnv *p0, jobject p1, jmethodID p2, va_list p3)
+{
+ //printf("call long methodV: %s %s\n", p2->name, p2->sig);
+ struct dummy_jstring *str = va_arg(p3, struct dummy_jstring*);
+ int i;
+ if (strcmp(p2->name, "getAssetFileOffset") == 0) {
+ for (i=0; i<apk_index_pos-1; i++) {
+ if (strstr(apk_index[i].filename, str->data) != NULL) {
+ return apk_index[i].offset;
+ }
+ }
+ fprintf(stderr, "not found: %s\n", str->data);
+ return -1;
+ } else if (strcmp(p2->name, "getAssetFileLength") == 0) {
+ for (i=0; i<apk_index_pos-1; i++) {
+ if (strstr(apk_index[i].filename, str->data) != NULL) {
+ return apk_index[i].length;
+ }
+ }
+ fprintf(stderr, "not found: %s\n", str->data);
+ return -1;
+ }
+ return 0;
+}
+
+jboolean
+worldofgoo_CallBooleanMethodV(JNIEnv* p0, jobject p1, jmethodID p2, va_list p3)
+{
+ printf("worldofgoo_CallBooleanMethodV(%s)\n", p2->name);
+ if (strcmp(p2->name, "isGlThread") == 0) {
+ printf("isGlThread: %x\n", eglGetCurrentContext());
+ return eglGetCurrentContext() != 0;
+ }
+ return 0;
+}
+
+jint
+worldofgoo_AttachCurrentThread(JavaVM *vm, JNIEnv **env, void *args)
+{
+ printf("worldofgoo_AttachCurrentThread()\n");
+ struct GlobalState *global = (*vm)->reserved0;
+ *env = ENV(global);
+ return 0;
+}
+
+jint
+worldofgoo_DetachCurrentThread(JavaVM *vm)
+{
+ printf("worldofgoo_DetachCurrentThread()\n");
+ return 0;
+}
+
+
+static int
+worldofgoo_try_init(struct SupportModule *self)
+{
+ self->priv->nativeOnCreate = (worldofgoo_oncreate_t)LOOKUP_M("nativeOnCreate");
+ self->priv->nativeOnSurfaceCreated = (worldofgoo_init_t)LOOKUP_M("nativeOnSurfaceCreated");
+ self->priv->nativeResize = (worldofgoo_resize_t)LOOKUP_M("nativeResize");
+ self->priv->nativeRender = (worldofgoo_render_t)LOOKUP_M("nativeRender");
+ self->priv->nativeTouchEvent = (worldofgoo_input_t)LOOKUP_M("nativeTouchEvent");
+
+ self->override_env.CallObjectMethodV = worldofgoo_CallObjectMethodV;
+ self->override_env.CallLongMethodV = worldofgoo_CallLongMethodV;
+ self->override_env.CallBooleanMethodV = worldofgoo_CallBooleanMethodV;
+ self->override_vm.AttachCurrentThread = worldofgoo_AttachCurrentThread;
+ self->override_vm.DetachCurrentThread = worldofgoo_DetachCurrentThread;
+
+ return (self->priv->nativeOnCreate != NULL &&
+ self->priv->nativeOnSurfaceCreated != NULL &&
+ self->priv->nativeResize != NULL &&
+ self->priv->nativeRender != NULL &&
+ self->priv->nativeTouchEvent != NULL);
+}
+
+static void
+worldofgoo_init(struct SupportModule *self, int width, int height, const char *home)
+{
+ self->priv->home_directory = home;
+ build_apk_index(GLOBAL_M->apk_filename);
+ self->priv->nativeOnCreate(ENV_M, GLOBAL_M, JNI_FALSE, JNI_TRUE, JNI_FALSE);
+ self->priv->nativeOnSurfaceCreated(ENV_M, GLOBAL_M);
+ self->priv->nativeResize(ENV_M, GLOBAL_M, width, height);
+}
+
+static void
+worldofgoo_input(struct SupportModule *self, int event, int x, int y, int finger)
+{
+ self->priv->nativeTouchEvent(ENV_M, GLOBAL_M, event, x, y, finger);
+}
+
+static void
+worldofgoo_update(struct SupportModule *self)
+{
+ Uint8 *keystate = SDL_GetKeyState(NULL);
+ if (keystate[SDLK_SPACE] || self->priv->running) {
+ self->priv->nativeRender(ENV_M, GLOBAL_M, JNI_FALSE, JNI_FALSE);
+ if (!self->priv->running) {
+ usleep(200000);
+ }
+ }
+ if (keystate[SDLK_r]) {
+ self->priv->running = !self->priv->running;
+ usleep(100000);
+ }
+}
+
+static void
+worldofgoo_deinit(struct SupportModule *self)
+{
+}
+
+static void
+worldofgoo_pause(struct SupportModule *self)
+{
+}
+
+static void
+worldofgoo_resume(struct SupportModule *self)
+{
+}
+
+APKENV_MODULE(worldofgoo, MODULE_PRIORITY_GAME)
+

0 comments on commit 0960ba0

Please sign in to comment.
Something went wrong with that request. Please try again.