299 lines
13 KiB
C
299 lines
13 KiB
C
// android.system.Os has no public chdir() (confirmed against the actual
|
|
// API 34 stub jar - Java has no way to change a process's working
|
|
// directory at all). This is the one bit of native code QuestShockActivity
|
|
// needs, compiled into the same "main" library as engine/ (see
|
|
// android/engine-patches/01-android-shared-lib.patch's ANDROID_EXTRA_SOURCES)
|
|
// - engine/ itself is never modified.
|
|
#include <ctype.h>
|
|
#include <jni.h>
|
|
#include <unistd.h>
|
|
|
|
#include <SDL.h>
|
|
|
|
#include "qs_config.h"
|
|
#include "qs_splash.h"
|
|
#include "xr_input.h"
|
|
#include "xr_overlay.h"
|
|
#include "xr_session.h"
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_QuestShockActivity_nativeChdir(JNIEnv *env, jclass clazz, jstring path) {
|
|
const char *cpath = (*env)->GetStringUTFChars(env, path, NULL);
|
|
chdir(cpath);
|
|
(*env)->ReleaseStringUTFChars(env, path, cpath);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_de_ladkau_questshock_QuestShockActivity_nativeSetSplashImage(
|
|
JNIEnv *env, jclass clazz, jintArray pixels, jint width, jint height) {
|
|
jint *data = (*env)->GetIntArrayElements(env, pixels, NULL);
|
|
if (data == NULL)
|
|
return;
|
|
qs_splash_set_image((const uint32_t *)data, width, height);
|
|
(*env)->ReleaseIntArrayElements(env, pixels, data, JNI_ABORT);
|
|
}
|
|
|
|
// KeyboardOverlay's hand-built on-screen keyboard (see
|
|
// KeyboardOverlay.handleCharKeyDown()/handleCharKeyUp()) has no real
|
|
// Android IME session behind it, so printable characters can't reach the
|
|
// game via Android's usual IME path - instead this builds and pushes an
|
|
// SDL_TEXTINPUT event directly, the same event type/shape SDL's own
|
|
// Android backend pushes for typed text, using only the public
|
|
// SDL_Event/SDL_PushEvent API. The engine's pump_events() (sdl_events.c)
|
|
// only picks up printable characters from this event, not from
|
|
// SDL_KEYDOWN.
|
|
//
|
|
// pump_events()'s SDL_TEXTINPUT handling sets sshockKeyStates[code] for
|
|
// this character and only ever clears it again on a matching SDL_KEYUP.
|
|
// Any character bound to a continuously-polled motion key (space -> jump,
|
|
// w -> forward, etc., see MacSrc/Prefs.c's default keybinds.txt) is
|
|
// polled every physics tick for as long as that state stays set, exactly
|
|
// like a real held key - so nativeSendPrintableCharDown()/Up() are called
|
|
// from the key button's own ACTION_DOWN/ACTION_UP (see
|
|
// KeyboardOverlay.charKeyTouchListener()), not both at once: pushing the
|
|
// release in the same call as the press would set and clear
|
|
// sshockKeyStates[code] within a single pump_events() call, before the
|
|
// game loop's poll (which runs once per frame, before pump_events - see
|
|
// GameSrc/mainloop.c) ever has a chance to observe the press.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_KeyboardOverlay_nativeSendPrintableCharDown(JNIEnv *env, jclass clazz,
|
|
jchar c) {
|
|
SDL_Event event;
|
|
SDL_zero(event);
|
|
event.type = SDL_TEXTINPUT;
|
|
event.text.timestamp = SDL_GetTicks();
|
|
event.text.windowID = 0;
|
|
event.text.text[0] = (char)c;
|
|
event.text.text[1] = '\0';
|
|
SDL_PushEvent(&event);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_KeyboardOverlay_nativeSendPrintableCharUp(JNIEnv *env, jclass clazz,
|
|
jchar c) {
|
|
SDL_Event releaseEvent;
|
|
SDL_zero(releaseEvent);
|
|
releaseEvent.type = SDL_KEYUP;
|
|
releaseEvent.key.timestamp = SDL_GetTicks();
|
|
releaseEvent.key.windowID = 0;
|
|
releaseEvent.key.state = SDL_RELEASED;
|
|
releaseEvent.key.repeat = 0;
|
|
// SDL keycodes for printable characters are the character's own
|
|
// (lowercased) byte value - see sdl_events.c's own comment on this.
|
|
releaseEvent.key.keysym.sym = (SDL_Keycode)tolower((unsigned char)c);
|
|
releaseEvent.key.keysym.mod = KMOD_NONE;
|
|
SDL_PushEvent(&releaseEvent);
|
|
}
|
|
|
|
// KeyboardOverlay's title-bar Close button - the keyboard is a fully
|
|
// independent overlay quad from the menu launcher (see xr_overlay.h), so
|
|
// this is the only way to hide it once it's open; the controller's menu
|
|
// button only ever affects the menu launcher.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_KeyboardOverlay_nativeRequestClose(JNIEnv *env, jclass clazz) {
|
|
xr_overlay_set_visible(xr_session_get_keyboard_overlay(), false);
|
|
}
|
|
|
|
// MenuOverlay's "Keyboard" button - only opens the keyboard overlay, never
|
|
// touches the menu launcher's own visibility, so both can be shown
|
|
// together.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeShowKeyboard(JNIEnv *env, jclass clazz) {
|
|
xr_overlay_set_visible(xr_session_get_keyboard_overlay(), true);
|
|
}
|
|
|
|
// MenuOverlay's "Save Configuration"/"Load Configuration" buttons - see
|
|
// qs_config.h for why these only enqueue an event rather than doing the
|
|
// actual file/engine-state work here directly (this runs on Android's UI
|
|
// thread, not the engine's own).
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSaveConfig(JNIEnv *env, jclass clazz) {
|
|
qs_config_request_save();
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestLoadConfig(JNIEnv *env, jclass clazz) {
|
|
qs_config_request_load();
|
|
}
|
|
|
|
// MenuOverlay's Video Options tab - live-appliable controls, see
|
|
// qs_config.h. Same enqueue-only reasoning as the Save/Load buttons above.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetRenderer(JNIEnv *env, jclass clazz,
|
|
jboolean opengl) {
|
|
qs_config_request_set_renderer(opengl);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetResolution(JNIEnv *env, jclass clazz,
|
|
jint resolutionIndex) {
|
|
qs_config_request_set_resolution(resolutionIndex);
|
|
}
|
|
|
|
// MenuOverlay's Main Menu tab's Language row - same enqueue-only reasoning as above.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetLanguage(JNIEnv *env, jclass clazz,
|
|
jint languageIndex) {
|
|
qs_config_request_set_language(languageIndex);
|
|
}
|
|
|
|
// MenuOverlay's Main Menu tab's "Reset Position" button - same enqueue-only
|
|
// reasoning as above.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestResetPosition(JNIEnv *env, jclass clazz) {
|
|
qs_config_request_reset_position();
|
|
}
|
|
|
|
// MenuOverlay's Video Options tab - "Initial Screen"/"Game Screen" width/
|
|
// distance preset rows, same enqueue-only reasoning as above.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetInitialScreenWidth(JNIEnv *env, jclass clazz,
|
|
jint presetIndex) {
|
|
qs_config_request_set_initial_screen_width(presetIndex);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetGameScreenWidth(JNIEnv *env, jclass clazz,
|
|
jint presetIndex) {
|
|
qs_config_request_set_game_screen_width(presetIndex);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetInitialScreenDistance(JNIEnv *env,
|
|
jclass clazz,
|
|
jint presetIndex) {
|
|
qs_config_request_set_initial_screen_distance(presetIndex);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestSetGameScreenDistance(JNIEnv *env, jclass clazz,
|
|
jint presetIndex) {
|
|
qs_config_request_set_game_screen_distance(presetIndex);
|
|
}
|
|
|
|
// Read-only queries - safe to call directly (no enqueue needed, see
|
|
// qs_config.h's own comment on each of these).
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetRendererIsOpenGl(JNIEnv *env, jclass clazz) {
|
|
return qs_config_current_renderer_is_opengl();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetResolutionIndex(JNIEnv *env, jclass clazz) {
|
|
return qs_config_current_resolution_index();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetInitialScreenWidthIndex(JNIEnv *env, jclass clazz) {
|
|
return qs_config_current_initial_screen_width_index();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetGameScreenWidthIndex(JNIEnv *env, jclass clazz) {
|
|
return qs_config_current_game_screen_width_index();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetInitialScreenDistanceIndex(JNIEnv *env,
|
|
jclass clazz) {
|
|
return qs_config_current_initial_screen_distance_index();
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetGameScreenDistanceIndex(JNIEnv *env, jclass clazz) {
|
|
return qs_config_current_game_screen_distance_index();
|
|
}
|
|
|
|
// Preset button *labels* (not the current value) - shared by both
|
|
// "Initial Screen" and "Game Screen" columns, since their offset/step is
|
|
// config-file-only, not per-profile (see qs_config.h's own comment).
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetScreenWidthPresetValue(JNIEnv *env, jclass clazz,
|
|
jint index) {
|
|
return qs_config_screen_width_preset_value(index);
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetScreenDistancePresetValue(JNIEnv *env, jclass clazz,
|
|
jint index) {
|
|
return qs_config_screen_distance_preset_value(index);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetLanguage(JNIEnv *env, jclass clazz) {
|
|
return qs_config_current_language();
|
|
}
|
|
|
|
// MenuOverlay's header - polled on a periodic timer (see its own comment),
|
|
// not event-driven, so these are plain synchronous reads too.
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetFps(JNIEnv *env, jclass clazz) {
|
|
return xr_session_get_fps();
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetFrameTimeMs(JNIEnv *env, jclass clazz) {
|
|
return xr_session_get_frame_ms();
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetCpuUtilization(JNIEnv *env, jclass clazz) {
|
|
return xr_session_get_cpu_utilization();
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetGpuUtilization(JNIEnv *env, jclass clazz) {
|
|
return xr_session_get_gpu_utilization();
|
|
}
|
|
|
|
// Controller Options tab: actionIndex follows xr_input.c's action order
|
|
// (MenuOverlay.java and Strings.java hold the matching labels).
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestBeginControlCapture(JNIEnv *env, jclass clazz,
|
|
jint actionIndex) {
|
|
qs_config_request_begin_control_capture(actionIndex);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestCancelControlCapture(JNIEnv *env, jclass clazz) {
|
|
qs_config_request_cancel_control_capture();
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestResetPlayerControls(JNIEnv *env, jclass clazz) {
|
|
qs_config_request_reset_player_controls();
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetControlBindingKey(JNIEnv *env, jclass clazz,
|
|
jint actionIndex) {
|
|
return (*env)->NewStringUTF(env, xr_input_get_action_binding_name(actionIndex));
|
|
}
|
|
|
|
JNIEXPORT jstring JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetActiveInteractionProfilePath(JNIEnv *env,
|
|
jclass clazz) {
|
|
return (*env)->NewStringUTF(env, xr_input_get_active_interaction_profile_path());
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeSetControllerOptionsTabOpen(JNIEnv *env, jclass clazz,
|
|
jboolean open) {
|
|
xr_input_set_controller_options_tab_open(open == JNI_TRUE);
|
|
}
|
|
|
|
// Cheats tab: same enqueue-only pattern as the other requests.
|
|
JNIEXPORT void JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeRequestCheat(JNIEnv *env, jclass clazz, jint cheatId) {
|
|
qs_config_request_cheat(cheatId);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetCheatUnlimitedMask(JNIEnv *env, jclass clazz) {
|
|
return qs_config_cheat_unlimited_mask();
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_de_ladkau_questshock_MenuOverlay_nativeGetCheatPhysicsRunning(JNIEnv *env, jclass clazz) {
|
|
return qs_config_cheat_physics_running();
|
|
}
|