Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/dependencies/android/androidHelpers.cpp
774 views
1
#include <RSDK/Core/RetroEngine.hpp>
2
#include <main.hpp>
3
#include <pthread.h>
4
5
bool32 launched = false;
6
pthread_t mainthread;
7
8
using namespace RSDK;
9
10
static struct JNISetup _jni_setup = { 0 };
11
12
android_app *app = NULL;
13
14
jmethodID getFD = { 0 };
15
jmethodID writeLog = { 0 };
16
17
jmethodID showLoading = { 0 };
18
jmethodID hideLoading = { 0 };
19
jmethodID setLoading = { 0 };
20
jmethodID setPixSize = { 0 };
21
22
#if RETRO_USE_MOD_LOADER
23
jmethodID fsExists = { 0 };
24
jmethodID fsIsDir = { 0 };
25
jmethodID fsDirIter = { 0 };
26
jmethodID fsRecurseIter = { 0 };
27
#endif
28
29
#include <game-activity/GameActivity.cpp>
30
#include <game-text-input/gametextinput.cpp>
31
extern "C" {
32
#include <game-activity/native_app_glue/android_native_app_glue.c>
33
}
34
35
struct JNISetup *GetJNISetup()
36
{
37
app->activity->vm->AttachCurrentThread(&_jni_setup.env, NULL);
38
if (!_jni_setup.thiz) {
39
_jni_setup.thiz = app->activity->javaGameActivity;
40
_jni_setup.clazz = _jni_setup.env->GetObjectClass(_jni_setup.thiz);
41
}
42
return &_jni_setup;
43
}
44
45
FileIO *fOpen(const char *path, const char *mode)
46
{
47
app->activity->vm->AttachCurrentThread(&_jni_setup.env, NULL);
48
jbyteArray jpath = _jni_setup.env->NewByteArray(strlen(path));
49
_jni_setup.env->SetByteArrayRegion(jpath, 0, strlen(path), (jbyte*)path);
50
int fd = _jni_setup.env->CallIntMethod(_jni_setup.thiz, getFD, jpath, mode[0]);
51
if (!fd)
52
return NULL;
53
return fdopen(fd, mode);
54
}
55
56
/*
57
int fSeek(FileIO* file, long offset, int whence) {
58
return fseek(file, offset, whence);
59
}
60
61
int fTell(FileIO* file) {
62
return ftell(file);
63
}//*/
64
65
int32 AndroidToWinAPIMappings(int32 mapping)
66
{
67
switch (mapping) {
68
default: return KEYMAP_NO_MAPPING;
69
// case AKEYCODE_HOME: return VK_HOME;
70
case AKEYCODE_0: return VK_0;
71
case AKEYCODE_1: return VK_1;
72
case AKEYCODE_2: return VK_2;
73
case AKEYCODE_3: return VK_3;
74
case AKEYCODE_4: return VK_4;
75
case AKEYCODE_5: return VK_5;
76
case AKEYCODE_6: return VK_6;
77
case AKEYCODE_7: return VK_7;
78
case AKEYCODE_8: return VK_8;
79
case AKEYCODE_9: return VK_9;
80
case AKEYCODE_DPAD_UP: return VK_UP;
81
case AKEYCODE_DPAD_DOWN: return VK_DOWN;
82
case AKEYCODE_DPAD_LEFT: return VK_LEFT;
83
case AKEYCODE_DPAD_RIGHT: return VK_RIGHT;
84
case AKEYCODE_DPAD_CENTER: return VK_SELECT;
85
// case AKEYCODE_VOLUME_UP: return VK_VOLUME_UP;
86
// case AKEYCODE_VOLUME_DOWN: return VK_VOLUME_DOWN;
87
case AKEYCODE_CLEAR: return VK_CLEAR;
88
case AKEYCODE_A: return VK_A;
89
case AKEYCODE_B: return VK_B;
90
case AKEYCODE_C: return VK_C;
91
case AKEYCODE_D: return VK_D;
92
case AKEYCODE_E: return VK_E;
93
case AKEYCODE_F: return VK_F;
94
case AKEYCODE_G: return VK_G;
95
case AKEYCODE_H: return VK_H;
96
case AKEYCODE_I: return VK_I;
97
case AKEYCODE_J: return VK_J;
98
case AKEYCODE_K: return VK_K;
99
case AKEYCODE_L: return VK_L;
100
case AKEYCODE_M: return VK_M;
101
case AKEYCODE_N: return VK_N;
102
case AKEYCODE_O: return VK_O;
103
case AKEYCODE_P: return VK_P;
104
case AKEYCODE_Q: return VK_Q;
105
case AKEYCODE_R: return VK_R;
106
case AKEYCODE_S: return VK_S;
107
case AKEYCODE_T: return VK_T;
108
case AKEYCODE_U: return VK_U;
109
case AKEYCODE_V: return VK_V;
110
case AKEYCODE_W: return VK_W;
111
case AKEYCODE_X: return VK_X;
112
case AKEYCODE_Y: return VK_Y;
113
case AKEYCODE_Z: return VK_Z;
114
case AKEYCODE_COMMA: return VK_OEM_COMMA;
115
case AKEYCODE_PERIOD: return VK_OEM_PERIOD;
116
case AKEYCODE_ALT_LEFT: return VK_LMENU;
117
case AKEYCODE_ALT_RIGHT: return VK_RMENU;
118
case AKEYCODE_SHIFT_LEFT: return VK_LSHIFT;
119
case AKEYCODE_SHIFT_RIGHT: return VK_RSHIFT;
120
case AKEYCODE_TAB: return VK_TAB;
121
case AKEYCODE_SPACE: return VK_SPACE;
122
case AKEYCODE_ENVELOPE: return VK_LAUNCH_MAIL;
123
case AKEYCODE_ENTER: return VK_RETURN;
124
case AKEYCODE_MINUS: return VK_OEM_MINUS;
125
case AKEYCODE_MENU: return VK_MENU;
126
case AKEYCODE_MEDIA_PLAY_PAUSE: return VK_MEDIA_PLAY_PAUSE;
127
case AKEYCODE_MEDIA_STOP: return VK_MEDIA_STOP;
128
case AKEYCODE_MEDIA_NEXT: return VK_MEDIA_NEXT_TRACK;
129
case AKEYCODE_MEDIA_PREVIOUS: return VK_MEDIA_PREV_TRACK;
130
case AKEYCODE_MUTE: return VK_VOLUME_MUTE;
131
case AKEYCODE_PAGE_UP: return VK_PRIOR;
132
case AKEYCODE_PAGE_DOWN: return VK_NEXT;
133
case AKEYCODE_ESCAPE: return VK_ESCAPE;
134
case AKEYCODE_DEL: return VK_BACK; // ???????????? i hate android
135
case AKEYCODE_FORWARD_DEL: return VK_DELETE;
136
case AKEYCODE_CTRL_LEFT: return VK_LCONTROL;
137
case AKEYCODE_CTRL_RIGHT: return VK_RCONTROL;
138
case AKEYCODE_CAPS_LOCK: return VK_CAPITAL;
139
case AKEYCODE_SCROLL_LOCK: return VK_SCROLL;
140
case AKEYCODE_SYSRQ: return VK_SNAPSHOT;
141
case AKEYCODE_BREAK: return VK_PAUSE;
142
case AKEYCODE_MOVE_HOME: return VK_HOME;
143
case AKEYCODE_MOVE_END: return VK_END;
144
case AKEYCODE_INSERT: return VK_INSERT;
145
case AKEYCODE_F1: return VK_F1;
146
case AKEYCODE_F2: return VK_F2;
147
case AKEYCODE_F3: return VK_F3;
148
case AKEYCODE_F4: return VK_F4;
149
case AKEYCODE_F5: return VK_F5;
150
case AKEYCODE_F6: return VK_F6;
151
case AKEYCODE_F7: return VK_F7;
152
case AKEYCODE_F8: return VK_F8;
153
case AKEYCODE_F9: return VK_F9;
154
case AKEYCODE_F10: return VK_F10;
155
case AKEYCODE_F11: return VK_F11;
156
case AKEYCODE_F12: return VK_F12;
157
case AKEYCODE_NUM_LOCK: return VK_NUMLOCK;
158
case AKEYCODE_NUMPAD_0: return VK_NUMPAD0;
159
case AKEYCODE_NUMPAD_1: return VK_NUMPAD1;
160
case AKEYCODE_NUMPAD_2: return VK_NUMPAD2;
161
case AKEYCODE_NUMPAD_3: return VK_NUMPAD3;
162
case AKEYCODE_NUMPAD_4: return VK_NUMPAD4;
163
case AKEYCODE_NUMPAD_5: return VK_NUMPAD5;
164
case AKEYCODE_NUMPAD_6: return VK_NUMPAD6;
165
case AKEYCODE_NUMPAD_7: return VK_NUMPAD7;
166
case AKEYCODE_NUMPAD_8: return VK_NUMPAD8;
167
case AKEYCODE_NUMPAD_9: return VK_NUMPAD9;
168
case AKEYCODE_NUMPAD_DIVIDE: return VK_DIVIDE;
169
case AKEYCODE_NUMPAD_MULTIPLY: return VK_MULTIPLY;
170
case AKEYCODE_NUMPAD_SUBTRACT: return VK_SUBTRACT;
171
case AKEYCODE_NUMPAD_ADD: return VK_ADD;
172
case AKEYCODE_NUMPAD_DOT: return VK_DECIMAL;
173
case AKEYCODE_NUMPAD_COMMA: return VK_OEM_COMMA;
174
case AKEYCODE_NUMPAD_ENTER: return VK_RETURN;
175
// case AKEYCODE_VOLUME_MUTE: return VK_VOLUME_MUTE;
176
case AKEYCODE_ZOOM_IN: return VK_ZOOM;
177
case AKEYCODE_ZOOM_OUT: return VK_ZOOM;
178
case AKEYCODE_SLEEP: return VK_SLEEP;
179
case AKEYCODE_HELP: return VK_HELP;
180
}
181
}
182
183
JNIEXPORT void JNICALL jnifunc(nativeOnTouch, RSDK, jint finger, jint action, jfloat x, jfloat y)
184
{
185
if (finger > 0x10)
186
return; // nah cause how tf
187
188
bool32 down = (action == AMOTION_EVENT_ACTION_DOWN) || (action == AMOTION_EVENT_ACTION_MOVE) || (action == AMOTION_EVENT_ACTION_POINTER_DOWN);
189
190
if (down) {
191
touchInfo.x[finger] = x;
192
touchInfo.y[finger] = y;
193
touchInfo.down[finger] = true;
194
if (touchInfo.count < finger + 1)
195
touchInfo.count = finger + 1;
196
}
197
else {
198
touchInfo.down[finger] = false;
199
if (touchInfo.count >= finger + 1) {
200
for (; touchInfo.count > 0; touchInfo.count--) {
201
if (touchInfo.down[touchInfo.count - 1])
202
break;
203
}
204
}
205
}
206
}
207
208
JNIEXPORT jbyteArray JNICALL jnifunc(nativeLoadFile, RSDK, jstring file) {
209
const char* path = env->GetStringUTFChars(file, NULL);
210
FileInfo info;
211
InitFileInfo(&info);
212
if (LoadFile(&info, path, FMODE_RB)) {
213
jbyteArray ret = env->NewByteArray(info.fileSize);
214
jbyte* array = env->GetByteArrayElements(ret, NULL);
215
ReadBytes(&info, array, info.fileSize);
216
CloseFile(&info);
217
env->ReleaseByteArrayElements(ret, array, 0);
218
env->ReleaseStringUTFChars(file, path);
219
return ret;
220
}
221
env->ReleaseStringUTFChars(file, path);
222
return NULL;
223
}
224
225
void ShowLoadingIcon() {
226
auto* jni = GetJNISetup();
227
jni->env->CallVoidMethod(jni->thiz, showLoading);
228
}
229
230
void HideLoadingIcon() {
231
auto* jni = GetJNISetup();
232
jni->env->CallVoidMethod(jni->thiz, hideLoading);
233
}
234
235
void SetLoadingIcon() {
236
auto* jni = GetJNISetup();
237
// cheating time
238
jstring name = jni->env->NewStringUTF("Data/Sprites/Android/Loading.bin");
239
jbyteArray waitSpinner = jniname(nativeLoadFile, RSDK)(jni->env, jni->clazz, name);
240
if (!waitSpinner) {
241
name = jni->env->NewStringUTF("Data/Sprites/UI/WaitSpinner.bin");
242
waitSpinner = jniname(nativeLoadFile, RSDK)(jni->env, jni->clazz, name);
243
}
244
jni->env->CallVoidMethod(jni->thiz, setLoading, waitSpinner);
245
}
246
247
248
void AndroidCommandCallback(android_app *app, int32 cmd)
249
{
250
PrintLog(PRINT_NORMAL, "COMMAND %d %d", cmd, app->window ? 1 : 0);
251
switch (cmd) {
252
case APP_CMD_INIT_WINDOW:
253
case APP_CMD_WINDOW_RESIZED:
254
case APP_CMD_CONFIG_CHANGED:
255
case APP_CMD_TERM_WINDOW:
256
videoSettings.windowState = WINDOWSTATE_INACTIVE;
257
RenderDevice::isInitialized = false;
258
RenderDevice::window = app->window;
259
#if RETRO_REV02
260
if (SKU::userCore)
261
SKU::userCore->focusState = 1;
262
#else
263
engine.focusState &= (~1);
264
#endif
265
if (app->window != NULL && cmd != APP_CMD_TERM_WINDOW) {
266
#if RETRO_REV02
267
if (SKU::userCore)
268
SKU::userCore->focusState = 0;
269
#else
270
engine.focusState |= 1;
271
#endif
272
videoSettings.windowState = WINDOWSTATE_ACTIVE;
273
SwappyGL_setWindow(app->window);
274
}
275
break;
276
case APP_CMD_STOP: Paddleboat_onStop(GetJNISetup()->env); break;
277
case APP_CMD_START: Paddleboat_onStart(GetJNISetup()->env); break;
278
case APP_CMD_GAINED_FOCUS: /*
279
#if RETRO_REV02
280
if (SKU::userCore)
281
SKU::userCore->focusState = 0;
282
#else
283
engine.focusState |= 1;
284
#endif
285
videoSettings.windowState = WINDOWSTATE_ACTIVE;//*/
286
break;
287
case APP_CMD_LOST_FOCUS: /*
288
#if RETRO_REV02
289
if (SKU::userCore)
290
SKU::userCore->focusState = 1;
291
#else
292
engine.focusState &= (~1);
293
#endif
294
videoSettings.windowState = WINDOWSTATE_INACTIVE; //*/
295
break;
296
default: break;
297
}
298
}
299
300
bool AndroidKeyDownCallback(GameActivity *activity, const GameActivityKeyEvent *event)
301
{
302
if (Paddleboat_processGameActivityKeyInputEvent(event, sizeof(GameActivityKeyEvent)))
303
return true;
304
int32 keycode = event->keyCode;
305
306
#if !RETRO_REV02
307
++RSDK::SKU::buttonDownCount;
308
#endif
309
switch (keycode) {
310
case AKEYCODE_ENTER:
311
312
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
313
RSDK::SKU::specialKeyStates[1] = true;
314
#endif
315
// [fallthrough]
316
317
default:
318
if (AndroidToWinAPIMappings(keycode)) {
319
320
#if RETRO_INPUTDEVICE_KEYBOARD
321
SKU::UpdateKeyState(AndroidToWinAPIMappings(keycode));
322
#endif
323
return true;
324
}
325
return false;
326
327
case AKEYCODE_ESCAPE:
328
if (engine.devMenu) {
329
#if RETRO_REV0U
330
if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)
331
#else
332
if (sceneInfo.state == ENGINESTATE_DEVMENU)
333
#endif
334
CloseDevMenu();
335
else
336
OpenDevMenu();
337
}
338
else {
339
#if RETRO_INPUTDEVICE_KEYBOARD
340
SKU::UpdateKeyState(AndroidToWinAPIMappings(keycode));
341
#endif
342
}
343
344
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
345
RSDK::SKU::specialKeyStates[0] = true;
346
#endif
347
return true;
348
349
#if !RETRO_USE_ORIGINAL_CODE
350
case AKEYCODE_F1:
351
sceneInfo.listPos--;
352
if (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart) {
353
sceneInfo.activeCategory--;
354
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
355
sceneInfo.activeCategory = sceneInfo.categoryCount - 1;
356
}
357
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;
358
}
359
360
LoadScene();
361
return true;
362
363
case AKEYCODE_F2:
364
sceneInfo.listPos++;
365
if (sceneInfo.listPos >= sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd) {
366
sceneInfo.activeCategory++;
367
if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {
368
sceneInfo.activeCategory = 0;
369
}
370
sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;
371
}
372
373
LoadScene();
374
return true;
375
#endif
376
377
case AKEYCODE_F3:
378
if (userShaderCount)
379
videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;
380
return true;
381
382
#if !RETRO_USE_ORIGINAL_CODE
383
case AKEYCODE_F5:
384
// Quick-Reload
385
LoadScene();
386
return true;
387
388
case AKEYCODE_F6:
389
if (engine.devMenu && videoSettings.screenCount > 1)
390
videoSettings.screenCount--;
391
return true;
392
393
case AKEYCODE_F7:
394
if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)
395
videoSettings.screenCount++;
396
return true;
397
398
case AKEYCODE_F9:
399
if (engine.devMenu)
400
showHitboxes ^= 1;
401
return true;
402
403
case AKEYCODE_F10:
404
if (engine.devMenu)
405
engine.showPaletteOverlay ^= 1;
406
return true;
407
#endif
408
case AKEYCODE_DEL:
409
if (engine.devMenu)
410
engine.gameSpeed = engine.fastForwardSpeed;
411
return true;
412
413
case AKEYCODE_F11:
414
case AKEYCODE_INSERT:
415
if (engine.devMenu)
416
engine.frameStep = true;
417
return true;
418
419
case AKEYCODE_F12:
420
case AKEYCODE_BREAK:
421
if (engine.devMenu) {
422
#if RETRO_REV0U
423
switch (engine.version) {
424
default: break;
425
case 5:
426
if (sceneInfo.state != ENGINESTATE_NONE)
427
sceneInfo.state ^= ENGINESTATE_STEPOVER;
428
break;
429
case 4:
430
case 3:
431
if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)
432
RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;
433
break;
434
}
435
#else
436
if (sceneInfo.state != ENGINESTATE_NONE)
437
sceneInfo.state ^= ENGINESTATE_STEPOVER;
438
#endif
439
}
440
return true;
441
}
442
return false;
443
}
444
445
bool AndroidKeyUpCallback(GameActivity *activity, const GameActivityKeyEvent *event)
446
{
447
if (Paddleboat_processGameActivityKeyInputEvent(event, sizeof(GameActivityKeyEvent)))
448
return true;
449
450
int32 keycode = event->keyCode;
451
#if !RETRO_REV02
452
--RSDK::SKU::buttonDownCount;
453
#endif
454
switch (keycode) {
455
default:
456
#if RETRO_INPUTDEVICE_KEYBOARD
457
SKU::ClearKeyState(AndroidToWinAPIMappings(keycode));
458
#endif
459
return true;
460
461
#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD
462
case AKEYCODE_ESCAPE: RSDK::SKU::specialKeyStates[0] = false; return true;
463
case AKEYCODE_ENTER: RSDK::SKU::specialKeyStates[1] = false; return true;
464
#endif
465
case AKEYCODE_DEL: engine.gameSpeed = 1; return true;
466
}
467
return false;
468
}
469