You've already forked RSDKv5-Decompilation
mirror of
https://github.com/izzy2lost/RSDKv5-Decompilation.git
synced 2026-03-26 16:42:45 -07:00
c7164fb06b
added loading icon to android will check `Data/Sprites/Android/Loading.bin` and then `Data/Sprites/UI/WaitSpinner.bin` fades in and out, renders outside of game
467 lines
16 KiB
C++
467 lines
16 KiB
C++
#include <RSDK/Core/RetroEngine.hpp>
|
|
#include <main.hpp>
|
|
#include <pthread.h>
|
|
|
|
bool32 launched = false;
|
|
pthread_t mainthread;
|
|
|
|
using namespace RSDK;
|
|
|
|
static struct JNISetup _jni_setup = { 0 };
|
|
|
|
android_app *app = NULL;
|
|
|
|
jmethodID getFD = { 0 };
|
|
jmethodID writeLog = { 0 };
|
|
|
|
jmethodID showLoading = { 0 };
|
|
jmethodID hideLoading = { 0 };
|
|
jmethodID setLoading = { 0 };
|
|
jmethodID setPixSize = { 0 };
|
|
|
|
#if RETRO_USE_MOD_LOADER
|
|
jmethodID fsExists = { 0 };
|
|
jmethodID fsIsDir = { 0 };
|
|
jmethodID fsDirIter = { 0 };
|
|
jmethodID fsRecurseIter = { 0 };
|
|
#endif
|
|
|
|
#include <game-activity/GameActivity.cpp>
|
|
#include <game-text-input/gametextinput.cpp>
|
|
extern "C" {
|
|
#include <game-activity/native_app_glue/android_native_app_glue.c>
|
|
}
|
|
|
|
struct JNISetup *GetJNISetup()
|
|
{
|
|
app->activity->vm->AttachCurrentThread(&_jni_setup.env, NULL);
|
|
if (!_jni_setup.thiz) {
|
|
_jni_setup.thiz = app->activity->javaGameActivity;
|
|
_jni_setup.clazz = _jni_setup.env->GetObjectClass(_jni_setup.thiz);
|
|
}
|
|
return &_jni_setup;
|
|
}
|
|
|
|
FileIO *fOpen(const char *path, const char *mode)
|
|
{
|
|
app->activity->vm->AttachCurrentThread(&_jni_setup.env, NULL);
|
|
jbyteArray jpath = _jni_setup.env->NewByteArray(strlen(path));
|
|
_jni_setup.env->SetByteArrayRegion(jpath, 0, strlen(path), (jbyte*)path);
|
|
int fd = _jni_setup.env->CallIntMethod(_jni_setup.thiz, getFD, jpath, mode[0]);
|
|
if (!fd)
|
|
return NULL;
|
|
return fdopen(fd, mode);
|
|
}
|
|
|
|
/*
|
|
int fSeek(FileIO* file, long offset, int whence) {
|
|
return fseek(file, offset, whence);
|
|
}
|
|
|
|
int fTell(FileIO* file) {
|
|
return ftell(file);
|
|
}//*/
|
|
|
|
int32 AndroidToWinAPIMappings(int32 mapping)
|
|
{
|
|
switch (mapping) {
|
|
default: return KEYMAP_NO_MAPPING;
|
|
// case AKEYCODE_HOME: return VK_HOME;
|
|
case AKEYCODE_0: return VK_0;
|
|
case AKEYCODE_1: return VK_1;
|
|
case AKEYCODE_2: return VK_2;
|
|
case AKEYCODE_3: return VK_3;
|
|
case AKEYCODE_4: return VK_4;
|
|
case AKEYCODE_5: return VK_5;
|
|
case AKEYCODE_6: return VK_6;
|
|
case AKEYCODE_7: return VK_7;
|
|
case AKEYCODE_8: return VK_8;
|
|
case AKEYCODE_9: return VK_9;
|
|
case AKEYCODE_DPAD_UP: return VK_UP;
|
|
case AKEYCODE_DPAD_DOWN: return VK_DOWN;
|
|
case AKEYCODE_DPAD_LEFT: return VK_LEFT;
|
|
case AKEYCODE_DPAD_RIGHT: return VK_RIGHT;
|
|
case AKEYCODE_DPAD_CENTER: return VK_SELECT;
|
|
// case AKEYCODE_VOLUME_UP: return VK_VOLUME_UP;
|
|
// case AKEYCODE_VOLUME_DOWN: return VK_VOLUME_DOWN;
|
|
case AKEYCODE_CLEAR: return VK_CLEAR;
|
|
case AKEYCODE_A: return VK_A;
|
|
case AKEYCODE_B: return VK_B;
|
|
case AKEYCODE_C: return VK_C;
|
|
case AKEYCODE_D: return VK_D;
|
|
case AKEYCODE_E: return VK_E;
|
|
case AKEYCODE_F: return VK_F;
|
|
case AKEYCODE_G: return VK_G;
|
|
case AKEYCODE_H: return VK_H;
|
|
case AKEYCODE_I: return VK_I;
|
|
case AKEYCODE_J: return VK_J;
|
|
case AKEYCODE_K: return VK_K;
|
|
case AKEYCODE_L: return VK_L;
|
|
case AKEYCODE_M: return VK_M;
|
|
case AKEYCODE_N: return VK_N;
|
|
case AKEYCODE_O: return VK_O;
|
|
case AKEYCODE_P: return VK_P;
|
|
case AKEYCODE_Q: return VK_Q;
|
|
case AKEYCODE_R: return VK_R;
|
|
case AKEYCODE_S: return VK_S;
|
|
case AKEYCODE_T: return VK_T;
|
|
case AKEYCODE_U: return VK_U;
|
|
case AKEYCODE_V: return VK_V;
|
|
case AKEYCODE_W: return VK_W;
|
|
case AKEYCODE_X: return VK_X;
|
|
case AKEYCODE_Y: return VK_Y;
|
|
case AKEYCODE_Z: return VK_Z;
|
|
case AKEYCODE_COMMA: return VK_OEM_COMMA;
|
|
case AKEYCODE_PERIOD: return VK_OEM_PERIOD;
|
|
case AKEYCODE_ALT_LEFT: return VK_LMENU;
|
|
case AKEYCODE_ALT_RIGHT: return VK_RMENU;
|
|
case AKEYCODE_SHIFT_LEFT: return VK_LSHIFT;
|
|
case AKEYCODE_SHIFT_RIGHT: return VK_RSHIFT;
|
|
case AKEYCODE_TAB: return VK_TAB;
|
|
case AKEYCODE_SPACE: return VK_SPACE;
|
|
case AKEYCODE_ENVELOPE: return VK_LAUNCH_MAIL;
|
|
case AKEYCODE_ENTER: return VK_RETURN;
|
|
case AKEYCODE_MINUS: return VK_OEM_MINUS;
|
|
case AKEYCODE_MENU: return VK_MENU;
|
|
case AKEYCODE_MEDIA_PLAY_PAUSE: return VK_MEDIA_PLAY_PAUSE;
|
|
case AKEYCODE_MEDIA_STOP: return VK_MEDIA_STOP;
|
|
case AKEYCODE_MEDIA_NEXT: return VK_MEDIA_NEXT_TRACK;
|
|
case AKEYCODE_MEDIA_PREVIOUS: return VK_MEDIA_PREV_TRACK;
|
|
case AKEYCODE_MUTE: return VK_VOLUME_MUTE;
|
|
case AKEYCODE_PAGE_UP: return VK_PRIOR;
|
|
case AKEYCODE_PAGE_DOWN: return VK_NEXT;
|
|
case AKEYCODE_ESCAPE: return VK_ESCAPE;
|
|
case AKEYCODE_DEL: return VK_BACK; // ???????????? i hate android
|
|
case AKEYCODE_FORWARD_DEL: return VK_DELETE;
|
|
case AKEYCODE_CTRL_LEFT: return VK_LCONTROL;
|
|
case AKEYCODE_CTRL_RIGHT: return VK_RCONTROL;
|
|
case AKEYCODE_CAPS_LOCK: return VK_CAPITAL;
|
|
case AKEYCODE_SCROLL_LOCK: return VK_SCROLL;
|
|
case AKEYCODE_SYSRQ: return VK_SNAPSHOT;
|
|
case AKEYCODE_BREAK: return VK_PAUSE;
|
|
case AKEYCODE_MOVE_HOME: return VK_HOME;
|
|
case AKEYCODE_MOVE_END: return VK_END;
|
|
case AKEYCODE_INSERT: return VK_INSERT;
|
|
case AKEYCODE_F1: return VK_F1;
|
|
case AKEYCODE_F2: return VK_F2;
|
|
case AKEYCODE_F3: return VK_F3;
|
|
case AKEYCODE_F4: return VK_F4;
|
|
case AKEYCODE_F5: return VK_F5;
|
|
case AKEYCODE_F6: return VK_F6;
|
|
case AKEYCODE_F7: return VK_F7;
|
|
case AKEYCODE_F8: return VK_F8;
|
|
case AKEYCODE_F9: return VK_F9;
|
|
case AKEYCODE_F10: return VK_F10;
|
|
case AKEYCODE_F11: return VK_F11;
|
|
case AKEYCODE_F12: return VK_F12;
|
|
case AKEYCODE_NUM_LOCK: return VK_NUMLOCK;
|
|
case AKEYCODE_NUMPAD_0: return VK_NUMPAD0;
|
|
case AKEYCODE_NUMPAD_1: return VK_NUMPAD1;
|
|
case AKEYCODE_NUMPAD_2: return VK_NUMPAD2;
|
|
case AKEYCODE_NUMPAD_3: return VK_NUMPAD3;
|
|
case AKEYCODE_NUMPAD_4: return VK_NUMPAD4;
|
|
case AKEYCODE_NUMPAD_5: return VK_NUMPAD5;
|
|
case AKEYCODE_NUMPAD_6: return VK_NUMPAD6;
|
|
case AKEYCODE_NUMPAD_7: return VK_NUMPAD7;
|
|
case AKEYCODE_NUMPAD_8: return VK_NUMPAD8;
|
|
case AKEYCODE_NUMPAD_9: return VK_NUMPAD9;
|
|
case AKEYCODE_NUMPAD_DIVIDE: return VK_DIVIDE;
|
|
case AKEYCODE_NUMPAD_MULTIPLY: return VK_MULTIPLY;
|
|
case AKEYCODE_NUMPAD_SUBTRACT: return VK_SUBTRACT;
|
|
case AKEYCODE_NUMPAD_ADD: return VK_ADD;
|
|
case AKEYCODE_NUMPAD_DOT: return VK_DECIMAL;
|
|
case AKEYCODE_NUMPAD_COMMA: return VK_OEM_COMMA;
|
|
case AKEYCODE_NUMPAD_ENTER: return VK_RETURN;
|
|
// case AKEYCODE_VOLUME_MUTE: return VK_VOLUME_MUTE;
|
|
case AKEYCODE_ZOOM_IN: return VK_ZOOM;
|
|
case AKEYCODE_ZOOM_OUT: return VK_ZOOM;
|
|
case AKEYCODE_SLEEP: return VK_SLEEP;
|
|
case AKEYCODE_HELP: return VK_HELP;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL jnifunc(nativeOnTouch, RSDK, jint finger, jint action, jfloat x, jfloat y)
|
|
{
|
|
if (finger > 0x10)
|
|
return; // nah cause how tf
|
|
|
|
bool32 down = (action == AMOTION_EVENT_ACTION_DOWN) || (action == AMOTION_EVENT_ACTION_MOVE) || (action == AMOTION_EVENT_ACTION_POINTER_DOWN);
|
|
|
|
if (down) {
|
|
touchInfo.x[finger] = x;
|
|
touchInfo.y[finger] = y;
|
|
touchInfo.down[finger] = true;
|
|
if (touchInfo.count < finger + 1)
|
|
touchInfo.count = finger + 1;
|
|
}
|
|
else {
|
|
touchInfo.down[finger] = false;
|
|
if (touchInfo.count >= finger + 1) {
|
|
for (; touchInfo.count > 0; touchInfo.count--) {
|
|
if (touchInfo.down[touchInfo.count - 1])
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL jnifunc(nativeLoadFile, RSDK, jstring file) {
|
|
const char* path = env->GetStringUTFChars(file, NULL);
|
|
FileInfo info;
|
|
InitFileInfo(&info);
|
|
if (LoadFile(&info, path, FMODE_RB)) {
|
|
jbyteArray ret = env->NewByteArray(info.fileSize);
|
|
jbyte* array = env->GetByteArrayElements(ret, NULL);
|
|
ReadBytes(&info, array, info.fileSize);
|
|
CloseFile(&info);
|
|
env->ReleaseByteArrayElements(ret, array, 0);
|
|
env->ReleaseStringUTFChars(file, path);
|
|
return ret;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void ShowLoadingIcon() {
|
|
auto* jni = GetJNISetup();
|
|
jni->env->CallVoidMethod(jni->thiz, showLoading);
|
|
}
|
|
|
|
void HideLoadingIcon() {
|
|
auto* jni = GetJNISetup();
|
|
jni->env->CallVoidMethod(jni->thiz, hideLoading);
|
|
}
|
|
|
|
void SetLoadingIcon() {
|
|
auto* jni = GetJNISetup();
|
|
// cheating time
|
|
jstring name = jni->env->NewStringUTF("Data/Sprites/Android/Loading.bin");
|
|
jbyteArray waitSpinner = jniname(nativeLoadFile, RSDK)(jni->env, jni->clazz, name);
|
|
if (!waitSpinner) {
|
|
name = jni->env->NewStringUTF("Data/Sprites/UI/WaitSpinner.bin");
|
|
waitSpinner = jniname(nativeLoadFile, RSDK)(jni->env, jni->clazz, name);
|
|
}
|
|
jni->env->CallVoidMethod(jni->thiz, setLoading, waitSpinner);
|
|
}
|
|
|
|
|
|
void AndroidCommandCallback(android_app *app, int32 cmd)
|
|
{
|
|
PrintLog(PRINT_NORMAL, "COMMAND %d %d", cmd, app->window ? 1 : 0);
|
|
switch (cmd) {
|
|
case APP_CMD_INIT_WINDOW:
|
|
case APP_CMD_WINDOW_RESIZED:
|
|
case APP_CMD_CONFIG_CHANGED:
|
|
case APP_CMD_TERM_WINDOW:
|
|
videoSettings.windowState = WINDOWSTATE_INACTIVE;
|
|
RenderDevice::isInitialized = false;
|
|
RenderDevice::window = app->window;
|
|
#if RETRO_REV02
|
|
if (SKU::userCore)
|
|
SKU::userCore->focusState = 1;
|
|
#else
|
|
engine.focusState &= (~1);
|
|
#endif
|
|
if (app->window != NULL && cmd != APP_CMD_TERM_WINDOW) {
|
|
#if RETRO_REV02
|
|
if (SKU::userCore)
|
|
SKU::userCore->focusState = 0;
|
|
#else
|
|
engine.focusState |= 1;
|
|
#endif
|
|
videoSettings.windowState = WINDOWSTATE_ACTIVE;
|
|
SwappyGL_setWindow(app->window);
|
|
}
|
|
break;
|
|
case APP_CMD_STOP: Paddleboat_onStop(GetJNISetup()->env); break;
|
|
case APP_CMD_START: Paddleboat_onStart(GetJNISetup()->env); break;
|
|
case APP_CMD_GAINED_FOCUS: /*
|
|
#if RETRO_REV02
|
|
if (SKU::userCore)
|
|
SKU::userCore->focusState = 0;
|
|
#else
|
|
engine.focusState |= 1;
|
|
#endif
|
|
videoSettings.windowState = WINDOWSTATE_ACTIVE;//*/
|
|
break;
|
|
case APP_CMD_LOST_FOCUS: /*
|
|
#if RETRO_REV02
|
|
if (SKU::userCore)
|
|
SKU::userCore->focusState = 1;
|
|
#else
|
|
engine.focusState &= (~1);
|
|
#endif
|
|
videoSettings.windowState = WINDOWSTATE_INACTIVE; //*/
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
bool AndroidKeyDownCallback(GameActivity *activity, const GameActivityKeyEvent *event)
|
|
{
|
|
if (Paddleboat_processGameActivityKeyInputEvent(event, sizeof(GameActivityKeyEvent)))
|
|
return true;
|
|
int32 keycode = event->keyCode;
|
|
|
|
#if !RETRO_REV02
|
|
++RSDK::SKU::buttonDownCount;
|
|
#endif
|
|
switch (keycode) {
|
|
case AKEYCODE_ENTER:
|
|
|
|
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
|
|
RSDK::SKU::specialKeyStates[1] = true;
|
|
#endif
|
|
// [fallthrough]
|
|
|
|
default:
|
|
if (AndroidToWinAPIMappings(keycode)) {
|
|
|
|
#if RETRO_INPUTDEVICE_KEYBOARD
|
|
SKU::UpdateKeyState(AndroidToWinAPIMappings(keycode));
|
|
#endif
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case AKEYCODE_ESCAPE:
|
|
if (engine.devMenu) {
|
|
#if RETRO_REV0U
|
|
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
|
|
#else
|
|
if (sceneInfo.state == ENGINESTATE_DEVMENU)
|
|
#endif
|
|
CloseDevMenu();
|
|
else
|
|
OpenDevMenu();
|
|
}
|
|
else {
|
|
#if RETRO_INPUTDEVICE_KEYBOARD
|
|
SKU::UpdateKeyState(AndroidToWinAPIMappings(keycode));
|
|
#endif
|
|
}
|
|
|
|
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
|
|
RSDK::SKU::specialKeyStates[0] = true;
|
|
#endif
|
|
return true;
|
|
|
|
#if !RETRO_USE_ORIGINAL_CODE
|
|
case AKEYCODE_F1:
|
|
sceneInfo.listPos--;
|
|
if (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart) {
|
|
sceneInfo.activeCategory--;
|
|
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
|
|
sceneInfo.activeCategory = sceneInfo.categoryCount - 1;
|
|
}
|
|
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;
|
|
}
|
|
|
|
LoadScene();
|
|
return true;
|
|
|
|
case AKEYCODE_F2:
|
|
sceneInfo.listPos++;
|
|
if (sceneInfo.listPos >= sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd) {
|
|
sceneInfo.activeCategory++;
|
|
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
|
|
sceneInfo.activeCategory = 0;
|
|
}
|
|
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;
|
|
}
|
|
|
|
LoadScene();
|
|
return true;
|
|
#endif
|
|
|
|
case AKEYCODE_F3:
|
|
if (userShaderCount)
|
|
videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;
|
|
return true;
|
|
|
|
#if !RETRO_USE_ORIGINAL_CODE
|
|
case AKEYCODE_F5:
|
|
// Quick-Reload
|
|
LoadScene();
|
|
return true;
|
|
|
|
case AKEYCODE_F6:
|
|
if (engine.devMenu && videoSettings.screenCount > 1)
|
|
videoSettings.screenCount--;
|
|
return true;
|
|
|
|
case AKEYCODE_F7:
|
|
if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)
|
|
videoSettings.screenCount++;
|
|
return true;
|
|
|
|
case AKEYCODE_F9:
|
|
if (engine.devMenu)
|
|
showHitboxes ^= 1;
|
|
return true;
|
|
|
|
case AKEYCODE_F10:
|
|
if (engine.devMenu)
|
|
engine.showPaletteOverlay ^= 1;
|
|
return true;
|
|
#endif
|
|
case AKEYCODE_DEL:
|
|
if (engine.devMenu)
|
|
engine.gameSpeed = engine.fastForwardSpeed;
|
|
return true;
|
|
|
|
case AKEYCODE_F11:
|
|
case AKEYCODE_INSERT:
|
|
if (engine.devMenu)
|
|
engine.frameStep = true;
|
|
return true;
|
|
|
|
case AKEYCODE_F12:
|
|
case AKEYCODE_BREAK:
|
|
if (engine.devMenu) {
|
|
#if RETRO_REV0U
|
|
switch (engine.version) {
|
|
default: break;
|
|
case 5:
|
|
if (sceneInfo.state != ENGINESTATE_NONE)
|
|
sceneInfo.state ^= ENGINESTATE_STEPOVER;
|
|
break;
|
|
case 4:
|
|
case 3:
|
|
if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)
|
|
RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;
|
|
break;
|
|
}
|
|
#else
|
|
if (sceneInfo.state != ENGINESTATE_NONE)
|
|
sceneInfo.state ^= ENGINESTATE_STEPOVER;
|
|
#endif
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AndroidKeyUpCallback(GameActivity *activity, const GameActivityKeyEvent *event)
|
|
{
|
|
if (Paddleboat_processGameActivityKeyInputEvent(event, sizeof(GameActivityKeyEvent)))
|
|
return true;
|
|
|
|
int32 keycode = event->keyCode;
|
|
#if !RETRO_REV02
|
|
--RSDK::SKU::buttonDownCount;
|
|
#endif
|
|
switch (keycode) {
|
|
default:
|
|
#if RETRO_INPUTDEVICE_KEYBOARD
|
|
SKU::ClearKeyState(AndroidToWinAPIMappings(keycode));
|
|
#endif
|
|
return true;
|
|
|
|
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
|
|
case AKEYCODE_ESCAPE: RSDK::SKU::specialKeyStates[0] = false; return true;
|
|
case AKEYCODE_ENTER: RSDK::SKU::specialKeyStates[1] = false; return true;
|
|
#endif
|
|
case AKEYCODE_DEL: engine.gameSpeed = 1; return true;
|
|
}
|
|
return false;
|
|
} |