diff --git a/Source/Android/Bridge/Bridge.vcxproj b/Source/Android/Bridge/Bridge.vcxproj
new file mode 100644
index 000000000..f6dff789f
--- /dev/null
+++ b/Source/Android/Bridge/Bridge.vcxproj
@@ -0,0 +1,48 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {593B00E6-1987-415D-A62C-26533FC3E95C}
+ Bridge
+ JniBridge
+
+
+ StaticLibrary
+
+
+
+
+
+
+
+
+
+ NotUsing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Android/Bridge/Bridge.vcxproj.filters b/Source/Android/Bridge/Bridge.vcxproj.filters
new file mode 100644
index 000000000..bd0537796
--- /dev/null
+++ b/Source/Android/Bridge/Bridge.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/Source/Android/Bridge/JavaBridge.cpp b/Source/Android/Bridge/JavaBridge.cpp
new file mode 100644
index 000000000..c2a54ac1d
--- /dev/null
+++ b/Source/Android/Bridge/JavaBridge.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+* *
+* Project 64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#include "JavaBridge.h"
+#include "jniBridge.h"
+
+#ifdef ANDROID
+JavaBridge::JavaBridge(JavaVM* vm) :
+ m_vm(vm)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ jclass GalleryActivityClass = env->FindClass("emu/project64/GalleryActivity");
+ if (GalleryActivityClass != NULL)
+ {
+ m_GalleryActivityClass = (jclass)env->NewGlobalRef(GalleryActivityClass);
+ }
+ jclass NotifierClass = env->FindClass("emu/project64/util/Notifier");
+ if (NotifierClass != NULL)
+ {
+ m_NotifierClass = (jclass)env->NewGlobalRef(NotifierClass);
+ }
+}
+
+void JavaBridge::GfxThreadInit()
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (g_GLThread != NULL && env != NULL)
+ {
+ jclass GLThreadClass = env->GetObjectClass(g_GLThread);
+ jmethodID midThreadStarting = env->GetMethodID(GLThreadClass, "ThreadStarting", "()V");
+ env->CallVoidMethod(g_GLThread, midThreadStarting);
+ env->DeleteLocalRef(GLThreadClass);
+ }
+}
+
+void JavaBridge::GfxThreadDone()
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (g_GLThread != NULL && env != NULL)
+ {
+ jclass GLThreadClass = env->GetObjectClass(g_GLThread);
+ jmethodID midThreadExiting = env->GetMethodID(GLThreadClass, "ThreadExiting", "()V");
+ env->CallVoidMethod(g_GLThread, midThreadExiting);
+ env->DeleteLocalRef(GLThreadClass);
+ }
+}
+
+void JavaBridge::SwapWindow()
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (g_GLThread != NULL && env != NULL)
+ {
+ jclass GLThreadClass = env->GetObjectClass(g_GLThread);
+ jmethodID midSwapBuffers = env->GetMethodID(GLThreadClass, "SwapBuffers", "()V");
+ env->CallVoidMethod(g_GLThread, midSwapBuffers);
+ env->DeleteLocalRef(GLThreadClass);
+ }
+}
+
+void JavaBridge::RomListReset(void)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (env)
+ {
+ jmethodID midRomListReset = env->GetStaticMethodID(m_GalleryActivityClass, "RomListReset", "()V");
+ env->CallStaticVoidMethod(m_GalleryActivityClass, midRomListReset);
+ }
+}
+
+void JavaBridge::RomListAddItem(const char * FullFileName, const char * FileName, const char * GoodName, uint32_t TextColor)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (env)
+ {
+ jmethodID midRomListAddItem = env->GetStaticMethodID(m_GalleryActivityClass, "RomListAddItem", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
+ if (midRomListAddItem != NULL)
+ {
+ jstring j_FullFileName = env->NewStringUTF(FullFileName);
+ jstring j_FileName = env->NewStringUTF(FileName);
+ jstring j_GoodName = env->NewStringUTF(GoodName);
+ env->CallStaticVoidMethod(m_GalleryActivityClass, midRomListAddItem, j_FullFileName, j_FileName, j_GoodName, TextColor);
+ env->DeleteLocalRef(j_FullFileName);
+ env->DeleteLocalRef(j_FileName);
+ env->DeleteLocalRef(j_GoodName);
+ }
+ }
+}
+
+void JavaBridge::RomListLoaded(void)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (env)
+ {
+ jmethodID midRomListLoadDone = env->GetStaticMethodID(m_GalleryActivityClass, "RomListLoadDone", "()V");
+ env->CallStaticVoidMethod(m_GalleryActivityClass, midRomListLoadDone);
+ }
+}
+
+void JavaBridge::DisplayMessage(const char * Message)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ if (env)
+ {
+ jstring j_Message = env->NewStringUTF(Message);
+ jmethodID midShowToast = env->GetStaticMethodID(m_NotifierClass, "showToast", "(Landroid/app/Activity;Ljava/lang/String;)V");
+ env->CallStaticVoidMethod(m_NotifierClass, midShowToast,g_Activity,j_Message);
+ env->DeleteLocalRef(j_Message);
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Source/Android/Bridge/JavaBridge.h b/Source/Android/Bridge/JavaBridge.h
new file mode 100644
index 000000000..7812cd482
--- /dev/null
+++ b/Source/Android/Bridge/JavaBridge.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#ifdef ANDROID
+
+#include
+#include
+
+class JavaBridge :
+ public RenderWindow
+{
+public:
+ JavaBridge (JavaVM* vm);
+
+ //Render window functions
+ void GfxThreadInit();
+ void GfxThreadDone();
+ void SwapWindow();
+
+ //Rom List
+ void RomListReset(void);
+ void RomListAddItem(const char * FullFileName, const char * FileName, const char * GoodName, uint32_t TextColor );
+ void RomListLoaded(void);
+
+ //Notification
+ void DisplayMessage(const char * Message);
+
+private:
+ JavaBridge(void); // Disable default constructor
+ JavaBridge(const JavaBridge&); // Disable copy constructor
+ JavaBridge& operator=(const JavaBridge&); // Disable assignment
+
+ JavaVM* m_vm;
+ jclass m_GalleryActivityClass;
+ jclass m_NotifierClass;
+};
+
+#endif
\ No newline at end of file
diff --git a/Source/Android/Bridge/JavaRomList.cpp b/Source/Android/Bridge/JavaRomList.cpp
new file mode 100644
index 000000000..4e0ad860f
--- /dev/null
+++ b/Source/Android/Bridge/JavaRomList.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+* *
+* Project 64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#include "JavaRomList.h"
+#include "JavaBridge.h"
+
+#ifdef ANDROID
+extern JavaBridge * g_JavaBridge;
+
+void CJavaRomList::RomListReset(void)
+{
+ if (g_JavaBridge)
+ {
+ g_JavaBridge->RomListReset();
+ }
+}
+
+void CJavaRomList::RomAddedToList(int32_t ListPos)
+{
+ if (g_JavaBridge)
+ {
+ ROM_INFO * pRomInfo = &m_RomInfo[ListPos];
+ g_JavaBridge->RomListAddItem(pRomInfo->szFullFileName, pRomInfo->FileName, pRomInfo->GoodName, pRomInfo->TextColor);
+ }
+}
+
+void CJavaRomList::RomListLoaded(void)
+{
+ if (g_JavaBridge)
+ {
+ g_JavaBridge->RomListLoaded();
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Source/Android/Bridge/JavaRomList.h b/Source/Android/Bridge/JavaRomList.h
new file mode 100644
index 000000000..b1fcb5950
--- /dev/null
+++ b/Source/Android/Bridge/JavaRomList.h
@@ -0,0 +1,11 @@
+#pragma once
+#include
+
+class CJavaRomList :
+ public CRomList
+{
+public:
+ void RomListReset(void);
+ void RomAddedToList(int32_t ListPos);
+ void RomListLoaded(void);
+};
\ No newline at end of file
diff --git a/Source/Android/Bridge/NotificationClass.cpp b/Source/Android/Bridge/NotificationClass.cpp
new file mode 100644
index 000000000..2f344fc83
--- /dev/null
+++ b/Source/Android/Bridge/NotificationClass.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+* *
+* Project64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#include
+#include
+#include
+#include
+#include "NotificationClass.h"
+#include "JavaBridge.h"
+#if defined(ANDROID)
+#include
+
+extern JavaBridge * g_JavaBridge;
+#endif
+
+CNotificationImp & Notify(void)
+{
+ static CNotificationImp g_Notify;
+ return g_Notify;
+}
+
+CNotificationImp::CNotificationImp() :
+ m_NextMsg(0)
+{
+}
+
+CNotificationImp::~CNotificationImp()
+{
+}
+
+void CNotificationImp::DisplayError(const char * /*Message*/) const
+{
+}
+
+void CNotificationImp::DisplayError(LanguageStringID /*StringID*/) const
+{
+}
+
+void CNotificationImp::FatalError(LanguageStringID /*StringID*/) const
+{
+}
+
+void CNotificationImp::DisplayMessage(int DisplayTime, LanguageStringID StringID) const
+{
+ DisplayMessage(DisplayTime, g_Lang->GetString(StringID).c_str());
+}
+
+void CNotificationImp::FatalError(const char * Message) const
+{
+ DisplayMessage(0,Message);
+}
+
+//User Feedback
+void CNotificationImp::DisplayMessage(int DisplayTime, const char * Message) const
+{
+#ifdef ANDROID
+ __android_log_print(ANDROID_LOG_VERBOSE, "PJ64-Bridge", "%s", Message);
+
+ if (g_JavaBridge == NULL) { return; }
+
+ /*if (m_NextMsg > 0 || DisplayTime > 0)
+ {
+ time_t Now = time(NULL);
+ if (DisplayTime == 0 && Now < m_NextMsg)
+ {
+ return;
+ }
+ if (DisplayTime > 0)
+ {
+ m_NextMsg = Now + DisplayTime;
+ }
+ if (m_NextMsg == 0)
+ {
+ m_NextMsg = 0;
+ }
+ }*/
+
+ g_JavaBridge->DisplayMessage(Message);
+#endif
+}
+
+void CNotificationImp::DisplayMessage2(const char * /*Message*/) const
+{
+}
+
+// Ask a Yes/No Question to the user, yes = true, no = false
+bool CNotificationImp::AskYesNoQuestion(const char * /*Question*/) const
+{
+ return false;
+}
+
+void CNotificationImp::BreakPoint(const char * FileName, int32_t LineNumber)
+{
+ if (g_Settings->LoadBool(Debugger_Enabled))
+ {
+ DisplayError(stdstr_f("Break point found at\n%s\n%d", FileName, LineNumber).c_str());
+#ifndef _WIN32
+ __builtin_trap();
+#endif
+#ifdef tofix
+ if (g_BaseSystem)
+ {
+ g_BaseSystem->CloseCpu();
+ }
+#endif
+ }
+ else
+ {
+ DisplayError("Fatal Error: Stopping emulation");
+#ifdef tofix
+ if (g_BaseSystem)
+ {
+ g_BaseSystem->CloseCpu();
+ }
+#endif
+ }
+}
+
+void CNotificationImp::AppInitDone(void)
+{
+}
+
+bool CNotificationImp::ProcessGuiMessages(void) const
+{
+ return false;
+}
+
+void CNotificationImp::ChangeFullScreen(void) const
+{
+}
\ No newline at end of file
diff --git a/Source/Android/Bridge/NotificationClass.h b/Source/Android/Bridge/NotificationClass.h
new file mode 100644
index 000000000..f51b51584
--- /dev/null
+++ b/Source/Android/Bridge/NotificationClass.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+* *
+* Project64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#pragma once
+
+#include
+
+class CNotificationImp :
+ public CNotification
+{
+public:
+ CNotificationImp(void);
+ virtual ~CNotificationImp();
+
+ //Error Messages
+ void DisplayError(const char * Message) const;
+ void DisplayError(LanguageStringID StringID) const;
+
+ void FatalError(const char * Message) const;
+ void FatalError(LanguageStringID StringID) const;
+
+ //User Feedback
+ void DisplayMessage(int DisplayTime, const char * Message) const;
+ void DisplayMessage(int DisplayTime, LanguageStringID StringID) const;
+
+ void DisplayMessage2(const char * Message) const;
+
+ // Ask a Yes/No Question to the user, yes = true, no = false
+ bool AskYesNoQuestion(const char * Question) const;
+ void BreakPoint(const char * FileName, int32_t LineNumber);
+
+ void AppInitDone(void);
+ bool ProcessGuiMessages(void) const;
+ void ChangeFullScreen(void) const;
+
+private:
+ CNotificationImp(const CNotificationImp&); // Disable copy constructor
+ CNotificationImp& operator=(const CNotificationImp&); // Disable assignment
+
+ mutable time_t m_NextMsg;
+};
+
+CNotificationImp & Notify(void);
\ No newline at end of file
diff --git a/Source/Android/Bridge/UISettings.cpp b/Source/Android/Bridge/UISettings.cpp
new file mode 100644
index 000000000..eccdbbbff
--- /dev/null
+++ b/Source/Android/Bridge/UISettings.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+* *
+* Project64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#include
+#include
+#include "UISettings.h"
+
+void RegisterUISettings(void)
+{
+ g_Settings->AddHandler((SettingID)(FirstUISettings + Asserts_Version), new CSettingTypeApplication("", "Asserts Version", (uint32_t)0));
+ g_Settings->AddHandler((SettingID)(FirstUISettings + Screen_Orientation), new CSettingTypeApplication("", "Screen Orientation", (uint32_t)0));
+}
+
+void UISettingsSaveBool(UISettingID Type, bool Value)
+{
+ g_Settings->SaveBool((SettingID)(FirstUISettings + Type), Value);
+ CSettings::FlushSettings(g_Settings);
+}
+
+void UISettingsSaveDword(UISettingID Type, uint32_t Value)
+{
+ g_Settings->SaveDword((SettingID)(FirstUISettings + Type), Value);
+ CSettings::FlushSettings(g_Settings);
+}
+
+bool UISettingsLoadBool(UISettingID Type)
+{
+ return g_Settings->LoadBool((SettingID)(FirstUISettings + Type));
+}
+
+uint32_t UISettingsLoadDword(UISettingID Type)
+{
+ return g_Settings->LoadDword((SettingID)(FirstUISettings + Type));
+}
+
diff --git a/Source/Android/Bridge/UISettings.h b/Source/Android/Bridge/UISettings.h
new file mode 100644
index 000000000..e5bb4d61a
--- /dev/null
+++ b/Source/Android/Bridge/UISettings.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+* *
+* Project64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#pragma once
+#include
+#include
+
+enum UISettingID
+{
+ Asserts_Version,
+ Screen_Orientation,
+};
+
+void RegisterUISettings(void);
+
+void UISettingsSaveBool(UISettingID Type, bool Value);
+void UISettingsSaveDword(UISettingID Type, uint32_t Value);
+
+bool UISettingsLoadBool(UISettingID Type);
+uint32_t UISettingsLoadDword(UISettingID Type);
+
+/*
+void UISettingsSaveBoolIndex(UISettingID Type, int32_t index, bool Value);
+void UISettingsSaveDwordIndex(UISettingID Type, int32_t index, uint32_t Value);
+void UISettingsSaveString(UISettingID Type, const std::string & Value);
+void UISettingsSaveStringIndex(UISettingID Type, int32_t index, const std::string & Value);
+
+void UISettingsDeleteSettingIndex(UISettingID Type, int32_t index);
+
+bool UISettingsLoadBoolIndex(UISettingID Type, int32_t index);
+bool UISettingsLoadDword(UISettingID Type, uint32_t & Value);
+bool UISettingsLoadDwordIndex(UISettingID Type, int index, uint32_t & Value);
+bool UISettingsLoadStringIndex(UISettingID Type, int32_t index, std::string & Value);
+std::string UISettingsLoadStringIndex(UISettingID Type, int32_t index);
+std::string UISettingsLoadStringVal(UISettingID Type);
+bool UISettingsLoadStringVal(UISettingID Type, char * Buffer, int32_t BufferSize);
+*/
\ No newline at end of file
diff --git a/Source/Android/Bridge/jniBridge.cpp b/Source/Android/Bridge/jniBridge.cpp
new file mode 100644
index 000000000..b23d1723b
--- /dev/null
+++ b/Source/Android/Bridge/jniBridge.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+* *
+* Project 64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#include
+#include "NotificationClass.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "jniBridge.h"
+#include "jniBridgeSettings.h"
+#include "JavaBridge.h"
+#include "UISettings.h"
+#include "JavaRomList.h"
+
+#ifdef _WIN32
+#define EXPORT extern "C" __declspec(dllexport)
+#define CALL __cdecl
+#else
+#define EXPORT extern "C" __attribute__((visibility("default")))
+#define CALL
+#endif
+
+CJniBridegSettings * JniBridegSettings = NULL;
+CJavaRomList * g_JavaRomList = NULL;
+
+#ifdef ANDROID
+#include
+
+class AndroidLogger : public CTraceModule
+{
+ void Write(uint32_t module, uint8_t severity, const char * file, int line, const char * function, const char * Message)
+ {
+ switch (severity)
+ {
+ case TraceError: __android_log_print(ANDROID_LOG_ERROR, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ case TraceWarning: __android_log_print(ANDROID_LOG_WARN, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ case TraceNotice: __android_log_print(ANDROID_LOG_INFO, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ case TraceInfo: __android_log_print(ANDROID_LOG_INFO, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ case TraceDebug: __android_log_print(ANDROID_LOG_DEBUG, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ case TraceVerbose: __android_log_print(ANDROID_LOG_VERBOSE, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ default: __android_log_print(ANDROID_LOG_UNKNOWN, TraceModule(module), "%05d: %s: %s",CThread::GetCurrentThreadId(),function,Message); break;
+ }
+ }
+};
+AndroidLogger * g_Logger = NULL;
+static pthread_key_t g_ThreadKey;
+static JavaVM* g_JavaVM = NULL;
+JavaBridge * g_JavaBridge = NULL;
+jobject g_Activity = NULL;
+jobject g_GLThread = NULL;
+
+static void Android_JNI_ThreadDestroyed(void*);
+static void Android_JNI_SetupThread(void);
+
+EXPORT jint CALL JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ __android_log_print(ANDROID_LOG_INFO, "jniBridge", "JNI_OnLoad called");
+ g_JavaVM = vm;
+
+ JNIEnv *env;
+ if (g_JavaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
+ {
+ __android_log_print(ANDROID_LOG_ERROR, "jniBridge", "Failed to get the environment using GetEnv()");
+ return -1;
+ }
+ /*
+ * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
+ * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
+ */
+ if (pthread_key_create(&g_ThreadKey, Android_JNI_ThreadDestroyed) != 0)
+ {
+ __android_log_print(ANDROID_LOG_ERROR, "jniBridge", "Error initializing pthread key");
+ }
+ Android_JNI_SetupThread();
+ return JNI_VERSION_1_4;
+}
+
+EXPORT jboolean CALL Java_emu_project64_jni_NativeExports_appInit(JNIEnv* env, jclass cls, jstring BaseDir)
+{
+ if (g_Logger == NULL)
+ {
+ g_Logger = new AndroidLogger();
+ }
+ TraceAddModule(g_Logger);
+
+ Notify().DisplayMessage(10, " ____ _ __ _____ __ __");
+ Notify().DisplayMessage(10, " / __ \\_________ (_)__ _____/ /_/ ___// // /");
+ Notify().DisplayMessage(10, " / /_/ / ___/ __ \\ / / _ \\/ ___/ __/ __ \\/ // /_");
+ Notify().DisplayMessage(10, " / ____/ / / /_/ / / / __/ /__/ /_/ /_/ /__ __/");
+ Notify().DisplayMessage(10, "/_/ /_/ \\____/_/ /\\___/\\___/\\__/\\____/ /_/");
+ Notify().DisplayMessage(10, " /___/");
+ Notify().DisplayMessage(10, "http://www.pj64-emu.com/");
+ Notify().DisplayMessage(10, stdstr_f("%s Version %s", VER_FILE_DESCRIPTION_STR, VER_FILE_VERSION_STR).c_str());
+ Notify().DisplayMessage(10, "");
+
+ if (g_JavaVM == NULL)
+ {
+ Notify().DisplayError("No java VM");
+ return false;
+ }
+
+ const char *baseDir = env->GetStringUTFChars(BaseDir, 0);
+ bool res = AppInit(&Notify(), baseDir, 0, NULL);
+
+ env->ReleaseStringUTFChars(BaseDir, baseDir);
+ if (res)
+ {
+ g_JavaBridge = new JavaBridge(g_JavaVM);
+ g_Plugins->SetRenderWindows(g_JavaBridge, NULL);
+
+ JniBridegSettings = new CJniBridegSettings();
+
+ RegisterUISettings();
+ }
+ else
+ {
+ AppCleanup();
+ }
+ return res;
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_SettingsSaveBool(JNIEnv* env, jclass cls, int Type, jboolean Value)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Saving %d value: %s",Type,Value ? "true" : "false");
+ g_Settings->SaveBool((SettingID)Type, Value);
+ WriteTrace(TraceUserInterface, TraceDebug, "Saved");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_SettingsSaveDword(JNIEnv* env, jclass cls, int Type, int Value)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Saving %d value: 0x%X",Type,Value);
+ g_Settings->SaveDword((SettingID)Type, Value);
+ WriteTrace(TraceUserInterface, TraceDebug, "Saved");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_SettingsSaveString(JNIEnv* env, jclass cls, int Type, jstring Buffer)
+{
+ const char *value = env->GetStringUTFChars(Buffer, 0);
+ WriteTrace(TraceUserInterface, TraceDebug, "Saving %d value: %s",Type,value);
+ g_Settings->SaveString((SettingID)Type, value);
+ WriteTrace(TraceUserInterface, TraceDebug, "Saved");
+ env->ReleaseStringUTFChars(Buffer, value);
+}
+
+EXPORT jboolean CALL Java_emu_project64_jni_NativeExports_SettingsLoadBool(JNIEnv* env, jclass cls, int Type)
+{
+ return g_Settings->LoadBool((SettingID)Type);
+}
+
+EXPORT jint CALL Java_emu_project64_jni_NativeExports_SettingsLoadDword(JNIEnv* env, jclass cls, int Type)
+{
+ return g_Settings->LoadDword((SettingID)Type);
+}
+
+EXPORT jstring CALL Java_emu_project64_jni_NativeExports_SettingsLoadString(JNIEnv* env, jclass cls, int Type)
+{
+ return env->NewStringUTF(g_Settings->LoadStringVal((SettingID)Type).c_str());
+}
+
+EXPORT jboolean CALL Java_emu_project64_jni_NativeExports_IsSettingSet(JNIEnv* env, jclass cls, int Type)
+{
+ return g_Settings->IsSettingSet((SettingID)Type);
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_LoadRomList(JNIEnv* env, jclass cls)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "start");
+ if (g_JavaRomList == NULL)
+ {
+ g_JavaRomList = new CJavaRomList;
+ }
+ g_JavaRomList->LoadRomList();
+
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_LoadGame(JNIEnv* env, jclass cls, jstring FileLoc, jobject activity, jobject GLThread)
+{
+ g_Activity = env->NewGlobalRef(activity);
+ g_GLThread = env->NewGlobalRef(GLThread);
+ const char *fileLoc = env->GetStringUTFChars(FileLoc, 0);
+ WriteTrace(TraceUserInterface, TraceDebug, "FileLoc: %s",fileLoc);
+ g_Settings->SaveBool(Setting_AutoStart,false);
+ CN64System::RunFileImage(fileLoc);
+ env->ReleaseStringUTFChars(FileLoc, fileLoc);
+ WriteTrace(TraceUserInterface, TraceDebug, "Image loaded");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_StartGame(JNIEnv* env, jclass cls)
+{
+ g_BaseSystem->StartEmulation(true);
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_RefreshRomDir(JNIEnv* env, jclass cls, jstring RomDir, jboolean Recursive)
+{
+ const char *romDir = env->GetStringUTFChars(RomDir, 0);
+ WriteTrace(TraceUserInterface, TraceDebug, "romDir = %s Recursive = %s", romDir, Recursive ? "true" : "false");
+ g_Settings->SaveString(RomList_GameDir,romDir);
+ g_Settings->SaveBool(RomList_GameDirRecursive,Recursive);
+ env->ReleaseStringUTFChars(RomDir, romDir);
+
+ if (g_JavaRomList == NULL)
+ {
+ g_JavaRomList = new CJavaRomList;
+ }
+ g_JavaRomList->RefreshRomList();
+
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_ExternalEvent(JNIEnv* env, jclass cls, int Type)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Start (Type: %d)",Type);
+ if (g_BaseSystem)
+ {
+ g_BaseSystem->ExternalEvent((SystemEvent)Type);
+ }
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_onSurfaceCreated(JNIEnv * env, jclass cls)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Start");
+ if (g_Plugins != NULL && g_Plugins->Gfx() != NULL && g_Plugins->Gfx()->SurfaceCreated)
+ {
+ g_Plugins->Gfx()->SurfaceCreated();
+ }
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_onSurfaceChanged(JNIEnv * env, jclass cls, jint width, jint height)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Start");
+ if (g_Plugins != NULL && g_Plugins->Gfx() != NULL && g_Plugins->Gfx()->SurfaceChanged)
+ {
+ g_Plugins->Gfx()->SurfaceChanged(width,height);
+ }
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_UISettingsSaveBool(JNIEnv* env, jclass cls, jint Type, jboolean Value)
+{
+ UISettingsSaveBool((UISettingID)Type, Value);
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_UISettingsSaveDword(JNIEnv* env, jclass cls, jint Type, jint Value)
+{
+ UISettingsSaveDword((UISettingID)Type, Value);
+}
+
+EXPORT jboolean CALL Java_emu_project64_jni_NativeExports_UISettingsLoadBool(JNIEnv* env, jclass cls, jint Type)
+{
+ return UISettingsLoadBool((UISettingID)Type);
+}
+
+EXPORT int CALL Java_emu_project64_jni_NativeExports_UISettingsLoadDword(JNIEnv* env, jclass cls, jint Type)
+{
+ return UISettingsLoadDword((UISettingID)Type);
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_StopEmulation(JNIEnv* env, jclass cls)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Start");
+ if (g_BaseSystem)
+ {
+ g_BaseSystem->CloseCpu();
+ }
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_StartEmulation(JNIEnv* env, jclass cls)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Start");
+ if (g_BaseSystem)
+ {
+ g_BaseSystem->StartEmulation(true);
+ }
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+EXPORT void CALL Java_emu_project64_jni_NativeExports_CloseSystem(JNIEnv* env, jclass cls)
+{
+ WriteTrace(TraceUserInterface, TraceDebug, "Start");
+ CN64System::CloseSystem();
+ env->DeleteGlobalRef(g_Activity);
+ g_Activity = NULL;
+ env->DeleteGlobalRef(g_GLThread);
+ g_GLThread = NULL;
+ WriteTrace(TraceUserInterface, TraceDebug, "Done");
+}
+
+static void Android_JNI_ThreadDestroyed(void* value)
+{
+ __android_log_print(ANDROID_LOG_ERROR, "Android_JNI_ThreadDestroyed", "start");
+
+ /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
+ JNIEnv *env = (JNIEnv*)value;
+ if (env != NULL)
+ {
+ g_JavaVM->DetachCurrentThread();
+ pthread_setspecific(g_ThreadKey, NULL);
+ }
+ __android_log_print(ANDROID_LOG_ERROR, "Android_JNI_ThreadDestroyed", "Done");
+}
+
+JNIEnv* Android_JNI_GetEnv(void)
+{
+ /* From http://developer.android.com/guide/practices/jni.html
+ * All threads are Linux threads, scheduled by the kernel.
+ * They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then
+ * attached to the JavaVM. For example, a thread started with pthread_create can be attached with the
+ * JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv,
+ * and cannot make JNI calls.
+ * Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main"
+ * ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread
+ * is a no-op.
+ * Note: You can call this function any number of times for the same thread, there's no harm in it
+ */
+
+ JNIEnv *env;
+ int status = g_JavaVM->AttachCurrentThread(&env, NULL);
+ if (status < 0)
+ {
+ __android_log_print(ANDROID_LOG_ERROR, "jniBridge", "failed to attach current thread");
+ return 0;
+ }
+
+ /* From http://developer.android.com/guide/practices/jni.html
+ * Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward,
+ * in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be
+ * called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific
+ * to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
+ * Note: The destructor is not called unless the stored value is != NULL
+ * Note: You can call this function any number of times for the same thread, there's no harm in it
+ * (except for some lost CPU cycles)
+ */
+ pthread_setspecific(g_ThreadKey, (void*)env);
+ return env;
+}
+
+void Android_JNI_SetupThread(void)
+{
+ Android_JNI_GetEnv();
+}
+
+#endif
\ No newline at end of file
diff --git a/Source/Android/Bridge/jniBridge.h b/Source/Android/Bridge/jniBridge.h
new file mode 100644
index 000000000..9376ebbc1
--- /dev/null
+++ b/Source/Android/Bridge/jniBridge.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef ANDROID
+#include
+
+JNIEnv* Android_JNI_GetEnv(void);
+
+extern jobject g_Activity;
+extern jobject g_GLThread;
+
+#endif
\ No newline at end of file
diff --git a/Source/Android/Bridge/jniBridgeSettings.cpp b/Source/Android/Bridge/jniBridgeSettings.cpp
new file mode 100644
index 000000000..268e251c7
--- /dev/null
+++ b/Source/Android/Bridge/jniBridgeSettings.cpp
@@ -0,0 +1,40 @@
+/****************************************************************************
+* *
+* Project64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#include "jniBridgeSettings.h"
+#include
+
+int CJniBridegSettings::m_RefCount = 0;
+bool CJniBridegSettings::m_bCPURunning;
+
+CJniBridegSettings::CJniBridegSettings()
+{
+ m_RefCount += 1;
+ if (m_RefCount == 1)
+ {
+ g_Settings->RegisterChangeCB(GameRunning_CPU_Running,NULL,RefreshSettings);
+ RefreshSettings(NULL);
+ }
+}
+
+CJniBridegSettings::~CJniBridegSettings()
+{
+ m_RefCount -= 1;
+ if (m_RefCount == 0)
+ {
+ g_Settings->UnregisterChangeCB(GameRunning_CPU_Running,NULL,RefreshSettings);
+ }
+}
+
+void CJniBridegSettings::RefreshSettings(void *)
+{
+ m_bCPURunning = g_Settings->LoadBool(GameRunning_CPU_Running);
+}
+
diff --git a/Source/Android/Bridge/jniBridgeSettings.h b/Source/Android/Bridge/jniBridgeSettings.h
new file mode 100644
index 000000000..971789445
--- /dev/null
+++ b/Source/Android/Bridge/jniBridgeSettings.h
@@ -0,0 +1,27 @@
+/****************************************************************************
+* *
+* Project64 - A Nintendo 64 emulator. *
+* http://www.pj64-emu.com/ *
+* Copyright (C) 2012 Project64. All rights reserved. *
+* *
+* License: *
+* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
+* *
+****************************************************************************/
+#pragma once
+
+class CJniBridegSettings
+{
+public:
+ CJniBridegSettings();
+ ~CJniBridegSettings();
+
+ static inline bool bCPURunning ( void) { return m_bCPURunning; }
+
+private:
+ static void RefreshSettings (void *);
+
+ static bool m_bCPURunning;
+
+ static int m_RefCount;
+};