mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Move the C++ part of the android wrapping here.
This commit is contained in:
parent
0983adb052
commit
1e398d4269
46
android/NativeApp.h
Normal file
46
android/NativeApp.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
// The Native App API.
|
||||
//
|
||||
// Implement these functions and you've got a native app. These are called
|
||||
// from app-android, which exposes the native JNI api which is a bit
|
||||
// more complicated.
|
||||
|
||||
// This is defined in input/input_state.h.
|
||||
struct InputState;
|
||||
|
||||
// The very first function to be called. Even NativeMix is not called
|
||||
// before this, although it may be called at any point in time afterwards.
|
||||
// Must not call OpenGL. Main thread.
|
||||
void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *installID);
|
||||
|
||||
// Runs after NativeInit() at some point. Can call OpenGL.
|
||||
void NativeInitGraphics();
|
||||
|
||||
// Signals that you need to recreate all buffered OpenGL resources,
|
||||
// like textures, vbo etc. Main thread.
|
||||
void NativeDeviceLost();
|
||||
|
||||
// Called ~sixty times a second, delivers the current input state.
|
||||
// Main thread.
|
||||
void NativeUpdate(const InputState &input);
|
||||
|
||||
// Called when it's time to render. If the device can keep up, this
|
||||
// will also be called sixty times per second. Main thread.
|
||||
void NativeRender();
|
||||
|
||||
// This should render num_samples 44khz stereo samples.
|
||||
// Try not to make too many assumptions on the granularity
|
||||
// of num_samples.
|
||||
// This function may be called from a totally separate thread from
|
||||
// the rest of the game.
|
||||
void NativeMix(short *audio, int num_samples);
|
||||
|
||||
// Called when it's time to shutdown. After this has been called,
|
||||
// no more calls to any other function will be made from the framework
|
||||
// before process exit.
|
||||
// The graphics context should still be active when calling this, as freeing
|
||||
// of graphics resources happens here.
|
||||
// Main thread.
|
||||
void NativeShutdownGraphics();
|
||||
void NativeShutdown();
|
244
android/app-android.cpp
Normal file
244
android/app-android.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
// This is generic code that is included in all Android apps that use the
|
||||
// Native framework by Henrik Rydgård (https://github.com/hrydgard/native).
|
||||
|
||||
// It calls a set of methods defined in NativeApp.h. These should be implemented
|
||||
// by your game or app.
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "file/zip_read.h"
|
||||
#include "input/input_state.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "android/NativeApp.h"
|
||||
#include "Globals.h"
|
||||
|
||||
#define coord_xres 800
|
||||
#define coord_yres 480
|
||||
|
||||
static JNIEnv *jniEnvUI;
|
||||
|
||||
std::string frameCommand;
|
||||
std::string frameCommandParam;
|
||||
|
||||
// Android implementation of callbacks to the Java part of the app
|
||||
void SystemToast(const char *text) {
|
||||
frameCommand = "toast";
|
||||
frameCommandParam = text;
|
||||
}
|
||||
|
||||
// TODO: need a Hide or bool show;
|
||||
void ShowAd(int x, int y, bool center_x) {
|
||||
ELOG("TODO! ShowAd!");
|
||||
}
|
||||
|
||||
void Vibrate(int length_ms) {
|
||||
frameCommand = "vibrate";
|
||||
frameCommandParam = "100";
|
||||
}
|
||||
|
||||
void LaunchBrowser(const char *url)
|
||||
{
|
||||
frameCommand = "launchBrowser";
|
||||
frameCommandParam = url;
|
||||
}
|
||||
|
||||
void LaunchMarket(const char *url)
|
||||
{
|
||||
frameCommand = "launchMarket";
|
||||
frameCommandParam = url;
|
||||
}
|
||||
|
||||
void LaunchEmail(const char *email_address)
|
||||
{
|
||||
frameCommand = "launchEmail";
|
||||
frameCommandParam = email_address;
|
||||
}
|
||||
|
||||
|
||||
// Remember that all of these need initialization on init! The process
|
||||
// may be reused when restarting the game. Globals are DANGEROUS.
|
||||
int xres, yres;
|
||||
|
||||
// Used for touch. (TODO)
|
||||
float xscale = 1;
|
||||
float yscale = 1;
|
||||
|
||||
InputState input_state;
|
||||
|
||||
static bool renderer_inited = false;
|
||||
static bool first_lost = true;
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_init
|
||||
(JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath,
|
||||
jstring dataDir, jstring externalDir, jstring jinstallID) {
|
||||
jniEnvUI = env;
|
||||
xres = xxres;
|
||||
yres = yyres;
|
||||
g_xres = xres;
|
||||
g_yres = yres;
|
||||
xscale = (float)coord_xres / xres;
|
||||
yscale = (float)coord_yres / yres;
|
||||
memset(&input_state, 0, sizeof(input_state));
|
||||
renderer_inited = false;
|
||||
first_lost = true;
|
||||
|
||||
jboolean isCopy;
|
||||
const char *str = env->GetStringUTFChars(apkpath, &isCopy);
|
||||
ILOG("APK path: %s", str);
|
||||
VFSRegister("", new ZipAssetReader(str, "assets/"));
|
||||
|
||||
str = env->GetStringUTFChars(externalDir, &isCopy);
|
||||
ILOG("External storage path: %s", str);
|
||||
|
||||
str = env->GetStringUTFChars(dataDir, &isCopy);
|
||||
user_data_path = std::string(str) + "/";
|
||||
settings_file = user_data_path + "settings.json";
|
||||
ILOG("Settings file: %s", settings_file.c_str());
|
||||
|
||||
str = env->GetStringUTFChars(jinstallID, &isCopy);
|
||||
std::string installID = std::string(str);
|
||||
|
||||
const char *app_name = "rollerball";
|
||||
NativeInit(1, &app_name, user_data_path.c_str(), installID.c_str());
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown
|
||||
(JNIEnv *, jclass) {
|
||||
ILOG("RollerBallMainShutdown - calling NativeShutdown.");
|
||||
if (renderer_inited) {
|
||||
NativeShutdownGraphics();
|
||||
}
|
||||
NativeShutdown();
|
||||
ILOG("RollerBallMainShutdown - calling VFSShutdown.");
|
||||
VFSShutdown();
|
||||
}
|
||||
|
||||
static jmethodID postCommand;
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
|
||||
if (!renderer_inited) {
|
||||
ILOG("Calling NativeInitGraphics();");
|
||||
NativeInitGraphics();
|
||||
} else {
|
||||
ILOG("Calling NativeDeviceLost();");
|
||||
}
|
||||
renderer_inited = true;
|
||||
jclass cls = env->GetObjectClass(obj);
|
||||
postCommand = env->GetMethodID(
|
||||
cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
ILOG("MethodID: %i", (int)postCommand);
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize
|
||||
(JNIEnv *, jobject clazz, jint w, jint h) {
|
||||
ILOG("nativeResize (%i, %i), device lost!", w, h);
|
||||
if (first_lost) {
|
||||
first_lost = false;
|
||||
} else {
|
||||
NativeDeviceLost();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender
|
||||
(JNIEnv *env, jobject obj) {
|
||||
if (renderer_inited) {
|
||||
UpdateInputState(&input_state);
|
||||
NativeUpdate(input_state);
|
||||
NativeRender();
|
||||
time_update();
|
||||
} else {
|
||||
ELOG("Ended up in nativeRender even though app has quit.%s", "");
|
||||
// Shouldn't really get here.
|
||||
glClearColor(1.0, 0.0, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if (!frameCommand.empty()) {
|
||||
ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str());
|
||||
jstring cmd = env->NewStringUTF(frameCommand.c_str());
|
||||
jstring param = env->NewStringUTF(frameCommandParam.c_str());
|
||||
|
||||
env->CallVoidMethod(obj, postCommand, cmd, param);
|
||||
|
||||
frameCommand = "";
|
||||
frameCommandParam = "";
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) {
|
||||
int buf_size = env->GetArrayLength(array);
|
||||
if (buf_size) {
|
||||
short *data = env->GetShortArrayElements(array, 0);
|
||||
int samples = buf_size / 2;
|
||||
NativeMix(data, samples);
|
||||
env->ReleaseShortArrayElements(array, data, 0);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch
|
||||
(JNIEnv *, jclass, int x, int y, int code) {
|
||||
// This really does require locking :/
|
||||
input_state.mouse_valid = false;
|
||||
input_state.mouse_x = x;
|
||||
input_state.mouse_y = y;
|
||||
if (code == 1) {
|
||||
input_state.mouse_buttons = 1;
|
||||
} else if (code == 2) {
|
||||
input_state.mouse_buttons = 0;
|
||||
}
|
||||
input_state.mouse_valid = true;
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown
|
||||
(JNIEnv *, jclass, jint key) {
|
||||
ILOG("Keydown %i", key);
|
||||
// Need a mechanism to release these.
|
||||
switch (key) {
|
||||
case 1: // Back
|
||||
input_state.pad_buttons |= PAD_BUTTON_BACK;
|
||||
break;
|
||||
case 2: // Menu
|
||||
input_state.pad_buttons |= PAD_BUTTON_START;
|
||||
break;
|
||||
case 3: // Search
|
||||
input_state.pad_buttons |= PAD_BUTTON_A;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp
|
||||
(JNIEnv *, jclass, jint key) {
|
||||
ILOG("Keyup %i", key);
|
||||
// Need a mechanism to release these.
|
||||
switch (key) {
|
||||
case 1: // Back
|
||||
input_state.pad_buttons &= ~PAD_BUTTON_BACK;
|
||||
break;
|
||||
case 2: // Menu
|
||||
input_state.pad_buttons &= ~PAD_BUTTON_START;
|
||||
break;
|
||||
case 3: // Search
|
||||
input_state.pad_buttons &= ~PAD_BUTTON_A;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer
|
||||
(JNIEnv *, jclass, float x, float y, float z) {
|
||||
// Theoretically this needs locking but I doubt it matters. Worst case, the X
|
||||
// from one "sensor frame" will be used together with Y from the next.
|
||||
// Should look into quantization though, for compressed movement storage.
|
||||
input_state.accelerometer_valid = true;
|
||||
input_state.acc.x = x;
|
||||
input_state.acc.y = y;
|
||||
input_state.acc.z = z;
|
||||
}
|
Loading…
Reference in New Issue
Block a user