Path: blob/master/dependencies/android/androidHelpers.cpp
774 views
#include <RSDK/Core/RetroEngine.hpp>1#include <main.hpp>2#include <pthread.h>34bool32 launched = false;5pthread_t mainthread;67using namespace RSDK;89static struct JNISetup _jni_setup = { 0 };1011android_app *app = NULL;1213jmethodID getFD = { 0 };14jmethodID writeLog = { 0 };1516jmethodID showLoading = { 0 };17jmethodID hideLoading = { 0 };18jmethodID setLoading = { 0 };19jmethodID setPixSize = { 0 };2021#if RETRO_USE_MOD_LOADER22jmethodID fsExists = { 0 };23jmethodID fsIsDir = { 0 };24jmethodID fsDirIter = { 0 };25jmethodID fsRecurseIter = { 0 };26#endif2728#include <game-activity/GameActivity.cpp>29#include <game-text-input/gametextinput.cpp>30extern "C" {31#include <game-activity/native_app_glue/android_native_app_glue.c>32}3334struct JNISetup *GetJNISetup()35{36app->activity->vm->AttachCurrentThread(&_jni_setup.env, NULL);37if (!_jni_setup.thiz) {38_jni_setup.thiz = app->activity->javaGameActivity;39_jni_setup.clazz = _jni_setup.env->GetObjectClass(_jni_setup.thiz);40}41return &_jni_setup;42}4344FileIO *fOpen(const char *path, const char *mode)45{46app->activity->vm->AttachCurrentThread(&_jni_setup.env, NULL);47jbyteArray jpath = _jni_setup.env->NewByteArray(strlen(path));48_jni_setup.env->SetByteArrayRegion(jpath, 0, strlen(path), (jbyte*)path);49int fd = _jni_setup.env->CallIntMethod(_jni_setup.thiz, getFD, jpath, mode[0]);50if (!fd)51return NULL;52return fdopen(fd, mode);53}5455/*56int fSeek(FileIO* file, long offset, int whence) {57return fseek(file, offset, whence);58}5960int fTell(FileIO* file) {61return ftell(file);62}//*/6364int32 AndroidToWinAPIMappings(int32 mapping)65{66switch (mapping) {67default: return KEYMAP_NO_MAPPING;68// case AKEYCODE_HOME: return VK_HOME;69case AKEYCODE_0: return VK_0;70case AKEYCODE_1: return VK_1;71case AKEYCODE_2: return VK_2;72case AKEYCODE_3: return VK_3;73case AKEYCODE_4: return VK_4;74case AKEYCODE_5: return VK_5;75case AKEYCODE_6: return VK_6;76case AKEYCODE_7: return VK_7;77case AKEYCODE_8: return VK_8;78case AKEYCODE_9: return VK_9;79case AKEYCODE_DPAD_UP: return VK_UP;80case AKEYCODE_DPAD_DOWN: return VK_DOWN;81case AKEYCODE_DPAD_LEFT: return VK_LEFT;82case AKEYCODE_DPAD_RIGHT: return VK_RIGHT;83case AKEYCODE_DPAD_CENTER: return VK_SELECT;84// case AKEYCODE_VOLUME_UP: return VK_VOLUME_UP;85// case AKEYCODE_VOLUME_DOWN: return VK_VOLUME_DOWN;86case AKEYCODE_CLEAR: return VK_CLEAR;87case AKEYCODE_A: return VK_A;88case AKEYCODE_B: return VK_B;89case AKEYCODE_C: return VK_C;90case AKEYCODE_D: return VK_D;91case AKEYCODE_E: return VK_E;92case AKEYCODE_F: return VK_F;93case AKEYCODE_G: return VK_G;94case AKEYCODE_H: return VK_H;95case AKEYCODE_I: return VK_I;96case AKEYCODE_J: return VK_J;97case AKEYCODE_K: return VK_K;98case AKEYCODE_L: return VK_L;99case AKEYCODE_M: return VK_M;100case AKEYCODE_N: return VK_N;101case AKEYCODE_O: return VK_O;102case AKEYCODE_P: return VK_P;103case AKEYCODE_Q: return VK_Q;104case AKEYCODE_R: return VK_R;105case AKEYCODE_S: return VK_S;106case AKEYCODE_T: return VK_T;107case AKEYCODE_U: return VK_U;108case AKEYCODE_V: return VK_V;109case AKEYCODE_W: return VK_W;110case AKEYCODE_X: return VK_X;111case AKEYCODE_Y: return VK_Y;112case AKEYCODE_Z: return VK_Z;113case AKEYCODE_COMMA: return VK_OEM_COMMA;114case AKEYCODE_PERIOD: return VK_OEM_PERIOD;115case AKEYCODE_ALT_LEFT: return VK_LMENU;116case AKEYCODE_ALT_RIGHT: return VK_RMENU;117case AKEYCODE_SHIFT_LEFT: return VK_LSHIFT;118case AKEYCODE_SHIFT_RIGHT: return VK_RSHIFT;119case AKEYCODE_TAB: return VK_TAB;120case AKEYCODE_SPACE: return VK_SPACE;121case AKEYCODE_ENVELOPE: return VK_LAUNCH_MAIL;122case AKEYCODE_ENTER: return VK_RETURN;123case AKEYCODE_MINUS: return VK_OEM_MINUS;124case AKEYCODE_MENU: return VK_MENU;125case AKEYCODE_MEDIA_PLAY_PAUSE: return VK_MEDIA_PLAY_PAUSE;126case AKEYCODE_MEDIA_STOP: return VK_MEDIA_STOP;127case AKEYCODE_MEDIA_NEXT: return VK_MEDIA_NEXT_TRACK;128case AKEYCODE_MEDIA_PREVIOUS: return VK_MEDIA_PREV_TRACK;129case AKEYCODE_MUTE: return VK_VOLUME_MUTE;130case AKEYCODE_PAGE_UP: return VK_PRIOR;131case AKEYCODE_PAGE_DOWN: return VK_NEXT;132case AKEYCODE_ESCAPE: return VK_ESCAPE;133case AKEYCODE_DEL: return VK_BACK; // ???????????? i hate android134case AKEYCODE_FORWARD_DEL: return VK_DELETE;135case AKEYCODE_CTRL_LEFT: return VK_LCONTROL;136case AKEYCODE_CTRL_RIGHT: return VK_RCONTROL;137case AKEYCODE_CAPS_LOCK: return VK_CAPITAL;138case AKEYCODE_SCROLL_LOCK: return VK_SCROLL;139case AKEYCODE_SYSRQ: return VK_SNAPSHOT;140case AKEYCODE_BREAK: return VK_PAUSE;141case AKEYCODE_MOVE_HOME: return VK_HOME;142case AKEYCODE_MOVE_END: return VK_END;143case AKEYCODE_INSERT: return VK_INSERT;144case AKEYCODE_F1: return VK_F1;145case AKEYCODE_F2: return VK_F2;146case AKEYCODE_F3: return VK_F3;147case AKEYCODE_F4: return VK_F4;148case AKEYCODE_F5: return VK_F5;149case AKEYCODE_F6: return VK_F6;150case AKEYCODE_F7: return VK_F7;151case AKEYCODE_F8: return VK_F8;152case AKEYCODE_F9: return VK_F9;153case AKEYCODE_F10: return VK_F10;154case AKEYCODE_F11: return VK_F11;155case AKEYCODE_F12: return VK_F12;156case AKEYCODE_NUM_LOCK: return VK_NUMLOCK;157case AKEYCODE_NUMPAD_0: return VK_NUMPAD0;158case AKEYCODE_NUMPAD_1: return VK_NUMPAD1;159case AKEYCODE_NUMPAD_2: return VK_NUMPAD2;160case AKEYCODE_NUMPAD_3: return VK_NUMPAD3;161case AKEYCODE_NUMPAD_4: return VK_NUMPAD4;162case AKEYCODE_NUMPAD_5: return VK_NUMPAD5;163case AKEYCODE_NUMPAD_6: return VK_NUMPAD6;164case AKEYCODE_NUMPAD_7: return VK_NUMPAD7;165case AKEYCODE_NUMPAD_8: return VK_NUMPAD8;166case AKEYCODE_NUMPAD_9: return VK_NUMPAD9;167case AKEYCODE_NUMPAD_DIVIDE: return VK_DIVIDE;168case AKEYCODE_NUMPAD_MULTIPLY: return VK_MULTIPLY;169case AKEYCODE_NUMPAD_SUBTRACT: return VK_SUBTRACT;170case AKEYCODE_NUMPAD_ADD: return VK_ADD;171case AKEYCODE_NUMPAD_DOT: return VK_DECIMAL;172case AKEYCODE_NUMPAD_COMMA: return VK_OEM_COMMA;173case AKEYCODE_NUMPAD_ENTER: return VK_RETURN;174// case AKEYCODE_VOLUME_MUTE: return VK_VOLUME_MUTE;175case AKEYCODE_ZOOM_IN: return VK_ZOOM;176case AKEYCODE_ZOOM_OUT: return VK_ZOOM;177case AKEYCODE_SLEEP: return VK_SLEEP;178case AKEYCODE_HELP: return VK_HELP;179}180}181182JNIEXPORT void JNICALL jnifunc(nativeOnTouch, RSDK, jint finger, jint action, jfloat x, jfloat y)183{184if (finger > 0x10)185return; // nah cause how tf186187bool32 down = (action == AMOTION_EVENT_ACTION_DOWN) || (action == AMOTION_EVENT_ACTION_MOVE) || (action == AMOTION_EVENT_ACTION_POINTER_DOWN);188189if (down) {190touchInfo.x[finger] = x;191touchInfo.y[finger] = y;192touchInfo.down[finger] = true;193if (touchInfo.count < finger + 1)194touchInfo.count = finger + 1;195}196else {197touchInfo.down[finger] = false;198if (touchInfo.count >= finger + 1) {199for (; touchInfo.count > 0; touchInfo.count--) {200if (touchInfo.down[touchInfo.count - 1])201break;202}203}204}205}206207JNIEXPORT jbyteArray JNICALL jnifunc(nativeLoadFile, RSDK, jstring file) {208const char* path = env->GetStringUTFChars(file, NULL);209FileInfo info;210InitFileInfo(&info);211if (LoadFile(&info, path, FMODE_RB)) {212jbyteArray ret = env->NewByteArray(info.fileSize);213jbyte* array = env->GetByteArrayElements(ret, NULL);214ReadBytes(&info, array, info.fileSize);215CloseFile(&info);216env->ReleaseByteArrayElements(ret, array, 0);217env->ReleaseStringUTFChars(file, path);218return ret;219}220env->ReleaseStringUTFChars(file, path);221return NULL;222}223224void ShowLoadingIcon() {225auto* jni = GetJNISetup();226jni->env->CallVoidMethod(jni->thiz, showLoading);227}228229void HideLoadingIcon() {230auto* jni = GetJNISetup();231jni->env->CallVoidMethod(jni->thiz, hideLoading);232}233234void SetLoadingIcon() {235auto* jni = GetJNISetup();236// cheating time237jstring name = jni->env->NewStringUTF("Data/Sprites/Android/Loading.bin");238jbyteArray waitSpinner = jniname(nativeLoadFile, RSDK)(jni->env, jni->clazz, name);239if (!waitSpinner) {240name = jni->env->NewStringUTF("Data/Sprites/UI/WaitSpinner.bin");241waitSpinner = jniname(nativeLoadFile, RSDK)(jni->env, jni->clazz, name);242}243jni->env->CallVoidMethod(jni->thiz, setLoading, waitSpinner);244}245246247void AndroidCommandCallback(android_app *app, int32 cmd)248{249PrintLog(PRINT_NORMAL, "COMMAND %d %d", cmd, app->window ? 1 : 0);250switch (cmd) {251case APP_CMD_INIT_WINDOW:252case APP_CMD_WINDOW_RESIZED:253case APP_CMD_CONFIG_CHANGED:254case APP_CMD_TERM_WINDOW:255videoSettings.windowState = WINDOWSTATE_INACTIVE;256RenderDevice::isInitialized = false;257RenderDevice::window = app->window;258#if RETRO_REV02259if (SKU::userCore)260SKU::userCore->focusState = 1;261#else262engine.focusState &= (~1);263#endif264if (app->window != NULL && cmd != APP_CMD_TERM_WINDOW) {265#if RETRO_REV02266if (SKU::userCore)267SKU::userCore->focusState = 0;268#else269engine.focusState |= 1;270#endif271videoSettings.windowState = WINDOWSTATE_ACTIVE;272SwappyGL_setWindow(app->window);273}274break;275case APP_CMD_STOP: Paddleboat_onStop(GetJNISetup()->env); break;276case APP_CMD_START: Paddleboat_onStart(GetJNISetup()->env); break;277case APP_CMD_GAINED_FOCUS: /*278#if RETRO_REV02279if (SKU::userCore)280SKU::userCore->focusState = 0;281#else282engine.focusState |= 1;283#endif284videoSettings.windowState = WINDOWSTATE_ACTIVE;//*/285break;286case APP_CMD_LOST_FOCUS: /*287#if RETRO_REV02288if (SKU::userCore)289SKU::userCore->focusState = 1;290#else291engine.focusState &= (~1);292#endif293videoSettings.windowState = WINDOWSTATE_INACTIVE; //*/294break;295default: break;296}297}298299bool AndroidKeyDownCallback(GameActivity *activity, const GameActivityKeyEvent *event)300{301if (Paddleboat_processGameActivityKeyInputEvent(event, sizeof(GameActivityKeyEvent)))302return true;303int32 keycode = event->keyCode;304305#if !RETRO_REV02306++RSDK::SKU::buttonDownCount;307#endif308switch (keycode) {309case AKEYCODE_ENTER:310311#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD312RSDK::SKU::specialKeyStates[1] = true;313#endif314// [fallthrough]315316default:317if (AndroidToWinAPIMappings(keycode)) {318319#if RETRO_INPUTDEVICE_KEYBOARD320SKU::UpdateKeyState(AndroidToWinAPIMappings(keycode));321#endif322return true;323}324return false;325326case AKEYCODE_ESCAPE:327if (engine.devMenu) {328#if RETRO_REV0U329if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)330#else331if (sceneInfo.state == ENGINESTATE_DEVMENU)332#endif333CloseDevMenu();334else335OpenDevMenu();336}337else {338#if RETRO_INPUTDEVICE_KEYBOARD339SKU::UpdateKeyState(AndroidToWinAPIMappings(keycode));340#endif341}342343#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD344RSDK::SKU::specialKeyStates[0] = true;345#endif346return true;347348#if !RETRO_USE_ORIGINAL_CODE349case AKEYCODE_F1:350sceneInfo.listPos--;351if (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart) {352sceneInfo.activeCategory--;353if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {354sceneInfo.activeCategory = sceneInfo.categoryCount - 1;355}356sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;357}358359LoadScene();360return true;361362case AKEYCODE_F2:363sceneInfo.listPos++;364if (sceneInfo.listPos >= sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd) {365sceneInfo.activeCategory++;366if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {367sceneInfo.activeCategory = 0;368}369sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;370}371372LoadScene();373return true;374#endif375376case AKEYCODE_F3:377if (userShaderCount)378videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;379return true;380381#if !RETRO_USE_ORIGINAL_CODE382case AKEYCODE_F5:383// Quick-Reload384LoadScene();385return true;386387case AKEYCODE_F6:388if (engine.devMenu && videoSettings.screenCount > 1)389videoSettings.screenCount--;390return true;391392case AKEYCODE_F7:393if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)394videoSettings.screenCount++;395return true;396397case AKEYCODE_F9:398if (engine.devMenu)399showHitboxes ^= 1;400return true;401402case AKEYCODE_F10:403if (engine.devMenu)404engine.showPaletteOverlay ^= 1;405return true;406#endif407case AKEYCODE_DEL:408if (engine.devMenu)409engine.gameSpeed = engine.fastForwardSpeed;410return true;411412case AKEYCODE_F11:413case AKEYCODE_INSERT:414if (engine.devMenu)415engine.frameStep = true;416return true;417418case AKEYCODE_F12:419case AKEYCODE_BREAK:420if (engine.devMenu) {421#if RETRO_REV0U422switch (engine.version) {423default: break;424case 5:425if (sceneInfo.state != ENGINESTATE_NONE)426sceneInfo.state ^= ENGINESTATE_STEPOVER;427break;428case 4:429case 3:430if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)431RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;432break;433}434#else435if (sceneInfo.state != ENGINESTATE_NONE)436sceneInfo.state ^= ENGINESTATE_STEPOVER;437#endif438}439return true;440}441return false;442}443444bool AndroidKeyUpCallback(GameActivity *activity, const GameActivityKeyEvent *event)445{446if (Paddleboat_processGameActivityKeyInputEvent(event, sizeof(GameActivityKeyEvent)))447return true;448449int32 keycode = event->keyCode;450#if !RETRO_REV02451--RSDK::SKU::buttonDownCount;452#endif453switch (keycode) {454default:455#if RETRO_INPUTDEVICE_KEYBOARD456SKU::ClearKeyState(AndroidToWinAPIMappings(keycode));457#endif458return true;459460#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD461case AKEYCODE_ESCAPE: RSDK::SKU::specialKeyStates[0] = false; return true;462case AKEYCODE_ENTER: RSDK::SKU::specialKeyStates[1] = false; return true;463#endif464case AKEYCODE_DEL: engine.gameSpeed = 1; return true;465}466return false;467}468469