diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 8bea55896..090eabd2c 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -260,7 +260,7 @@ bool rend_frame(TA_context* ctx, bool draw_osd) { bool do_swp = proc && renderer->Render(); if (do_swp && draw_osd) - renderer->DrawOSD(); + renderer->DrawOSD(false); return do_swp; } @@ -273,14 +273,13 @@ bool rend_single_frame() // FIXME not here os_DoEvents(); #if !defined(TARGET_NO_THREADS) - if (gui_is_open()) + if (gui_is_open() || gui_state == VJoyEdit) { - if (!rs.Wait(1000 / 60) || !rend_framePending()) // !rend_framePending() needed for OSX - { - gui_display_ui(); - FinishRender(NULL); - return true; - } + gui_display_ui(); + if (gui_state == VJoyEdit && renderer != NULL) + renderer->DrawOSD(true); + FinishRender(NULL); + return true; } else { @@ -381,10 +380,6 @@ void rend_term_renderer() void* rend_thread(void* p) { -#if FEAT_HAS_NIXPROF - install_prof_handler(1); -#endif - rend_init_renderer(); //we don't know if this is true, so let's not speculate here diff --git a/core/hw/pvr/Renderer_if.h b/core/hw/pvr/Renderer_if.h index 3625a2159..8bd991835 100644 --- a/core/hw/pvr/Renderer_if.h +++ b/core/hw/pvr/Renderer_if.h @@ -45,7 +45,7 @@ struct Renderer virtual void Present()=0; - virtual void DrawOSD() { } + virtual void DrawOSD(bool clear_screen) { } virtual u32 GetTexture(TSP tsp, TCW tcw) { return 0; } }; diff --git a/core/input/gamepad_device.h b/core/input/gamepad_device.h index 7ad8f5c1b..b8f7e269d 100644 --- a/core/input/gamepad_device.h +++ b/core/input/gamepad_device.h @@ -52,6 +52,7 @@ public: InputMapping *get_input_mapping() { return input_mapper; } void save_mapping(); bool remappable() { return _remappable && input_mapper != NULL; } + virtual bool is_virtual_gamepad() { return false; } virtual void rumble(float power, float inclination, u32 duration_ms) {} virtual void update_rumble() {} diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp index 4f94856f7..cee37671d 100644 --- a/core/linux-dist/main.cpp +++ b/core/linux-dist/main.cpp @@ -54,20 +54,6 @@ #include "profiler/profiler.h" #endif -int msgboxf(const wchar* text, unsigned int type, ...) -{ - va_list args; - - wchar temp[2048]; - va_start(args, type); - vsprintf(temp, text, args); - va_end(args); - - //printf(NULL,temp,VER_SHORTNAME,type | MB_TASKMODAL); - puts(temp); - return MBX_OK; -} - void* x11_win = 0; void* x11_disp = 0; diff --git a/core/nullDC.cpp b/core/nullDC.cpp index e6f27f142..dd79c00db 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -504,6 +504,7 @@ void InitSettings() settings.input.MouseSensitivity = 100; settings.input.JammaSetup = 0; + settings.input.VirtualGamepadVibration = 20; for (int i = 0; i < MAPLE_PORTS; i++) { settings.input.maple_devices[i] = i == 0 ? MDT_SegaController : MDT_None; @@ -583,6 +584,7 @@ void LoadSettings(bool game_specific) settings.input.MouseSensitivity = cfgLoadInt(input_section, "MouseSensitivity", settings.input.MouseSensitivity); settings.input.JammaSetup = cfgLoadInt(input_section, "JammaSetup", settings.input.JammaSetup); + settings.input.VirtualGamepadVibration = cfgLoadInt(input_section, "VirtualGamepadVibration", settings.input.VirtualGamepadVibration); for (int i = 0; i < MAPLE_PORTS; i++) { char device_name[32]; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 62fcee621..505b1d23f 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -954,12 +954,12 @@ struct gl4rend : Renderer void Present() { gl_swap(); } - void DrawOSD() + void DrawOSD(bool clear_screen) { glBindVertexArray(gl4.vbo.main_vao); glBindBuffer(GL_ARRAY_BUFFER, gl4.vbo.geometry); glCheck(); - OSD_DRAW(); + OSD_DRAW(clear_screen); } virtual u32 GetTexture(TSP tsp, TCW tcw) { diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index e64750e6c..f9371984c 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -1433,7 +1433,7 @@ static void osd_gen_vertices() #define OSD_TEX_W 512 #define OSD_TEX_H 256 -void OSD_DRAW() +void OSD_DRAW(bool clear_screen) { #ifndef TARGET_PANDORA if (osd_tex) @@ -1491,6 +1491,11 @@ void OSD_DRAW() glcache.Disable(GL_SCISSOR_TEST); glViewport(0, 0, screen_width, screen_height); + if (clear_screen) + { + glcache.ClearColor(0.7f, 0.7f, 0.7f, 1.f); + glClear(GL_COLOR_BUFFER_BIT); + } int dfa = osd_vertices.used() / 4; for (int i = 0; i < dfa; i++) @@ -1979,7 +1984,7 @@ struct glesrend : Renderer bool RenderLastFrame() { return render_output_framebuffer(); } void Present() { gl_swap(); glViewport(0, 0, screen_width, screen_height); } - void DrawOSD() + void DrawOSD(bool clear_screen) { if (gl.gl_major >= 3) glBindVertexArray(gl.vbo.vao); @@ -1993,7 +1998,7 @@ struct glesrend : Renderer glEnableVertexAttribArray(VERTEX_UV_ARRAY); glVertexAttribPointer(VERTEX_UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex,u)); - OSD_DRAW(); + OSD_DRAW(clear_screen); } virtual u32 GetTexture(TSP tsp, TCW tcw) { diff --git a/core/rend/gles/imgui_impl_opengl3.cpp b/core/rend/gles/imgui_impl_opengl3.cpp index 61391b3d3..3fe069942 100644 --- a/core/rend/gles/imgui_impl_opengl3.cpp +++ b/core/rend/gles/imgui_impl_opengl3.cpp @@ -579,4 +579,9 @@ void ImGui_ImplOpenGL3_DrawBackground() ImGui::GetWindowDrawList()->AddImage((ImTextureID)(uintptr_t)g_BackgroundTexture, ImVec2(0, 0), io.DisplaySize, ImVec2(0, 1), ImVec2(1, 0), 0xffffffff); ImGui::End(); } + else + { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } } diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index f5b03b721..06d5aaf8a 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -21,6 +21,7 @@ #include #include +#include "gui.h" #include "oslib/oslib.h" #include "cfg/cfg.h" #include "hw/maple/maple_cfg.h" @@ -32,6 +33,8 @@ #include "input/keyboard_device.h" #include "linux-dist/main.h" // FIXME for kcode[] #include "gui_util.h" +#include "gui_android.h" +#include "version/version.h" extern void dc_loadstate(); extern void dc_savestate(); @@ -57,7 +60,7 @@ int screen_dpi = 96; static bool inited = false; static float scaling = 1; -static enum { Closed, Commands, Settings, ClosedNoResume, Main, Onboarding } gui_state = Main; +GuiState gui_state = Main; static bool settings_opening; static bool touch_up; @@ -138,7 +141,7 @@ void gui_init() printf("Screen DPI is %d, size %d x %d. Scaling by %.2f\n", screen_dpi, screen_width, screen_height, scaling); } -static void ImGui_Impl_NewFrame() +void ImGui_Impl_NewFrame() { ImGui_ImplOpenGL3_NewFrame(); ImGui::GetIO().DisplaySize.x = screen_width; @@ -272,11 +275,15 @@ void gui_open_settings() settings_opening = true; HideOSD(); } + else if (gui_state == VJoyEdit) + { + gui_state = VJoyEditCommands; + } } bool gui_is_open() { - return gui_state != Closed; + return gui_state != Closed && gui_state != VJoyEdit; } static void gui_display_commands() @@ -561,6 +568,32 @@ static void controller_mapping_popup(std::shared_ptr gamepad) ImGui::PopStyleVar(); } +static std::string error_msg; + +static void error_popup() +{ + if (!error_msg.empty()) + { + if (ImGui::BeginPopupModal("Error", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) + { + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + 400.f * scaling); + ImGui::TextWrapped(error_msg.c_str()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16 * scaling, 3 * scaling)); + float currentwidth = ImGui::GetContentRegionAvailWidth(); + ImGui::SetCursorPosX((currentwidth - 80.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x); + if (ImGui::Button("OK", ImVec2(80.f * scaling, 0.f))) + { + error_msg.clear(); + ImGui::CloseCurrentPopup(); + } + ImGui::SetItemDefaultFocus(); + ImGui::PopStyleVar(); + ImGui::EndPopup(); + } + ImGui::OpenPopup("Error"); + } +} + static bool game_list_done; // Set to false to refresh the game list void directory_selected_callback(bool cancelled, std::string selection) @@ -833,6 +866,18 @@ static void gui_display_settings() controller_mapping_popup(gamepad); +#ifdef _ANDROID + if (gamepad->is_virtual_gamepad()) + { + if (ImGui::Button("Edit")) + { + vjoy_start_editing(); + gui_state = VJoyEdit; + } + ImGui::SameLine(); + ImGui::SliderInt("Haptic", &settings.input.VirtualGamepadVibration, 0, 60); + } +#endif ImGui::NextColumn(); ImGui::PopID(); } @@ -969,6 +1014,78 @@ static void gui_display_settings() ImGui::PopStyleVar(); ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("About")) + { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, normal_padding); + if (ImGui::CollapsingHeader("Reicast", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Version: %s", version); + ImGui::Text("Git Hash: %s", git_hash); + ImGui::Text("Build Date: %s", build_date); + ImGui::Text("Target: %s", +#if DC_PLATFORM == DC_PLATFORM_DREAMCAST + "Dreamcast" +#elif DC_PLATFORM == DC_PLATFORM_NAOMI + "Naomi" +#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE + "Atomiswave" +#else + "Unknown" +#endif + ); + } + if (ImGui::CollapsingHeader("Platform", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("CPU: %s", +#if HOST_CPU == CPU_X86 + "x86" +#elif HOST_CPU == CPU_ARM + "ARM" +#elif HOST_CPU == CPU_MIPS + "MIPS" +#elif HOST_CPU == CPU_X64 + "x86/64" +#elif HOST_CPU == CPU_GENERIC + "Generic" +#elif HOST_CPU == CPU_ARM64 + "ARM64" +#else + "Unknown" +#endif + ); + ImGui::Text("Operating System: %s", +#ifdef _ANDROID + "Android" +#elif HOST_OS == OS_LINUX + "Linux" +#elif HOST_OS == OS_DARWIN +#if TARGET_IPHONE + "iOS" +#else + "OSX" +#endif +#elif HOST_OS == OS_WINDOWS + "Windows" +#else + "Unknown" +#endif + ); + } + if (ImGui::CollapsingHeader("Open GL", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Renderer: %s", (const char *)glGetString(GL_RENDERER)); + ImGui::Text("Version: %s", (const char *)glGetString(GL_VERSION)); + } +#ifdef _ANDROID + ImGui::Separator(); + if (ImGui::Button("Send Logs")) { + void android_send_logs(); + android_send_logs(); + } +#endif + ImGui::PopStyleVar(); + ImGui::EndTabItem(); + } ImGui::EndTabBar(); } ImGui::PopStyleVar(); @@ -1081,7 +1198,25 @@ static void gui_display_demo() static void gui_start_game(const std::string& path) { - dc_start_game(path.c_str()); + int rc = dc_start_game(path.c_str()); + if (rc != 0) + { + gui_state = Main; + game_started = false; + switch (rc) { + case -3: + error_msg = "Audio/video initialization failed"; + break; + case -5: + error_msg = "Cannot find BIOS files"; + break; + case -6: + error_msg = "Cannot load NAOMI rom"; + break; + default: + break; + } + } } static void gui_display_content() @@ -1124,8 +1259,8 @@ static void gui_display_content() ImGui::PushID(game.path.c_str()); if (ImGui::Selectable(game.name.c_str())) { - gui_start_game(game.path); gui_state = ClosedNoResume; + gui_start_game(game.path); } ImGui::PopID(); } @@ -1135,6 +1270,8 @@ static void gui_display_content() ImGui::End(); ImGui::PopStyleVar(); + error_popup(); + ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData(), false); } @@ -1149,7 +1286,9 @@ void systemdir_selected_callback(bool cancelled, std::string selection) { LoadSettings(false); gui_state = Main; - // FIXME Save config dir in android app prefs + if (settings.dreamcast.ContentPath.empty()) + settings.dreamcast.ContentPath.push_back(selection); + SaveSettings(); } } } @@ -1186,6 +1325,13 @@ void gui_display_ui() case Onboarding: gui_display_onboarding(); break; + case VJoyEdit: + break; + case VJoyEditCommands: +#ifdef _ANDROID + gui_display_vjoy_commands(screen_width, screen_height, scaling); +#endif + break; } if (gui_state == Closed) @@ -1235,9 +1381,9 @@ static std::string getFPSNotification() LastFPSTime = now; lastFrameCount = FrameCount; } - if (fps >= 0) { + if (fps >= 0.f && fps < 9999.f) { char text[32]; - sprintf(text, "F:%.1f", fps); + snprintf(text, sizeof(text), "F:%.1f", fps); return std::string(text); } @@ -1247,6 +1393,8 @@ static std::string getFPSNotification() void gui_display_osd() { + if (gui_state == VJoyEdit) + return; double now = os_GetSeconds(); if (!osd_message.empty()) { @@ -1290,3 +1438,18 @@ void gui_term() ImGui_ImplOpenGL3_Shutdown(); ImGui::DestroyContext(); } + +int msgboxf(const wchar* text, unsigned int type, ...) { + va_list args; + + wchar temp[2048]; + va_start(args, type); + vsnprintf(temp, sizeof(temp), text, args); + va_end(args); + printf("%s", temp); + + gui_display_notification(temp, 2000); + + return 1; +} + diff --git a/core/rend/gui.h b/core/rend/gui.h index fb2dc489f..a03680b92 100644 --- a/core/rend/gui.h +++ b/core/rend/gui.h @@ -28,3 +28,8 @@ void gui_open_onboarding(); void gui_term(); extern int screen_dpi; + +typedef enum { Closed, Commands, Settings, ClosedNoResume, Main, Onboarding, VJoyEdit, VJoyEditCommands } GuiState; +extern GuiState gui_state; +void ImGui_Impl_NewFrame(); + diff --git a/core/rend/gui_android.cpp b/core/rend/gui_android.cpp new file mode 100644 index 000000000..5aff13ec7 --- /dev/null +++ b/core/rend/gui_android.cpp @@ -0,0 +1,68 @@ +/* + Copyright 2019 flyinghead + + This file is part of reicast. + + reicast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + reicast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with reicast. If not, see . + */ +#ifdef _ANDROID + +#include "gui_android.h" +#include "gui.h" + +#include "types.h" +#include "stdclass.h" +#include "imgui/imgui.h" +#include "gles/imgui_impl_opengl3.h" + +extern bool settings_opening; + +void vjoy_reset_editing(); +void vjoy_stop_editing(bool canceled); + +void gui_display_vjoy_commands(int screen_width, int screen_height, float scaling) +{ + ImGui_Impl_NewFrame(); + ImGui::NewFrame(); + + ImGui::SetNextWindowPos(ImVec2(screen_width / 2.f, screen_height / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + + ImGui::Begin("Virtual Joystick", NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse + | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize); + + if (ImGui::Button("Save", ImVec2(150 * scaling, 50 * scaling))) + { + vjoy_stop_editing(false); + gui_state = Settings; + } + ImGui::SameLine(); + if (ImGui::Button("Reset", ImVec2(150 * scaling, 50 * scaling))) + { + vjoy_reset_editing(); + gui_state = VJoyEdit; + } + + ImGui::SameLine(); + if (ImGui::Button("Cancel", ImVec2(150 * scaling, 50 * scaling))) + { + vjoy_stop_editing(true); + gui_state = Settings; + } + ImGui::End(); + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData(), false); +} + +#endif // _ANDROID diff --git a/core/rend/gui_android.h b/core/rend/gui_android.h new file mode 100644 index 000000000..48d071ff7 --- /dev/null +++ b/core/rend/gui_android.h @@ -0,0 +1,20 @@ +/* + Copyright 2019 flyinghead + + This file is part of reicast. + + reicast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + reicast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with reicast. If not, see . + */ +void gui_display_vjoy_commands(int screen_width, int screen_height, float scaling); +void vjoy_start_editing(); diff --git a/core/rend/gui_util.cpp b/core/rend/gui_util.cpp index 96d37d63b..137c665ac 100644 --- a/core/rend/gui_util.cpp +++ b/core/rend/gui_util.cpp @@ -117,6 +117,7 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca while (home != NULL) { const char *pcolon = strchr(home, ':'); + // FIXME Java was doing this: String sdCardPath = sd.replace("mnt/media_rw", "storage"); if (pcolon != NULL) { select_subfolders.push_back(std::string(home, pcolon - home)); diff --git a/core/types.h b/core/types.h index 383e80c93..739871ab7 100644 --- a/core/types.h +++ b/core/types.h @@ -815,6 +815,7 @@ struct settings_t // 4: dual I/O boards (4P), 5: Namco JYU board (Ninja Assault) int maple_devices[4]; int maple_expansion_devices[4][2]; + int VirtualGamepadVibration; } input; }; diff --git a/core/version/.gitignore b/core/version/.gitignore new file mode 100644 index 000000000..1946cee8c --- /dev/null +++ b/core/version/.gitignore @@ -0,0 +1 @@ +/version.cpp diff --git a/core/windows/winmain.cpp b/core/windows/winmain.cpp index d80315054..d54e44a97 100644 --- a/core/windows/winmain.cpp +++ b/core/windows/winmain.cpp @@ -181,19 +181,6 @@ void SetupPath() set_user_data_dir(fn); } -int msgboxf(const wchar* text,unsigned int type,...) -{ - va_list args; - - wchar temp[2048]; - va_start(args, type); - vsprintf(temp, text, args); - va_end(args); - - - return MessageBox(NULL,temp,VER_SHORTNAME,type | MB_TASKMODAL); -} - // Gamepads u16 kcode[4] = { 0xffff, 0xffff, 0xffff, 0xffff }; u32 vks[4]; diff --git a/shell/android-studio/reicast/src/main/AndroidManifest.xml b/shell/android-studio/reicast/src/main/AndroidManifest.xml index 1d6cf003d..fb0b0ab3a 100644 --- a/shell/android-studio/reicast/src/main/AndroidManifest.xml +++ b/shell/android-studio/reicast/src/main/AndroidManifest.xml @@ -68,7 +68,7 @@ android:name="com.reicast.emulator.NativeGLActivity" android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden" android:screenOrientation="sensorLandscape" - android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > + android:theme="@style/AppTheme.NoActionBar"> - output_field) { - try { - FileOutputStream fos = new FileOutputStream(filename); - GZIPOutputStream gzos = new GZIPOutputStream(fos); - ObjectOutputStream out = new ObjectOutputStream(gzos); - out.writeObject(output_field); - out.flush(); - out.close(); - } catch (IOException e) { - e.getStackTrace(); - } - } - - @SuppressWarnings("unchecked") - public List loadArray(String filename) { - try { - FileInputStream fis = new FileInputStream(filename); - GZIPInputStream gzis = new GZIPInputStream(fis); - ObjectInputStream in = new ObjectInputStream(gzis); - List read_field = (List) in.readObject(); - in.close(); - return read_field; - } catch (Exception e) { - e.getStackTrace(); - } - return null; - } - public Collection listFiles(File directory, FilenameFilter[] filter, int recurse) { diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/AboutFragment.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/AboutFragment.java deleted file mode 100644 index a6b13d13d..000000000 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/AboutFragment.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.reicast.emulator; - -import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.support.constraint.ConstraintLayout; -import android.support.design.widget.Snackbar; -import android.support.graphics.drawable.VectorDrawableCompat; -import android.support.v4.app.Fragment; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; -import android.widget.TextView; - -import com.reicast.emulator.config.Config; -import com.reicast.emulator.debug.GitAdapter; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.ref.WeakReference; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; - -import javax.net.ssl.HttpsURLConnection; - -public class AboutFragment extends Fragment { - - String buildId = ""; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.about_fragment, container, false); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - - try { - String versionName = getActivity().getPackageManager() - .getPackageInfo(getActivity().getPackageName(), 0).versionName; - int versionCode = getActivity().getPackageManager() - .getPackageInfo(getActivity().getPackageName(), 0).versionCode; - TextView version = (TextView) getView().findViewById(R.id.revision_text); - version.setText(getString(R.string.revision_text, - versionName, String.valueOf(versionCode))); - int start = versionName.lastIndexOf("-"); - buildId = versionName.substring(start + 2, start + 9); - } catch (NameNotFoundException e) { - e.printStackTrace(); - } - - new retrieveGitTask(this).execute(Config.git_api); - } - - private static class retrieveGitTask extends - AsyncTask>> { - - private WeakReference ref; - - retrieveGitTask(AboutFragment context) { - ref = new WeakReference<>(context); - } - - @Override - protected ArrayList> doInBackground( - String... paths) { - ArrayList> commitList = new ArrayList<>(); - try { - JSONArray gitObject = getContent(paths[0]); - for (int i = 0; i < gitObject.length(); i++) { - JSONObject jsonObject = gitObject.getJSONObject(i); - - JSONObject commitArray = jsonObject.getJSONObject("commit"); - - String date = commitArray.getJSONObject("committer") - .getString("date").replace("T", " ").replace("Z", ""); - String author = commitArray.getJSONObject("author").getString("name"); - String committer = commitArray.getJSONObject("committer").getString("name"); - - String avatar; - if (!jsonObject.getString("committer").equals("null")) { - avatar = jsonObject.getJSONObject("committer").getString("avatar_url"); - committer = committer + " (" + jsonObject - .getJSONObject("committer").getString("login") + ")"; - if (avatar.equals("null")) { - avatar = "https://github.com/apple-touch-icon-144.png"; - } - } else { - avatar = "https://github.com/apple-touch-icon-144.png"; - } - if (!jsonObject.getString("author").equals("null")) { - author = author + " (" + jsonObject.getJSONObject( - "author").getString("login") + ")"; - } - String sha = jsonObject.getString("sha"); - String curl = jsonObject.getString("url") - .replace("https://api.github.com/repos", "https://github.com") - .replace("commits", "commit"); - - String title; - String message = "No commit message attached"; - - if (commitArray.getString("message").contains("\n\n")) { - String fullOutput = commitArray.getString("message"); - title = fullOutput.substring(0, fullOutput.indexOf("\n\n")); - message = fullOutput.substring( - fullOutput.indexOf("\n\n") + 1, fullOutput.length()); - } else { - title = commitArray.getString("message"); - } - - HashMap map = new HashMap<>(); - map.put("Date", date); - map.put("Committer", committer); - map.put("Title", title); - map.put("Message", message); - map.put("Sha", sha); - map.put("Url", curl); - map.put("Author", author); - map.put("Avatar", avatar); - map.put("Build", ref.get().buildId); - commitList.add(map); - } - - } catch (JSONException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - return commitList; - } - - @Override - protected void onPostExecute( - ArrayList> commitList) { - if (commitList != null && commitList.size() > 0) { - ListView list = (ListView) ref.get().getView().findViewById(R.id.list); - list.setSelector(R.drawable.list_selector); - list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); - GitAdapter adapter = new GitAdapter(ref.get().getActivity(), commitList); - // Set adapter as specified collection - list.setAdapter(adapter); - } else { - ref.get().showToastMessage(ref.get().getActivity().getString( - R.string.git_broken), Snackbar.LENGTH_SHORT); - } - - } - - private JSONArray getContent(String urlString) throws IOException, JSONException { - HttpURLConnection conn = (HttpURLConnection) new URL(urlString).openConnection(); - conn.setRequestMethod("GET"); - conn.setDoInput(true); - - int responseCode = conn.getResponseCode(); - if (responseCode == HttpsURLConnection.HTTP_OK) { - InputStream in = conn.getInputStream(); - BufferedReader streamReader = new BufferedReader( - new InputStreamReader(in, "UTF-8")); - StringBuilder responseStrBuilder = new StringBuilder(); - - String inputStr; - while ((inputStr = streamReader.readLine()) != null) - responseStrBuilder.append(inputStr); - - in.close(); - return new JSONArray(responseStrBuilder.toString()); - } - return null; - } - } - - private void showToastMessage(String message, int duration) { - ConstraintLayout layout = (ConstraintLayout) getActivity().findViewById(R.id.mainui_layout); - Snackbar snackbar = Snackbar.make(layout, message, duration); - View snackbarLayout = snackbar.getView(); - TextView textView = (TextView) snackbarLayout.findViewById( - android.support.design.R.id.snackbar_text); - textView.setGravity(Gravity.CENTER_VERTICAL); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) - textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY); - Drawable drawable; - if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { - drawable = getResources().getDrawable( - R.drawable.ic_info_outline, getActivity().getTheme()); - } else { - drawable = VectorDrawableCompat.create(getResources(), - R.drawable.ic_info_outline, getActivity().getTheme()); - } - textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); - textView.setCompoundDrawablePadding(getResources() - .getDimensionPixelOffset(R.dimen.snackbar_icon_padding)); - snackbar.show(); - } -} diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/BaseNativeGLActivity.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/BaseNativeGLActivity.java index 6942e5a5b..f62c715a9 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/BaseNativeGLActivity.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/BaseNativeGLActivity.java @@ -10,38 +10,18 @@ import android.view.SurfaceHolder; import com.reicast.emulator.emu.JNIdc; import com.reicast.emulator.emu.NativeGLView; -public class BaseNativeGLActivity extends Activity implements SurfaceHolder.Callback { - protected boolean editVjoyMode; +public class BaseNativeGLActivity extends Activity { protected NativeGLView mView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - String fileName = null; - if (getIntent().getAction().equals("com.reicast.EMULATOR")) - fileName = Uri.decode(getIntent().getData().toString()); - // Create the actual GL view - try { - mView = new NativeGLView(this, fileName, editVjoyMode); - setContentView(mView); - mView.getHolder().addCallback(this); - } catch (NativeGLView.EmulatorInitFailed e) { - finish(); - } - } - - @Override - protected void onPause() { - super.onPause(); - JNIdc.pause(); - } - - @Override - protected void onResume() { - super.onResume(); - JNIdc.resume(); +// mView = new NativeGLView(this); +// setContentView(mView); + setContentView(R.layout.nativegl_content); + mView = (NativeGLView)findViewById(R.id.glView); } @Override @@ -51,25 +31,6 @@ public class BaseNativeGLActivity extends Activity implements SurfaceHolder.Call } protected void stopEmulator() { - if (mView != null) { - mView.stop(); - } - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - //Log.i("BaseNativeGLActivity", "surfaceChanged: " + w + "x" + h); - JNIdc.rendinitNative(holder.getSurface(), w, h); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - //Log.i("BaseNativeGLActivity", "surfaceDestroyed"); - JNIdc.rendinitNative(null, 0, 0); + JNIdc.stop(); } } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/Emulator.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/Emulator.java index 2e33c29b0..06882158c 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/Emulator.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/Emulator.java @@ -1,6 +1,5 @@ package com.reicast.emulator; -import android.app.Activity; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; @@ -9,41 +8,12 @@ import android.support.v7.app.AppCompatDelegate; import android.util.Log; import com.reicast.emulator.config.Config; +import com.reicast.emulator.emu.AudioBackend; import com.reicast.emulator.emu.JNIdc; public class Emulator extends Application { private static Context context; - public static final String pref_dynarecopt = "dynarec_opt"; - public static final String pref_unstable = "unstable_opt"; - public static final String pref_dynsafemode = "dyn_safemode"; - public static final String pref_idleskip = "idle_skip"; - public static final String pref_cable = "dc_cable"; - public static final String pref_dcregion = "dc_region"; - public static final String pref_broadcast = "dc_broadcast"; - public static final String pref_language = "dc_language"; - public static final String pref_limitfps = "limit_fps"; - public static final String pref_nosound = "sound_disabled"; - public static final String pref_nobatch = "nobatch"; - public static final String pref_interrupt = "delay_interrupt"; - public static final String pref_mipmaps = "use_mipmaps"; - public static final String pref_widescreen = "stretch_view"; - public static final String pref_frameskip = "frame_skip"; - public static final String pref_pvrrender = "pvr_render"; - public static final String pref_syncedrender = "synced_render"; - public static final String pref_modvols = "modifier_volumes"; - public static final String pref_clipping = "clipping"; - public static final String pref_bootdisk = "boot_disk"; - public static final String pref_usereios = "use_reios"; - public static final String pref_customtextures = "custom_textures"; - public static final String pref_showfps = "show_fps"; - public static final String pref_RenderToTextureBuffer = "RenderToTextureBuffer"; - public static final String pref_RenderToTextureUpscale = "RenderToTextureUpscale"; - public static final String pref_TextureUpscale = "TextureUpscale"; - public static final String pref_MaxFilteredTextureSize= "MaxFilteredTextureSize"; - public static final String pref_MaxThreads = "MaxThreads"; - public static final String pref_controller_type = "controller_type"; - public static final String pref_peripheral_type = "peripheral_type"; // see MapleDeviceType in hw/maple/maple_devs.h public static final int MDT_SegaController = 0; public static final int MDT_SegaVMU = 1; @@ -56,34 +26,9 @@ public class Emulator extends Application { public static final int MDT_None = 8; public static final int MDT_Count = 9; - public static boolean dynarecopt = true; - public static boolean idleskip = true; - public static boolean unstableopt = false; - public static boolean dynsafemode = true; - public static int cable = 3; - public static int dcregion = 3; - public static int broadcast = 4; - public static int language = 6; - public static boolean limitfps = true; - public static boolean nobatch = false; public static boolean nosound = false; - public static boolean interrupt = false; - public static boolean mipmaps = true; - public static boolean widescreen = false; - public static int frameskip = 0; - public static int pvrrender = 0; - public static boolean syncedrender = true; - public static boolean modvols = true; - public static boolean clipping = true; - public static String bootdisk = null; - public static boolean usereios = false; - public static boolean customtextures = false; - public static boolean showfps = false; - public static boolean RenderToTextureBuffer = false; - public static int RenderToTextureUpscale = 1; - public static int TextureUpscale = 1; - public static int MaxFilteredTextureSize = 256; - public static int MaxThreads = 1; + public static int vibrationDuration = 20; + public static int maple_devices[] = { MDT_SegaController, MDT_None, @@ -98,91 +43,13 @@ public class Emulator extends Application { }; /** - * Load the user configuration from preferences + * Load the settings from native code * */ - public void getConfigurationPrefs(SharedPreferences mPrefs) { - Emulator.dynarecopt = mPrefs.getBoolean(pref_dynarecopt, dynarecopt); - Emulator.unstableopt = mPrefs.getBoolean(pref_unstable, unstableopt); - Emulator.dynsafemode = mPrefs.getBoolean(pref_dynsafemode, dynsafemode); - Emulator.idleskip = mPrefs.getBoolean(pref_idleskip, idleskip); - Emulator.cable = mPrefs.getInt(pref_cable, cable); - Emulator.dcregion = mPrefs.getInt(pref_dcregion, dcregion); - Emulator.broadcast = mPrefs.getInt(pref_broadcast, broadcast); - Emulator.language = mPrefs.getInt(pref_language, language); - Emulator.limitfps = mPrefs.getBoolean(pref_limitfps, limitfps); - Emulator.nosound = mPrefs.getBoolean(pref_nosound, nosound); - Emulator.nobatch = mPrefs.getBoolean(pref_nobatch, nobatch); - Emulator.mipmaps = mPrefs.getBoolean(pref_mipmaps, mipmaps); - Emulator.widescreen = mPrefs.getBoolean(pref_widescreen, widescreen); - Emulator.frameskip = mPrefs.getInt(pref_frameskip, frameskip); - Emulator.pvrrender = mPrefs.getInt(pref_pvrrender, pvrrender); - Emulator.syncedrender = mPrefs.getBoolean(pref_syncedrender, syncedrender); - Emulator.modvols = mPrefs.getBoolean(pref_modvols, modvols); - Emulator.clipping = mPrefs.getBoolean(pref_clipping, clipping); - Emulator.bootdisk = mPrefs.getString(pref_bootdisk, bootdisk); - Emulator.usereios = mPrefs.getBoolean(pref_usereios, usereios); - Emulator.customtextures = mPrefs.getBoolean(pref_customtextures, customtextures); - Emulator.showfps = mPrefs.getBoolean(pref_showfps, showfps); - Emulator.RenderToTextureBuffer = mPrefs.getBoolean(pref_RenderToTextureBuffer, RenderToTextureBuffer); - Emulator.RenderToTextureUpscale = mPrefs.getInt(pref_RenderToTextureUpscale, RenderToTextureUpscale); - Emulator.TextureUpscale = mPrefs.getInt(pref_TextureUpscale, TextureUpscale); - Emulator.MaxFilteredTextureSize = mPrefs.getInt(pref_MaxFilteredTextureSize, MaxFilteredTextureSize); - Emulator.MaxThreads = mPrefs.getInt(pref_MaxThreads, MaxThreads); - for (int i = 0; i < maple_devices.length; i++) { - maple_devices[i] = mPrefs.getInt(pref_controller_type + i, Emulator.maple_devices[i]); - maple_expansion_devices[i][0] = mPrefs.getInt(pref_peripheral_type + i + "0", Emulator.maple_expansion_devices[i][0]); - maple_expansion_devices[i][1] = mPrefs.getInt(pref_peripheral_type + i + "1", Emulator.maple_expansion_devices[i][1]); - } - } - - /** - * Write configuration settings to the emulator - * - */ - public void loadConfigurationPrefs() { - JNIdc.setDynarec(Emulator.dynarecopt); - JNIdc.setIdleskip(Emulator.idleskip); - JNIdc.setUnstable(Emulator.unstableopt); - JNIdc.setSafemode(Emulator.dynsafemode); - JNIdc.setCable(Emulator.cable); - JNIdc.setRegion(Emulator.dcregion); - JNIdc.setBroadcast(Emulator.broadcast); - JNIdc.setLanguage(Emulator.language); - JNIdc.setLimitfps(Emulator.limitfps); - JNIdc.setNobatch(Emulator.nobatch); - JNIdc.setNosound(Emulator.nosound); - JNIdc.setMipmaps(Emulator.mipmaps); - JNIdc.setWidescreen(Emulator.widescreen); - JNIdc.setFrameskip(Emulator.frameskip); - JNIdc.setPvrrender(Emulator.pvrrender); - JNIdc.setSyncedrender(Emulator.syncedrender); - JNIdc.setModvols(Emulator.modvols); - JNIdc.setClipping(Emulator.clipping); - JNIdc.setUsereios(Emulator.usereios); - JNIdc.bootdisk(Emulator.bootdisk); - JNIdc.setCustomtextures(Emulator.customtextures); - JNIdc.setShowfps(Emulator.showfps); - JNIdc.setRenderToTextureBuffer(Emulator.RenderToTextureBuffer); - JNIdc.setRenderToTextureUpscale(Emulator.RenderToTextureUpscale); - JNIdc.setTextureUpscale(Emulator.TextureUpscale); - JNIdc.setMaxFilteredTextureSize(Emulator.MaxFilteredTextureSize); - JNIdc.setMaxThreads(Emulator.MaxThreads); - JNIdc.initControllers(maple_devices, maple_expansion_devices); - } - - public void loadGameConfiguration(String gameId) { - SharedPreferences mPrefs = getSharedPreferences(gameId, Activity.MODE_PRIVATE); - JNIdc.setDynarec(mPrefs.getBoolean(pref_dynarecopt, dynarecopt)); - JNIdc.setUnstable(mPrefs.getBoolean(pref_unstable, unstableopt)); - JNIdc.setSafemode(mPrefs.getBoolean(pref_dynsafemode, dynsafemode)); - JNIdc.setFrameskip(mPrefs.getInt(pref_frameskip, frameskip)); - JNIdc.setPvrrender(mPrefs.getInt(pref_pvrrender, pvrrender)); - JNIdc.setSyncedrender(mPrefs.getBoolean(pref_syncedrender, syncedrender)); - JNIdc.setModvols(mPrefs.getBoolean(pref_modvols, modvols)); - JNIdc.setClipping(mPrefs.getBoolean(pref_clipping, clipping)); - JNIdc.bootdisk(mPrefs.getString(pref_bootdisk, bootdisk)); - JNIdc.setCustomtextures(mPrefs.getBoolean(pref_customtextures, customtextures)); + public void getConfigurationPrefs() { + Emulator.nosound = JNIdc.getNosound(); + Emulator.vibrationDuration = JNIdc.getVirtualGamepadVibration(); + JNIdc.getControllers(maple_devices, maple_expansion_devices); } /** @@ -191,75 +58,19 @@ public class Emulator extends Application { */ public void SaveAndroidSettings(String homeDirectory) { - Log.i("Emulator", "SaveAndroidSettings: saving preferences"); + Log.i("reicast", "SaveAndroidSettings: saving preferences"); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - - Emulator.dynarecopt = JNIdc.getDynarec(); - Emulator.idleskip = JNIdc.getIdleskip(); - Emulator.unstableopt = JNIdc.getUnstable(); - Emulator.dynsafemode = JNIdc.getSafemode(); - Emulator.cable = JNIdc.getCable(); - Emulator.dcregion = JNIdc.getRegion(); - Emulator.broadcast = JNIdc.getBroadcast(); - Emulator.language = JNIdc.getLanguage(); - Emulator.limitfps = JNIdc.getLimitfps(); - Emulator.nobatch = JNIdc.getNobatch(); Emulator.nosound = JNIdc.getNosound(); - Emulator.mipmaps = JNIdc.getMipmaps(); - Emulator.widescreen = JNIdc.getWidescreen(); - Emulator.frameskip = JNIdc.getFrameskip(); - Emulator.pvrrender = JNIdc.getPvrrender(); - Emulator.syncedrender = JNIdc.getSyncedrender(); - Emulator.modvols = JNIdc.getModvols(); - Emulator.clipping = JNIdc.getClipping(); - Emulator.usereios = JNIdc.getUsereios(); - //Emulator.bootdisk = JNIdc.getBootdisk(); - Emulator.customtextures = JNIdc.getCustomtextures(); - Emulator.showfps = JNIdc.getShowfps(); - Emulator.RenderToTextureBuffer = JNIdc.getRenderToTextureBuffer(); - Emulator.RenderToTextureUpscale = JNIdc.getRenderToTextureUpscale(); - Emulator.TextureUpscale = JNIdc.getTextureUpscale(); - Emulator.MaxFilteredTextureSize = JNIdc.getMaxFilteredTextureSize(); - Emulator.MaxThreads = JNIdc.getMaxThreads(); + Emulator.vibrationDuration = JNIdc.getVirtualGamepadVibration(); JNIdc.getControllers(maple_devices, maple_expansion_devices); - SharedPreferences.Editor editor = prefs.edit() - .putString(Config.pref_home, homeDirectory) - .putBoolean(Emulator.pref_dynarecopt, Emulator.dynarecopt) - .putBoolean(Emulator.pref_idleskip, Emulator.idleskip) - .putBoolean(Emulator.pref_unstable, Emulator.unstableopt) - .putBoolean(Emulator.pref_dynsafemode, Emulator.dynsafemode) - .putInt(Emulator.pref_cable, Emulator.cable) - .putInt(Emulator.pref_dcregion, Emulator.dcregion) - .putInt(Emulator.pref_broadcast, Emulator.broadcast) - .putInt(Emulator.pref_language, Emulator.language) - .putBoolean(Emulator.pref_limitfps, Emulator.limitfps) - .putBoolean(Emulator.pref_nobatch, Emulator.nobatch) - .putBoolean(Emulator.pref_nosound, Emulator.nosound) - .putBoolean(Emulator.pref_mipmaps, Emulator.mipmaps) - .putBoolean(Emulator.pref_widescreen, Emulator.widescreen) - .putInt(Emulator.pref_frameskip, Emulator.frameskip) - .putInt(Emulator.pref_pvrrender, Emulator.pvrrender) - .putBoolean(Emulator.pref_syncedrender, Emulator.syncedrender) - .putBoolean(Emulator.pref_modvols, Emulator.modvols) - .putBoolean(Emulator.pref_clipping, Emulator.clipping) - .putBoolean(Emulator.pref_usereios, Emulator.usereios) - .putBoolean(Emulator.pref_customtextures, Emulator.customtextures) - .putBoolean(Emulator.pref_showfps, Emulator.showfps) - .putBoolean(Emulator.pref_RenderToTextureBuffer, Emulator.RenderToTextureBuffer) - .putInt(Emulator.pref_RenderToTextureUpscale, Emulator.RenderToTextureUpscale) - .putInt(Emulator.pref_TextureUpscale, Emulator.TextureUpscale) - .putInt(Emulator.pref_MaxFilteredTextureSize, Emulator.MaxFilteredTextureSize) - .putInt(Emulator.pref_MaxThreads, Emulator.MaxThreads); - for (int i = 0; i < maple_devices.length; i++) { - editor.putInt(pref_controller_type + i, Emulator.maple_devices[i]); - editor.putInt(pref_peripheral_type + i + "0", Emulator.maple_expansion_devices[i][0]); - editor.putInt(pref_peripheral_type + i + "1", Emulator.maple_expansion_devices[i][1]); - } - editor.apply(); + prefs.edit() + .putString(Config.pref_home, homeDirectory).apply(); + AudioBackend.getInstance().enableSound(!Emulator.nosound); } public static boolean micPluggedIn() { + JNIdc.getControllers(maple_devices, maple_expansion_devices); for (int i = 0; i < maple_expansion_devices.length; i++) if (maple_expansion_devices[i][0] == MDT_Microphone || maple_expansion_devices[i][1] == MDT_Microphone) diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/GL2JNIActivity.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/GL2JNIActivity.java index c51de8d47..4a5095251 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/GL2JNIActivity.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/GL2JNIActivity.java @@ -26,7 +26,6 @@ import com.reicast.emulator.config.Config; import com.reicast.emulator.emu.GL2JNIView; import com.reicast.emulator.emu.JNIdc; import com.reicast.emulator.emu.OnScreenMenu; -import com.reicast.emulator.emu.OnScreenMenu.FpsPopup; import com.reicast.emulator.periph.Gamepad; import com.reicast.emulator.periph.InputDeviceManager; import com.reicast.emulator.periph.SipEmulator; @@ -37,8 +36,6 @@ import tv.ouya.console.api.OuyaController; public class GL2JNIActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback { public GL2JNIView mView; - OnScreenMenu menu; - FpsPopup fpsPop; private SharedPreferences prefs; private Gamepad pad = new Gamepad(); @@ -57,8 +54,7 @@ public class GL2JNIActivity extends Activity implements ActivityCompat.OnRequest InputDeviceManager.getInstance().startListening(getApplicationContext()); Emulator app = (Emulator)getApplicationContext(); - app.getConfigurationPrefs(prefs); - menu = new OnScreenMenu(GL2JNIActivity.this, prefs); + app.getConfigurationPrefs(); pad.isOuyaOrTV = pad.IsOuyaOrTV(GL2JNIActivity.this, false); @@ -89,7 +85,7 @@ public class GL2JNIActivity extends Activity implements ActivityCompat.OnRequest prefs.getString(Gamepad.pref_player4, null), 3); pad.deviceDescriptor_PlayerNum.remove(null); - JNIdc.initControllers(Emulator.maple_devices, Emulator.maple_expansion_devices); + // JNIdc.initControllers(Emulator.maple_devices, Emulator.maple_expansion_devices); int joys[] = InputDevice.getDeviceIds(); for (int joy: joys) { @@ -153,21 +149,10 @@ public class GL2JNIActivity extends Activity implements ActivityCompat.OnRequest pad.fullCompatibilityMode(prefs); } - app.loadConfigurationPrefs(); - - // When viewing a resource, pass its URI to the native code for opening - if (getIntent().getAction().equals("com.reicast.EMULATOR")) - fileName = Uri.decode(getIntent().getData().toString()); - - try { // Create the actual GLES view - mView = new GL2JNIView(GL2JNIActivity.this, fileName, false, + mView = new GL2JNIView(GL2JNIActivity.this, false, prefs.getInt(Config.pref_renderdepth, 24), 8, false); - setContentView(mView); - } catch (GL2JNIView.EmulatorInitFailed e) { - finish(); - return; - } + setContentView(mView); //setup mic if (Emulator.micPluggedIn()) { @@ -183,27 +168,12 @@ public class GL2JNIActivity extends Activity implements ActivityCompat.OnRequest onRequestPermissionsResult(0, new String[] { Manifest.permission.RECORD_AUDIO }, new int[] { PackageManager.PERMISSION_GRANTED }); } } - - if (Emulator.showfps) { - fpsPop = menu.new FpsPopup(this); - mView.setFpsDisplay(fpsPop); - mView.post(new Runnable() { - public void run() { - displayFPS(); - } - }); - } } public Gamepad getPad() { return pad; } - public void displayFPS() { - fpsPop.showAtLocation(mView, Gravity.TOP | Gravity.LEFT, 20, 20); - fpsPop.update(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - } - public void screenGrab() { mView.screenGrab(); } @@ -313,7 +283,6 @@ public class GL2JNIActivity extends Activity implements ActivityCompat.OnRequest InputDeviceManager.getInstance().stopListening(); if (mView != null) { mView.onDestroy(); - // FIXME This should be called to deinit what's been inited... JNIdc.destroy(); } } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/MainActivity.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/MainActivity.java index 10ba26f17..06c2eccc1 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/MainActivity.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/MainActivity.java @@ -2,56 +2,34 @@ package com.reicast.emulator; import android.Manifest; import android.app.AlertDialog; -import android.app.UiModeManager; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.res.Configuration; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Environment; import android.preference.PreferenceManager; import android.support.annotation.NonNull; -import android.support.constraint.ConstraintLayout; -import android.support.design.widget.NavigationView; -import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; -import android.support.v4.app.Fragment; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.SearchView; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.MenuItem; import android.view.View; import android.view.View.OnSystemUiVisibilityChangeListener; import android.view.WindowManager; -import android.widget.TextView; -import com.reicast.emulator.config.Config; -import com.reicast.emulator.config.EditVJoyActivity; -import com.reicast.emulator.config.InputFragment; -import com.reicast.emulator.config.OptionsFragment; import com.reicast.emulator.debug.GenerateLogs; import com.reicast.emulator.emu.JNIdc; import java.lang.Thread.UncaughtExceptionHandler; import java.util.List; -public class MainActivity extends AppCompatActivity implements - NavigationView.OnNavigationItemSelectedListener, FileBrowser.OnItemSelectedListener, - OptionsFragment.OnClickListener, InputFragment.OnClickListener { +public class MainActivity extends AppCompatActivity { private static final int PERMISSION_REQUEST = 1001; - private SharedPreferences mPrefs; private boolean hasAndroidMarket = false; - private boolean activity_paused = false; + private boolean renderer_started = false; + private Uri gameUri; @Override public void onCreate(Bundle savedInstanceState) { @@ -76,39 +54,29 @@ public class MainActivity extends AppCompatActivity implements WindowManager.LayoutParams.FLAG_FULLSCREEN); } - mPrefs = PreferenceManager.getDefaultSharedPreferences(this); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - String prior_error = mPrefs.getString("prior_error", null); + String prior_error = prefs.getString("prior_error", null); if (prior_error != null) { displayLogOutput(prior_error); - mPrefs.edit().remove("prior_error").apply(); - } else { - UncaughtExceptionHandler mUEHandler = new Thread.UncaughtExceptionHandler() { - public void uncaughtException(Thread t, Throwable error) { - if (error != null) { - StringBuilder output = new StringBuilder(); - for (StackTraceElement trace : error.getStackTrace()) { - output.append(trace.toString()); - output.append("\n"); - } - mPrefs.edit().putString("prior_error", output.toString()).apply(); - error.printStackTrace(); - android.os.Process.killProcess(android.os.Process.myPid()); - System.exit(0); + prefs.edit().remove("prior_error").apply(); + } + UncaughtExceptionHandler mUEHandler = new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable error) { + if (error != null) { + StringBuilder output = new StringBuilder(); + for (StackTraceElement trace : error.getStackTrace()) { + output.append(trace.toString()); + output.append("\n"); } + prefs.edit().putString("prior_error", output.toString()).apply(); + error.printStackTrace(); + android.os.Process.killProcess(android.os.Process.myPid()); + System.exit(0); } - }; - Thread.setDefaultUncaughtExceptionHandler(mUEHandler); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - ActivityCompat.requestPermissions(MainActivity.this, - new String[] { - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - }, - PERMISSION_REQUEST); - } + } + }; + Thread.setDefaultUncaughtExceptionHandler(mUEHandler); Intent market = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=dummy")); if (isCallable(market)) { @@ -118,85 +86,28 @@ public class MainActivity extends AppCompatActivity implements if (!getFilesDir().exists()) { getFilesDir().mkdir(); } - String home_directory = mPrefs.getString(Config.pref_home, ""); - String result = JNIdc.initEnvironment((Emulator)getApplicationContext(), home_directory); - if (result != null) - showToastMessage("Initialization failed: " + result, - Snackbar.LENGTH_LONG); - - String android_home_directory = Environment.getExternalStorageDirectory().getAbsolutePath(); - JNIdc.config(android_home_directory); // When viewing a resource, pass its URI to the native code for opening Intent intent = getIntent(); if (intent.getAction() != null) { if (intent.getAction().equals(Intent.ACTION_VIEW)) { - onGameSelected(Uri.parse(intent.getData().toString())); + gameUri = Uri.parse(intent.getData().toString()); // Flush the intent to prevent multiple calls getIntent().setData(null); setIntent(null); - Config.externalIntent = true; } } - // Check that the activity is using the layout version with - // the fragment_container FrameLayout - if (findViewById(R.id.fragment_container) != null) { - onMainBrowseSelected(null, true, null); - } - - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); - android.support.v7.app.ActionBarDrawerToggle toggle = new android.support.v7.app.ActionBarDrawerToggle( - this, drawer, toolbar, R.string.drawer_open, R.string.drawer_shut) { - @Override - public void onDrawerOpened(View drawerView) { - - } - @Override - public void onDrawerClosed(View drawerView) { - - } - }; - //noinspection deprecation - drawer.setDrawerListener(toggle); - toggle.syncState(); - - NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); - if (!hasAndroidMarket) { - navigationView.getMenu().findItem(R.id.rateme_menu).setEnabled(false); - navigationView.getMenu().findItem(R.id.rateme_menu).setVisible(false); - } - try { - UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE); - if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) { - View header = navigationView.getHeaderView(0); - ((TextView) header.findViewById(R.id.project_link)).setVisibility(View.GONE); - } - } catch (Exception e) { - // They require a check, so they can fix their API - } - navigationView.setNavigationItemSelectedListener(this); - - final SearchView searchView = (SearchView) findViewById(R.id.searchView); - if (searchView != null) { - searchView.setQueryHint(getString(R.string.search_hint)); - searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - onMainBrowseSelected(mPrefs.getString(Config.pref_games, - Environment.getExternalStorageDirectory().getAbsolutePath()), - true, query); - searchView.onActionViewCollapsed(); - return false; - } - @Override - public boolean onQueryTextChange(String s) { - return false; - } - }); + if (prior_error == null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + ActivityCompat.requestPermissions(MainActivity.this, + new String[]{ + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + }, + PERMISSION_REQUEST); + } else + startNativeRenderer(); } } @@ -218,308 +129,41 @@ public class MainActivity extends AppCompatActivity implements new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { generateErrorLog(); + startNativeRenderer(); } }); builder.setNegativeButton(R.string.dismiss, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); + startNativeRenderer(); } }); builder.create(); builder.show(); } - public void onEditorSelected(Uri uri) { - if (activity_paused) + private void startNativeRenderer() { + if (renderer_started) return; - activity_paused = true; - String home_directory = mPrefs.getString(Config.pref_home, - Environment.getExternalStorageDirectory().getAbsolutePath()); + renderer_started = true; - //JNIdc.config(home_directory); - - startActivity(new Intent("com.reicast.EMULATOR", uri, - getApplicationContext(), EditVJoyActivity.class)); - } - - public void onGameSelected(Uri uri) { - if (activity_paused) - return; - activity_paused = true; - String home_directory = mPrefs.getString(Config.pref_home, - Environment.getExternalStorageDirectory().getAbsolutePath()); - - //JNIdc.config(home_directory); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - uri = Uri.parse(uri.toString().replace("content://" - + uri.getAuthority() + "/external_files", "/storage")); + if (gameUri != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + gameUri = Uri.parse(gameUri.toString().replace("content://" + + gameUri.getAuthority() + "/external_files", "/storage")); } + if (gameUri != null) + JNIdc.setGameUri(gameUri.toString()); Intent intent = new Intent("com.reicast.EMULATOR", // uri, getApplicationContext(), GL2JNIActivity.class); - uri, getApplicationContext(), NativeGLActivity.class); + gameUri, getApplicationContext(), NativeGLActivity.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); startActivity(intent); } - public void onFolderSelected(Uri uri) { - FileBrowser browserFrag = (FileBrowser) getSupportFragmentManager() - .findFragmentByTag("MAIN_BROWSER"); - if (browserFrag != null) { - if (browserFrag.isVisible()) { - Log.d("reicast", "Main folder: " + uri.toString()); - // return; - } - } - - OptionsFragment optsFrag = new OptionsFragment(); - getSupportFragmentManager().beginTransaction().replace( - R.id.fragment_container, optsFrag, "OPTIONS_FRAG").commit(); - setTitle(R.string.settings); - } - - /** - * Launch the browser activity with specified parameters - * - * @param path - * The root path of the browser fragment - * @param games - * Conditional for viewing games or BIOS - * @param query - * Search parameters to limit list items - */ - public void onMainBrowseSelected(String path, boolean games, String query) { - FileBrowser firstFragment = new FileBrowser(); - Bundle args = new Bundle(); - args.putString("browse_entry", path); - // specify a path for selecting folder options - args.putBoolean("games_entry", games); - // specify if the desired path is for games or data - args.putString("search_params", query); - - firstFragment.setArguments(args); - // In case this activity was started with special instructions from - // an Intent, pass the Intent's extras to the fragment as arguments - // firstFragment.setArguments(getIntent().getExtras()); - - // Add the fragment to the 'fragment_container' FrameLayout - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, firstFragment, "MAIN_BROWSER") - .addToBackStack(null).commit(); - setTitle(R.string.browser); - } - - public void launchBIOSdetection() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.bios_selection); - builder.setPositiveButton(R.string.browse, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String home_directory = mPrefs.getString(Config.pref_home, - Environment.getExternalStorageDirectory().getAbsolutePath()); - onMainBrowseSelected(home_directory, false, null); - } - }); - builder.setNegativeButton(R.string.gdrive, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - showToastMessage(getString(R.string.require_bios), - Snackbar.LENGTH_SHORT); - } - }); - builder.create(); - builder.show(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - Fragment fragment = getSupportFragmentManager().findFragmentByTag("MAIN_BROWSER"); - if (fragment != null && fragment.isVisible()) { - boolean readyToQuit = true; - if (fragment.getArguments() != null) { - readyToQuit = fragment.getArguments().getBoolean( - "games_entry", true); - } - if (readyToQuit) { - MainActivity.this.finish(); - } else { - launchMainFragment(); - } - return true; - } else { - launchMainFragment(); - return true; - } - - } - - return super.onKeyDown(keyCode, event); - } - - private void launchMainFragment() { - onMainBrowseSelected(null, true, null); - } - - @Override - protected void onPause() { - super.onPause(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - } - - @Override - protected void onResume() { - super.onResume(); - activity_paused = false; - - CloudFragment cloudfragment = (CloudFragment) getSupportFragmentManager() - .findFragmentByTag("CLOUD_FRAG"); - if (cloudfragment != null && cloudfragment.isVisible()) { - cloudfragment.onResume(); - } - } - - @Override - public void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - } - - @Override - public boolean onNavigationItemSelected(@NonNull MenuItem item) { - // Handle navigation view item clicks here. - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); - - switch (item.getItemId()) { - - case R.id.browser_menu: - FileBrowser browseFrag = (FileBrowser) getSupportFragmentManager() - .findFragmentByTag("MAIN_BROWSER"); - if (browseFrag != null) { - if (browseFrag.isVisible()) { - drawer.closeDrawer(GravityCompat.START); - return true; - } - } - browseFrag = new FileBrowser(); - Bundle args = new Bundle(); - args.putString("browse_entry", null); - // specify a path for selecting folder options - args.putBoolean("games_entry", true); - // specify if the desired path is for games or data - browseFrag.setArguments(args); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, browseFrag, "MAIN_BROWSER") - .addToBackStack(null).commit(); - setTitle(R.string.browser); - drawer.closeDrawer(GravityCompat.START); - return true; - - case R.id.settings_menu: - OptionsFragment optionsFrag = (OptionsFragment) getSupportFragmentManager() - .findFragmentByTag("OPTIONS_FRAG"); - if (optionsFrag != null) { - if (optionsFrag.isVisible()) { - drawer.closeDrawer(GravityCompat.START); - return true; - } - } - optionsFrag = new OptionsFragment(); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, optionsFrag, "OPTIONS_FRAG") - .addToBackStack(null).commit(); - setTitle(R.string.settings); - drawer.closeDrawer(GravityCompat.START); - return true; - - case R.id.input_menu: - InputFragment inputFrag = (InputFragment) getSupportFragmentManager() - .findFragmentByTag("INPUT_FRAG"); - if (inputFrag != null) { - if (inputFrag.isVisible()) { - drawer.closeDrawer(GravityCompat.START); - return true; - } - } - inputFrag = new InputFragment(); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, inputFrag, "INPUT_FRAG") - .addToBackStack(null).commit(); - setTitle(R.string.input); - drawer.closeDrawer(GravityCompat.START); - return true; - - case R.id.about_menu: - AboutFragment aboutFrag = (AboutFragment) getSupportFragmentManager() - .findFragmentByTag("ABOUT_FRAG"); - if (aboutFrag != null) { - if (aboutFrag.isVisible()) { - drawer.closeDrawer(GravityCompat.START); - return true; - } - } - aboutFrag = new AboutFragment(); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, aboutFrag, "ABOUT_FRAG") - .addToBackStack(null).commit(); - setTitle(R.string.about); - drawer.closeDrawer(GravityCompat.START); - return true; - - case R.id.cloud_menu: - CloudFragment cloudFrag = (CloudFragment) getSupportFragmentManager() - .findFragmentByTag("CLOUD_FRAG"); - if (cloudFrag != null) { - if (cloudFrag.isVisible()) { - drawer.closeDrawer(GravityCompat.START); - return true; - } - } - cloudFrag = new CloudFragment(); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.fragment_container, cloudFrag, "CLOUD_FRAG") - .addToBackStack(null).commit(); - setTitle(R.string.cloud); - drawer.closeDrawer(GravityCompat.START); - return true; - - case R.id.rateme_menu: - // vib.vibrate(50); - startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("market://details?id=" + getPackageName()))); - //setTitle(R.string.rateme); - drawer.closeDrawer(GravityCompat.START); - return true; - - case R.id.message_menu: - generateErrorLog(); - drawer.closeDrawer(GravityCompat.START); - return true; - - default: - drawer.closeDrawer(GravityCompat.START); - return true; - - } - } - @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); @@ -533,33 +177,18 @@ public class MainActivity extends AppCompatActivity implements } } - public boolean isCallable(Intent intent) { + private boolean isCallable(Intent intent) { List list = getPackageManager().queryIntentActivities( intent, PackageManager.MATCH_DEFAULT_ONLY); return list.size() > 0; } - private void showToastMessage(String message, int duration) { - ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.mainui_layout); - Snackbar snackbar = Snackbar.make(layout, message, duration); - View snackbarLayout = snackbar.getView(); - TextView textView = (TextView) snackbarLayout.findViewById( - android.support.design.R.id.snackbar_text); - textView.setGravity(Gravity.CENTER_VERTICAL); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) - textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY); - textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_notification, 0, 0, 0); - textView.setCompoundDrawablePadding(getResources() - .getDimensionPixelOffset(R.dimen.snackbar_icon_padding)); - snackbar.show(); - } - @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (permissions.length > 0 && (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permissions[0]) || Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0])) && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - onGameSelected(Uri.parse("file://whatever")); + startNativeRenderer(); } } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java index d36a95c1e..05128d87f 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/NativeGLActivity.java @@ -1,50 +1,77 @@ package com.reicast.emulator; import android.Manifest; -import android.app.Activity; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.constraint.ConstraintLayout; +import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.util.Log; +import android.view.Gravity; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.SurfaceHolder; +import android.view.View; import android.view.ViewConfiguration; import android.view.Window; +import android.widget.FrameLayout; +import android.widget.TextView; +import com.reicast.emulator.config.Config; +import com.reicast.emulator.debug.GenerateLogs; +import com.reicast.emulator.emu.AudioBackend; import com.reicast.emulator.emu.JNIdc; -import com.reicast.emulator.emu.NativeGLView; import com.reicast.emulator.periph.InputDeviceManager; import com.reicast.emulator.periph.SipEmulator; +import com.reicast.emulator.periph.VJoy; + +import java.util.ArrayList; +import java.util.List; import tv.ouya.console.api.OuyaController; -public class NativeGLActivity extends BaseNativeGLActivity implements ActivityCompat.OnRequestPermissionsResultCallback { +public final class NativeGLActivity extends BaseNativeGLActivity implements ActivityCompat.OnRequestPermissionsResultCallback { public static byte[] syms; + private float[][] vjoy_d_cached; // Used for VJoy editing + private AudioBackend audioBackend; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); InputDeviceManager.getInstance().startListening(getApplicationContext()); Emulator app = (Emulator)getApplicationContext(); - app.getConfigurationPrefs(prefs); + app.getConfigurationPrefs(); OuyaController.init(this); - JNIdc.initControllers(Emulator.maple_devices, Emulator.maple_expansion_devices); - - app.loadConfigurationPrefs(); super.onCreate(savedInstanceState); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + String home_directory = prefs.getString(Config.pref_home, ""); + String result = JNIdc.initEnvironment((Emulator)getApplicationContext(), home_directory); + if (result != null) + showToastMessage("Initialization failed: " + result, Snackbar.LENGTH_LONG); + + String android_home_directory = Environment.getExternalStorageDirectory().getAbsolutePath(); + List pathList = new ArrayList<>(); + pathList.add(android_home_directory); + pathList.addAll(FileBrowser.getExternalMounts()); + Log.i("reicast", "External storage dirs: " + pathList); + JNIdc.setExternalStorageDirectories(pathList.toArray()); + + register(this); + + audioBackend = new AudioBackend(); + + // FIXME Maple microphone can be plugged at any time with in-game gui + // so this perm may be required at any time as well //setup mic if (Emulator.micPluggedIn()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -124,6 +151,8 @@ public class NativeGLActivity extends BaseNativeGLActivity implements ActivityCo protected void onDestroy() { super.onDestroy(); InputDeviceManager.getInstance().stopListening(); + register(null); + audioBackend.release(); } @Override @@ -135,4 +164,46 @@ public class NativeGLActivity extends BaseNativeGLActivity implements ActivityCo JNIdc.setupMic(sip); } } + + private void showToastMessage(String message, int duration) { + View view = findViewById(android.R.id.content); + Snackbar snackbar = Snackbar.make(view, message, duration); + View snackbarLayout = snackbar.getView(); + TextView textView = (TextView) snackbarLayout.findViewById( + android.support.design.R.id.snackbar_text); + textView.setGravity(Gravity.CENTER_VERTICAL); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) + textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY); + textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_notification, 0, 0, 0); + textView.setCompoundDrawablePadding(getResources() + .getDimensionPixelOffset(R.dimen.snackbar_icon_padding)); + snackbar.show(); + } + + // Called from native code + private void VJoyStartEditing() { + vjoy_d_cached = VJoy.readCustomVjoyValues(getApplicationContext()); + JNIdc.show_osd(); + mView.setEditVjoyMode(true); + } + // Called from native code + private void VJoyResetEditing() { + VJoy.resetCustomVjoyValues(getApplicationContext()); + mView.vjoy_d_custom = VJoy + .readCustomVjoyValues(getApplicationContext()); + mView.resetEditMode(); + mView.requestLayout(); + } + // Called from native code + private void VJoyStopEditing(boolean canceled) { + if (canceled) + mView.restoreCustomVjoyValues(vjoy_d_cached); + mView.setEditVjoyMode(false); + } + // Called from native code + private void generateErrorLog() { + new GenerateLogs(this).execute(getFilesDir().getAbsolutePath()); + } + + private static native void register(NativeGLActivity activity); } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/Config.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/Config.java index b3eebd745..57ba6249d 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/Config.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/Config.java @@ -1,9 +1,5 @@ package com.reicast.emulator.config; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; - public class Config { public static final String pref_home = "home_directory"; @@ -15,42 +11,5 @@ public class Config { public static final String pref_rendertype = "render_type"; public static final String pref_renderdepth = "depth_render"; - public static final String pref_touchvibe = "touch_vibration_enabled"; - public static final String pref_vibrationDuration = "vibration_duration"; - - public static final String game_title = "game_title"; - - public static int vibrationDuration = 20; - - public static final String pref_vmu = "vmu_floating"; - - public static String git_api = "https://api.github.com/repos/reicast/reicast-emulator/commits?sha=fh/mymaster"; public static String git_issues = "https://github.com/reicast/reicast-emulator/issues/"; - - public static boolean externalIntent = false; - - /** - * Read the output of a shell command - * - * @param command - * The shell command being issued to the terminal - */ - public static String readOutput(String command) { - try { - Process p = Runtime.getRuntime().exec(command); - InputStream is; - if (p.waitFor() == 0) { - is = p.getInputStream(); - } else { - is = p.getErrorStream(); - } - BufferedReader br = new BufferedReader(new InputStreamReader(is),2048); - String line = br.readLine(); - br.close(); - return line; - } catch (Exception ex) { - return "ERROR: " + ex.getMessage(); - } - } - } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/EditVJoyActivity.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/EditVJoyActivity.java deleted file mode 100644 index 906970e0d..000000000 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/EditVJoyActivity.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.reicast.emulator.config; - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.SurfaceHolder; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.view.Window; -import android.widget.ImageButton; -import android.widget.ImageView.ScaleType; -import android.widget.LinearLayout; -import android.widget.PopupWindow; - -import com.reicast.emulator.BaseNativeGLActivity; -import com.reicast.emulator.MainActivity; -import com.reicast.emulator.R; -import com.reicast.emulator.emu.JNIdc; -import com.reicast.emulator.emu.NativeGLView; -import com.reicast.emulator.emu.OnScreenMenu; -import com.reicast.emulator.periph.VJoy; - -public class EditVJoyActivity extends BaseNativeGLActivity { - PopupWindow popUp; - LayoutParams params; - - private float[][] vjoy_d_cached; - - View addbut(int x, OnClickListener ocl) { - ImageButton but = new ImageButton(this); - - but.setImageResource(x); - but.setScaleType(ScaleType.FIT_CENTER); - but.setOnClickListener(ocl); - - return but; - } - - @Override - protected void onCreate(Bundle icicle) { - requestWindowFeature(Window.FEATURE_NO_TITLE); - - popUp = createVJoyPopup(); - - String fileName = null; - - editVjoyMode = true; - // Call parent onCreate() - super.onCreate(icicle); - - vjoy_d_cached = VJoy.readCustomVjoyValues(getApplicationContext()); - - JNIdc.show_osd(); - } - - PopupWindow createVJoyPopup() { - final PopupWindow popUp = new PopupWindow(this); - int p = OnScreenMenu.getPixelsFromDp(60, this); - params = new LayoutParams(p, p); - - LinearLayout hlay = new LinearLayout(this); - - hlay.setOrientation(LinearLayout.HORIZONTAL); - - hlay.addView(addbut(R.drawable.apply, new OnClickListener() { - public void onClick(View v) { - stopEmulator(); - Intent inte = new Intent(EditVJoyActivity.this, MainActivity.class); - startActivity(inte); - finish(); - } - }), params); - - hlay.addView(addbut(R.drawable.reset, new OnClickListener() { - public void onClick(View v) { - // Reset VJoy positions and scale - VJoy.resetCustomVjoyValues(getApplicationContext()); - mView.vjoy_d_custom = VJoy - .readCustomVjoyValues(getApplicationContext()); - mView.resetEditMode(); - mView.requestLayout(); - popUp.dismiss(); - } - }), params); - - hlay.addView(addbut(R.drawable.close, new OnClickListener() { - public void onClick(View v) { - mView.restoreCustomVjoyValues(vjoy_d_cached); - popUp.dismiss(); - } - }), params); - - popUp.setContentView(hlay); - return popUp; - } - - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_MENU - || keyCode == KeyEvent.KEYCODE_BACK) { - if (!popUp.isShowing()) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - popUp.showAtLocation(mView, Gravity.BOTTOM, 0, 60); - } else { - popUp.showAtLocation(mView, Gravity.BOTTOM, 0, 0); - } - popUp.update(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - } else { - popUp.dismiss(); - } - - return true; - } else - return super.onKeyDown(keyCode, event); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - } -} diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/InputFragment.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/InputFragment.java deleted file mode 100644 index a4fdc362f..000000000 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/InputFragment.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.reicast.emulator.config; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Bundle; -import android.os.Environment; -import android.os.Vibrator; -import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.LinearLayout; -import android.widget.SeekBar; -import android.widget.TextView; - -import com.reicast.emulator.Emulator; -import com.reicast.emulator.R; - -import java.io.File; - -public class InputFragment extends Fragment { - private OnClickListener mCallback; - - private SharedPreferences mPrefs; - private CompoundButton switchTouchVibrationEnabled; - - Vibrator vib; - - // Container Activity must implement this interface - public interface OnClickListener { - void onEditorSelected(Uri uri); - } - - @Override @SuppressWarnings("deprecation") - public void onAttach(Activity activity) { - super.onAttach(activity); - - // This makes sure that the container activity has implemented - // the callback interface. If not, it throws an exception - try { - mCallback = (OnClickListener) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement OnClickListener"); - } - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - - // This makes sure that the container activity has implemented - // the callback interface. If not, it throws an exception - try { - mCallback = (OnClickListener) context; - } catch (ClassCastException e) { - throw new ClassCastException(context.getClass().toString() - + " must implement OnClickListener"); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.input_fragment, container, false); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); - - Config.vibrationDuration = mPrefs.getInt(Config.pref_vibrationDuration, 20); - vib = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE); - - final Button buttonLaunchEditor = (Button) getView().findViewById(R.id.buttonLaunchEditor); - buttonLaunchEditor.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - buttonLaunchEditor.setEnabled(false); - mCallback.onEditorSelected(Uri.EMPTY); - } - }); - - buttonLaunchEditor.setEnabled(isBIOSAvailable()); - - final TextView duration = (TextView) getView().findViewById(R.id.vibDuration_current); - final LinearLayout vibLay = (LinearLayout) getView().findViewById(R.id.vibDuration_layout); - final SeekBar vibSeek = (SeekBar) getView().findViewById(R.id.vib_seekBar); - - if (mPrefs.getBoolean(Config.pref_touchvibe, true)) { - vibLay.setVisibility(View.VISIBLE); - } else { - vibLay.setVisibility(View.GONE); - } - - duration.setText(String.valueOf(Config.vibrationDuration + " ms")); - vibSeek.setProgress(Config.vibrationDuration); - - vibSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - duration.setText(String.valueOf(progress + 5 + " ms")); - } - - public void onStartTrackingTouch(SeekBar seekBar) { - - } - - public void onStopTrackingTouch(SeekBar seekBar) { - int progress = seekBar.getProgress() + 5; - mPrefs.edit().putInt(Config.pref_vibrationDuration, progress).apply(); - Config.vibrationDuration = progress; - vib.vibrate(progress); - } - }); - - OnCheckedChangeListener touch_vibration = new OnCheckedChangeListener() { - public void onCheckedChanged(CompoundButton buttonView, - boolean isChecked) { - mPrefs.edit().putBoolean(Config.pref_touchvibe, isChecked).apply(); - vibLay.setVisibility( isChecked ? View.VISIBLE : View.GONE ); - } - }; - switchTouchVibrationEnabled = (CompoundButton) getView().findViewById( - R.id.switchTouchVibrationEnabled); - boolean vibrate = mPrefs.getBoolean(Config.pref_touchvibe, true); - if (vibrate) { - switchTouchVibrationEnabled.setChecked(true); - } else { - switchTouchVibrationEnabled.setChecked(false); - } - switchTouchVibrationEnabled.setOnCheckedChangeListener(touch_vibration); - updateVibration(); - } - - @Override - public void onResume() { - super.onResume(); - Button buttonLaunchEditor = (Button) getView().findViewById(R.id.buttonLaunchEditor); - buttonLaunchEditor.setEnabled(isBIOSAvailable()); - } - - private boolean isBIOSAvailable() { - String home_directory = mPrefs.getString(Config.pref_home, - Environment.getExternalStorageDirectory().getAbsolutePath()); - return new File(home_directory, "data/dc_flash.bin").exists() - || mPrefs.getBoolean(Emulator.pref_usereios, false); - } - - private void updateVibration() { - boolean touchVibrationEnabled = mPrefs.getBoolean(Config.pref_touchvibe, true); - switchTouchVibrationEnabled.setChecked(touchVibrationEnabled); - } - -} diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/OptionsFragment.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/OptionsFragment.java index 1985c5ba4..08adeeecf 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/OptionsFragment.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/OptionsFragment.java @@ -124,7 +124,7 @@ public class OptionsFragment extends Fragment { home_directory = mPrefs.getString(Config.pref_home, home_directory); Emulator app = (Emulator) getActivity().getApplicationContext(); - app.getConfigurationPrefs(mPrefs); + app.getConfigurationPrefs(); // Generate the menu options and fill in existing settings @@ -422,53 +422,12 @@ public class OptionsFragment extends Fragment { } private void resetEmuSettings() { - mPrefs.edit().remove(Emulator.pref_usereios).apply(); mPrefs.edit().remove(Config.pref_gamedetails).apply(); - mPrefs.edit().remove(Emulator.pref_dynarecopt).apply(); - mPrefs.edit().remove(Emulator.pref_unstable).apply(); - mPrefs.edit().remove(Emulator.pref_cable).apply(); - mPrefs.edit().remove(Emulator.pref_dcregion).apply(); - mPrefs.edit().remove(Emulator.pref_broadcast).apply(); - mPrefs.edit().remove(Emulator.pref_language).apply(); - mPrefs.edit().remove(Emulator.pref_limitfps).apply(); - mPrefs.edit().remove(Emulator.pref_mipmaps).apply(); - mPrefs.edit().remove(Emulator.pref_widescreen).apply(); - mPrefs.edit().remove(Emulator.pref_frameskip).apply(); - mPrefs.edit().remove(Emulator.pref_pvrrender).apply(); - mPrefs.edit().remove(Emulator.pref_syncedrender).apply(); - mPrefs.edit().remove(Emulator.pref_bootdisk).apply(); - mPrefs.edit().remove(Emulator.pref_showfps).apply(); mPrefs.edit().remove(Config.pref_rendertype).apply(); - mPrefs.edit().remove(Emulator.pref_nosound).apply(); - mPrefs.edit().remove(Emulator.pref_nobatch).apply(); - mPrefs.edit().remove(Emulator.pref_customtextures).apply(); - mPrefs.edit().remove(Emulator.pref_modvols).apply(); - mPrefs.edit().remove(Emulator.pref_clipping).apply(); - mPrefs.edit().remove(Emulator.pref_dynsafemode).apply(); mPrefs.edit().remove(Config.pref_renderdepth).apply(); mPrefs.edit().remove(Config.pref_theme).apply(); - - Emulator.usereios = false; - Emulator.dynarecopt = true; - Emulator.unstableopt = false; - Emulator.cable = 3; - Emulator.dcregion = 3; - Emulator.broadcast = 4; - Emulator.language = 6; - Emulator.limitfps = true; - Emulator.mipmaps = true; - Emulator.widescreen = false; - Emulator.frameskip = 0; - Emulator.pvrrender = 0; - Emulator.syncedrender = true; - Emulator.bootdisk = null; Emulator.nosound = false; - Emulator.nobatch = false; - Emulator.customtextures = false; - Emulator.modvols = true; - Emulator.clipping = true; - Emulator.dynsafemode = true; getActivity().finish(); } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/PGConfigFragment.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/PGConfigFragment.java deleted file mode 100644 index 76ada6e3d..000000000 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/config/PGConfigFragment.java +++ /dev/null @@ -1,399 +0,0 @@ -package com.reicast.emulator.config; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.preference.PreferenceManager; -import android.support.constraint.ConstraintLayout; -import android.support.design.widget.Snackbar; -import android.support.graphics.drawable.VectorDrawableCompat; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.Spinner; -import android.widget.TextView; - -import com.android.util.FileUtils; -import com.reicast.emulator.Emulator; -import com.reicast.emulator.R; -import com.reicast.emulator.periph.Gamepad; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.ref.WeakReference; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class PGConfigFragment extends Fragment { - - private Spinner mSpnrConfigs; - - private CompoundButton switchJoystickDpadEnabled; - private CompoundButton dynarec_opt; - private CompoundButton unstable_opt; - private CompoundButton safemode_opt; - private EditText mainFrames; - private SeekBar frameSeek; - private CompoundButton pvr_render; - private CompoundButton synced_render; - private CompoundButton modifier_volumes; - private CompoundButton interrupt_opt; - private EditText bootdiskEdit; - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.pgconfig_fragment, container, false); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - - Emulator app = (Emulator) getActivity().getApplicationContext(); - app.getConfigurationPrefs(PreferenceManager.getDefaultSharedPreferences(getActivity())); - - mSpnrConfigs = (Spinner) getView().findViewById(R.id.config_spinner); - new LocateConfigs(PGConfigFragment.this).execute("/data/data/" - + getActivity().getPackageName() + "/shared_prefs/"); - - switchJoystickDpadEnabled = (CompoundButton) getView().findViewById( - R.id.switchJoystickDpadEnabled); - dynarec_opt = (CompoundButton) getView().findViewById(R.id.dynarec_option); - unstable_opt = (CompoundButton) getView().findViewById(R.id.unstable_option); - safemode_opt = (CompoundButton) getView().findViewById(R.id.dynarec_safemode); - mainFrames = (EditText) getView().findViewById(R.id.current_frames); - frameSeek = (SeekBar) getView().findViewById(R.id.frame_seekbar); - pvr_render = (CompoundButton) getView().findViewById(R.id.render_option); - synced_render = (CompoundButton) getView().findViewById(R.id.syncrender_option); - modifier_volumes = (CompoundButton) getView().findViewById(R.id.modvols_option); - interrupt_opt = (CompoundButton) getView().findViewById(R.id.interrupt_option); - bootdiskEdit = (EditText) getView().findViewById(R.id.boot_disk); - } - - private void saveSettings(SharedPreferences mPrefs) { - mPrefs.edit() - .putBoolean(Gamepad.pref_js_merged + "_A", switchJoystickDpadEnabled.isChecked()) - .putBoolean(Emulator.pref_dynarecopt, dynarec_opt.isChecked()) - .putBoolean(Emulator.pref_unstable, unstable_opt.isChecked()) - .putBoolean(Emulator.pref_dynsafemode, safemode_opt.isChecked()) - .putInt(Emulator.pref_frameskip, frameSeek.getProgress()) - .putBoolean(Emulator.pref_pvrrender, pvr_render.isChecked()) - .putBoolean(Emulator.pref_syncedrender, synced_render.isChecked()) - .putBoolean(Emulator.pref_modvols, modifier_volumes.isChecked()) - .putBoolean(Emulator.pref_interrupt, interrupt_opt.isChecked()).apply(); - if (bootdiskEdit.getText() != null) - mPrefs.edit().putString(Emulator.pref_bootdisk, - bootdiskEdit.getText().toString()).apply(); - else - mPrefs.edit().remove(Emulator.pref_bootdisk).apply(); - showToastMessage(getActivity().getString(R.string.pgconfig_saved), Snackbar.LENGTH_SHORT); - } - - private void clearSettings(SharedPreferences mPrefs, String gameId) { - mPrefs.edit() // Prevent clear() removing title - .remove(Gamepad.pref_js_merged + "_A") - .remove(Emulator.pref_dynarecopt) - .remove(Emulator.pref_unstable) - .remove(Emulator.pref_dynsafemode) - .remove(Emulator.pref_frameskip) - .remove(Emulator.pref_pvrrender) - .remove(Emulator.pref_syncedrender) - .remove(Emulator.pref_modvols) - .remove(Emulator.pref_interrupt) - .remove(Emulator.pref_bootdisk).apply(); - showToastMessage(getActivity().getString(R.string.pgconfig_cleared), Snackbar.LENGTH_SHORT); - configureViewByGame(gameId); - } - - private void configureViewByGame(final String gameId) { - final SharedPreferences mPrefs = getActivity() - .getSharedPreferences(gameId, Activity.MODE_PRIVATE); - switchJoystickDpadEnabled.setChecked(mPrefs.getBoolean( - Gamepad.pref_js_merged + "_A", false)); - dynarec_opt.setChecked(mPrefs.getBoolean(Emulator.pref_dynarecopt, Emulator.dynarecopt)); - unstable_opt.setChecked(mPrefs.getBoolean(Emulator.pref_unstable, Emulator.unstableopt)); - safemode_opt.setChecked(mPrefs.getBoolean(Emulator.pref_dynsafemode, Emulator.dynsafemode)); - - int frameskip = mPrefs.getInt(Emulator.pref_frameskip, Emulator.frameskip); - mainFrames.setText(String.valueOf(frameskip)); - - frameSeek.setProgress(frameskip); - frameSeek.setIndeterminate(false); - frameSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - mainFrames.setText(String.valueOf(progress)); - } - - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } - - public void onStopTrackingTouch(SeekBar seekBar) { - - } - }); - - mainFrames.setOnEditorActionListener(new EditText.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_DONE - || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER - && event.getAction() == KeyEvent.ACTION_DOWN)) { - if (event == null || !event.isShiftPressed()) { - if (v.getText() != null) { - int frames = Integer.parseInt(v.getText().toString()); - frameSeek.setProgress(frames); - } - hideSoftKeyBoard(); - return true; - } - } - return false; - } - }); - - synced_render.setChecked(mPrefs.getBoolean(Emulator.pref_syncedrender, Emulator.syncedrender)); - modifier_volumes.setChecked(mPrefs.getBoolean(Emulator.pref_modvols, Emulator.modvols)); - interrupt_opt.setChecked(mPrefs.getBoolean(Emulator.pref_interrupt, Emulator.interrupt)); - bootdiskEdit.setText(mPrefs.getString(Emulator.pref_bootdisk, Emulator.bootdisk)); - - bootdiskEdit.setOnEditorActionListener(new EditText.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_DONE - || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER - && event.getAction() == KeyEvent.ACTION_DOWN)) { - if (event == null || !event.isShiftPressed()) { - String disk; - if (v.getText() != null) { - disk = v.getText().toString(); - if (disk.equals("") || disk.substring( - disk.lastIndexOf("/") + 1).length() == 0) { - disk = null; - } else { - if (!disk.contains("/")) - disk = mPrefs.getString(Config.pref_games, - Environment.getExternalStorageDirectory() - .getAbsolutePath()) + "/" + disk; - if (!new File(disk).exists()) - disk = null; - } - v.setText(disk); - } - hideSoftKeyBoard(); - return true; - } - } - return false; - } - }); - - Button savePGC = (Button) getView().findViewById(R.id.save_pg_btn); - savePGC.setOnClickListener(new View.OnClickListener() { - public void onClick(View view) { - saveSettings(mPrefs); - } - }); - - Button importPGC = (Button) getView().findViewById(R.id.import_pg_btn); - importPGC.setOnClickListener(new View.OnClickListener() { - public void onClick(View view) { - try { - File xml = new File("/data/data/" - + getActivity().getPackageName(),"/shared_prefs/"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - xml = new File(getActivity().getDataDir(), - "/shared_prefs/" + gameId + ".xml"); - } - copy(new File(getActivity().getExternalFilesDir(null), - gameId + ".xml"), xml); - showToastMessage(getActivity().getString( - R.string.pgconfig_imported), Snackbar.LENGTH_SHORT); - configureViewByGame(gameId); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - Button exportPGC = (Button) getView().findViewById(R.id.export_pg_btn); - exportPGC.setOnClickListener(new View.OnClickListener() { - public void onClick(View view) { - try { - File xml = new File("/data/data/" - + getActivity().getPackageName(),"/shared_prefs/"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - xml = new File(getActivity().getDataDir(), - "/shared_prefs/" + gameId + ".xml"); - } - copy(xml, new File(getActivity().getExternalFilesDir(null), - gameId + ".xml")); - showToastMessage(getActivity().getString( - R.string.pgconfig_exported), Snackbar.LENGTH_SHORT); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - Button clearPGC = (Button) getView().findViewById(R.id.clear_pg_btn); - clearPGC.setOnClickListener(new View.OnClickListener() { - public void onClick(View view) { - clearSettings(mPrefs, gameId); - } - }); - } - - private void copy(File src, File dst) throws IOException { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - try (InputStream in = new FileInputStream(src)) { - try (OutputStream out = new FileOutputStream(dst)) { - // Transfer bytes from in to out - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } - } - } else { - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dst); - try { - // Transfer bytes from in to out - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } finally { - in.close(); - out.close(); - } - } - } - - private static class LocateConfigs extends AsyncTask> { - private WeakReference options; - - LocateConfigs(PGConfigFragment context) { - options = new WeakReference<>(context); - } - - @Override - protected List doInBackground(String... paths) { - File storage = new File(paths[0]); - Log.d("Files", storage.getAbsolutePath()); - FilenameFilter[] filter = new FilenameFilter[1]; - filter[0] = new FilenameFilter() { - public boolean accept(File dir, String name) { - return !name.endsWith("_preferences.xml"); - } - }; - FileUtils fileUtils = new FileUtils(); - Collection files = fileUtils.listFiles(storage, filter, 0); - return (List) files; - } - - @Override - protected void onPostExecute(List items) { - if (items != null && !items.isEmpty()) { - final Map gameMap = new HashMap<>(); - String[] titles = new String[items.size()]; - for (int i = 0; i < items.size(); i ++) { - String filename = items.get(i).getName(); - String gameFile = filename.substring(0, filename.length() - 4); - SharedPreferences mPrefs = options.get().getActivity() - .getSharedPreferences(gameFile, Activity.MODE_PRIVATE); - titles[i] = mPrefs.getString(Config.game_title, "Title Unavailable"); - gameMap.put(titles[i], gameFile); - } - ArrayAdapter configAdapter = new ArrayAdapter( - options.get().getActivity(), android.R.layout.simple_spinner_item, titles); - configAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - options.get().mSpnrConfigs.setAdapter(configAdapter); - options.get().mSpnrConfigs.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View select, int pos, long id) { - options.get().configureViewByGame(gameMap.get( - String.valueOf(parent.getItemAtPosition(pos)) - )); - } - @Override - public void onNothingSelected(AdapterView parentView) { - - } - }); - } else { - options.get().mSpnrConfigs.setEnabled(false); - } - } - } - - private void hideSoftKeyBoard() { - InputMethodManager iMm = (InputMethodManager) getActivity() - .getSystemService(Context.INPUT_METHOD_SERVICE); - if (iMm != null && iMm.isAcceptingText()) { - iMm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); - } - } - - private void showToastMessage(String message, int duration) { - ConstraintLayout layout = (ConstraintLayout) getActivity().findViewById(R.id.mainui_layout); - Snackbar snackbar = Snackbar.make(layout, message, duration); - View snackbarLayout = snackbar.getView(); - TextView textView = (TextView) snackbarLayout.findViewById( - android.support.design.R.id.snackbar_text); - textView.setGravity(Gravity.CENTER_VERTICAL); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) - textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY); - Drawable drawable; - if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { - drawable = getResources().getDrawable( - R.drawable.ic_settings, getActivity().getTheme()); - } else { - drawable = VectorDrawableCompat.create(getResources(), - R.drawable.ic_settings, getActivity().getTheme()); - } - textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); - textView.setCompoundDrawablePadding(getResources() - .getDimensionPixelOffset(R.dimen.snackbar_icon_padding)); - snackbar.show(); - } -} diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/debug/GenerateLogs.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/debug/GenerateLogs.java index 2fa204d07..0f774215a 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/debug/GenerateLogs.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/debug/GenerateLogs.java @@ -93,7 +93,11 @@ public class GenerateLogs extends AsyncTask { build_version = MM; } else if (build_sdk >= 24 && build_sdk < 26) { build_version = NT; - } else if (build_sdk >= 26) { + } else if (build_sdk >= 26 && build_sdk < 28) { + build_version = "Oreo"; + } else if (build_sdk == 28) { + build_version = "Pie"; + } else if (build_sdk > 28) { build_version = NL; } s += build_version + " (" + build_sdk + ")"; @@ -212,8 +216,8 @@ public class GenerateLogs extends AsyncTask { } private void showToastMessage(String message, int duration) { - ConstraintLayout layout = (ConstraintLayout) - ((Activity) mContext.get()).findViewById(R.id.mainui_layout); + View layout = + ((Activity) mContext.get()).findViewById(android.R.id.content); Snackbar snackbar = Snackbar.make(layout, message, duration); View snackbarLayout = snackbar.getView(); ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams( diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/AudioBackend.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/AudioBackend.java new file mode 100644 index 000000000..081880635 --- /dev/null +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/AudioBackend.java @@ -0,0 +1,102 @@ +package com.reicast.emulator.emu; + +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.os.Build; +import android.util.Log; + +import com.reicast.emulator.Emulator; + +import static android.media.AudioTrack.STATE_INITIALIZED; + +public final class AudioBackend { + static { System.loadLibrary("dc"); } + + private AudioTrack audioTrack; + private long writePosition; + private long size; //size in frames + private static AudioBackend instance; + + public AudioBackend() { + setInstance(this); + instance = this; + enableSound(!Emulator.nosound); + } + + public static AudioBackend getInstance() { + return instance; + } + public void release() { + setInstance(null); + instance = null; + } + + public void enableSound(boolean enable) { + if (enable && audioTrack == null) { + int min = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); + + if (2048 > min) + min = 2048; + + audioTrack = new AudioTrack( + AudioManager.STREAM_MUSIC, + 44100, + AudioFormat.CHANNEL_OUT_STEREO, + AudioFormat.ENCODING_PCM_16BIT, + min, + AudioTrack.MODE_STREAM + ); + if (audioTrack.getState() != STATE_INITIALIZED) { + audioTrack = null; + release(); + Log.e("reicast", "Error initializing AudioTrack. Disabling sound"); + } + else { + size = min / 4; + writePosition = 0; + + Log.i("audcfg", "Audio streaming: buffer size " + min + " samples / " + min / 44100.0 + " ms"); + audioTrack.play(); + } + } + else if (!enable && audioTrack != null) { + audioTrack.pause(); + audioTrack.flush(); + audioTrack.release(); + audioTrack = null; + } + } + + // Called by native code + private int writeBuffer(short[] samples, boolean wait) + { + if (audioTrack != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + audioTrack.write(samples, 0, samples.length, wait ? AudioTrack.WRITE_BLOCKING : AudioTrack.WRITE_NON_BLOCKING); + } else { + if (wait) + { + int newdata = samples.length / 2; + + //user bytes = write-read + //available = size - (write - play) + long used = writePosition - audioTrack.getPlaybackHeadPosition(); + long avail = size - used; + + //Log.i("audcfg", "u: " + used + " a: " + avail); + if (avail < newdata) + return 0; + + writePosition += newdata; + } + + audioTrack.write(samples, 0, samples.length); + } + } + + return 1; + } + + private static native void setInstance(AudioBackend backend); +} diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/EmuThread.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/EmuThread.java deleted file mode 100644 index ea6cf83a5..000000000 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/EmuThread.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.reicast.emulator.emu; - -import android.media.AudioFormat; -import android.media.AudioManager; -import android.media.AudioTrack; -import android.util.Log; - -import java.io.UnsupportedEncodingException; - -class EmuThread extends Thread -{ - private IEmulatorView view; - AudioTrack Player; - long pos; //write position - long size; //size in frames - private boolean sound; - - EmuThread(IEmulatorView view) { - this.view = view; - this.sound = view.hasSound(); - } - - @Override public void run() - { - if (sound) { - int min=AudioTrack.getMinBufferSize(44100,AudioFormat.CHANNEL_OUT_STEREO,AudioFormat.ENCODING_PCM_16BIT); - - if (2048>min) - min=2048; - - Player = new AudioTrack( - AudioManager.STREAM_MUSIC, - 44100, - AudioFormat.CHANNEL_OUT_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - min, - AudioTrack.MODE_STREAM - ); - - size=min/4; - pos=0; - - Log.i("audcfg", "Audio streaming: buffer size " + min + " samples / " + min/44100.0 + " ms"); - Player.play(); - } - - JNIdc.run(this); - } - - // Called by native code - int WriteBuffer(short[] samples, int wait) - { - if (sound) { - int newdata=samples.length/2; - - if (wait==0) - { - //user bytes = write-read - //available = size - (write - play) - long used=pos-Player.getPlaybackHeadPosition(); - long avail=size-used; - - //Log.i("audcfg", "u: " + used + " a: " + avail); - if (avail vjoy[j][1] && y <= (vjoy[j][1] + vjoy[j][3])) { if (vjoy[j][4] >= -2) { if (vjoy[j][5] == 0) - if (!editVjoyMode && touchVibrationEnabled) - vib.vibrate(vibrationDuration); + if (!editVjoyMode && Emulator.vibrationDuration > 0) + vib.vibrate(Emulator.vibrationDuration); vjoy[j][5] = 2; } @@ -507,46 +469,11 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView int joyy = get_anal(11, 1); InputDeviceManager.getInstance().virtualGamepadEvent(rv, joyx, joyy, left_trigger, right_trigger); // Only register the mouse event if no virtual gamepad button is down - if (!editVjoyMode && rv == 0xFFFF) + if ((!editVjoyMode && rv == 0xFFFF) || JNIdc.guiIsOpen()) InputDeviceManager.getInstance().mouseEvent(mouse_pos[0], mouse_pos[1], mouse_btns); return(true); } - @Override - public boolean hasSound() { - return !Emulator.nosound; - } - - @Override - public void reiosInfo(String reiosId, String reiosSoftware) { - if (fileName != null) { - String gameId = reiosId.replaceAll("[^a-zA-Z0-9]+", "").toLowerCase(); - SharedPreferences mPrefs = context.getSharedPreferences(gameId, Activity.MODE_PRIVATE); - Emulator app = (Emulator) context.getApplicationContext(); - app.loadGameConfiguration(gameId); - if (context instanceof GL2JNIActivity) - ((GL2JNIActivity) context).getPad().joystick[0] = mPrefs.getBoolean( - Gamepad.pref_js_merged + "_A", - ((GL2JNIActivity) context).getPad().joystick[0]); - mPrefs.edit().putString(Config.game_title, reiosSoftware.trim()).apply(); - } - } - - @Override - public void postMessage(final String msg) { - handler.post(new Runnable() { - public void run() { - Log.d(context.getPackageName(), msg); - Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); - } - }); - } - - @Override - public void finish() { - ((Activity) context).finish(); - } - private class OscOnScaleGestureListener extends SimpleOnScaleGestureListener { @@ -572,8 +499,6 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView { private GL2JNIView mView; - private FPSCounter fps = new FPSCounter(); - private FpsPopup fpsPop; Renderer (GL2JNIView mView) { this.mView = mView; @@ -582,73 +507,32 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView public void onDrawFrame(GL10 gl) { if (JNIdc.rendframeJava()) { - if (fpsPop != null && fpsPop.isShowing()) { - fps.logFrame(); - } } if(mView.takeScreenshot){ mView.takeScreenshot = false; FileUtils.saveScreenshot(mView.getContext(), mView.getWidth(), mView.getHeight(), gl); } - if (mView.ethd.getState() == Thread.State.TERMINATED) { - JNIdc.rendtermJava(); - System.exit(0); - // Ideally: ((Activity)mView.getContext()).finish(); - } } public void onSurfaceChanged(GL10 gl,int width,int height) { gl.glViewport(0, 0, width, height); - if (Emulator.widescreen) { + // TODO Is this required? The renderer sets the viewport and scissor test correctly +// if (Emulator.widescreen) { JNIdc.rendinitJava(width, height); - } else { - JNIdc.rendinitJava(height * (4 / 3), height); - } +// } else { +// JNIdc.rendinitJava(height * (4 / 3), height); +// } } public void onSurfaceCreated(GL10 gl,EGLConfig config) { onSurfaceChanged(gl, 800, 480); } - - class FPSCounter { - long startTime = System.nanoTime(); - int frames = 0; - - void logFrame() { - frames++; - if (System.nanoTime() - startTime >= 1000000000) { - final int current_frames = frames; - frames = 0; - startTime = System.nanoTime(); - mView.post(new Runnable() { - public void run() { - fpsPop.setText(current_frames); - } - }); - } - } - } - } - - public void audioDisable(boolean disabled) { - if (disabled) { - ethd.Player.pause(); - } else { - ethd.Player.play(); - } - } - - public void fastForward(boolean enabled) { - if (enabled) { - ethd.setPriority(Thread.MIN_PRIORITY); - } else { - ethd.setPriority(Thread.NORM_PRIORITY); - } } public void onDestroy() { + /* // Workaround for ANR when returning to menu System.exit(0); try { @@ -656,6 +540,7 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView } catch (InterruptedException e) { e.printStackTrace(); } + */ } @TargetApi(19) @@ -678,7 +563,4 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView public void screenGrab() { takeScreenshot = true; } - - public static class EmulatorInitFailed extends RuntimeException { - } } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/IEmulatorView.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/IEmulatorView.java deleted file mode 100644 index 9dfe94ab4..000000000 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/IEmulatorView.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.reicast.emulator.emu; - -public interface IEmulatorView { - boolean hasSound(); - void reiosInfo(String reiosId, String reiosSoftware); - void postMessage(String msg); - void finish(); -} diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java index 7e7341db8..f7da3c90a 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java @@ -1,5 +1,6 @@ package com.reicast.emulator.emu; +import android.util.Log; import android.view.Surface; import com.reicast.emulator.Emulator; @@ -10,10 +11,8 @@ public final class JNIdc static { System.loadLibrary("dc"); } public static native String initEnvironment(Emulator emulator, String homeDirectory); - public static native void config(String dirName); - public static native String init(String fileName); - public static native void query(EmuThread thread); - public static native void run(EmuThread thread); + public static native void setExternalStorageDirectories(Object[] pathList); + public static native void setGameUri(String fileName); public static native void pause(); public static native void resume(); public static native void stop(); @@ -31,65 +30,11 @@ public final class JNIdc public static native void vjoy(int id,float x, float y, float w, float h); public static native void getControllers(int[] controllers, int[][] peripherals); - public static native void initControllers(int[] controllers, int[][] peripherals); public static native void setupMic(SipEmulator sip); - public static native void diskSwap(String disk); - public static native void vmuSwap(); - public static native void setupVmu(Object sip); - public static native boolean getDynarec(); - public static native void setDynarec(boolean dynarec); - public static native boolean getIdleskip(); - public static native void setIdleskip(boolean idleskip); - public static native boolean getUnstable(); - public static native void setUnstable(boolean unstable); - public static native boolean getSafemode(); - public static native void setSafemode(boolean safemode); - public static native int getCable(); - public static native void setCable(int cable); - public static native int getRegion(); - public static native void setRegion(int region); - public static native int getBroadcast(); - public static native void setBroadcast(int broadcast); - public static native int getLanguage(); - public static native void setLanguage(int language); - public static native boolean getLimitfps(); - public static native void setLimitfps(boolean limiter); - public static native boolean getNobatch(); - public static native void setNobatch(boolean nobatch); public static native boolean getNosound(); - public static native void setNosound(boolean noaudio); - public static native boolean getMipmaps(); - public static native void setMipmaps(boolean mipmaps); public static native boolean getWidescreen(); - public static native void setWidescreen(boolean stretch); - public static native int getFrameskip(); - public static native void setFrameskip(int frames); - public static native int getPvrrender(); - public static native void setPvrrender(int render); - public static native boolean getSyncedrender(); - public static native void setSyncedrender(boolean sync); - public static native boolean getModvols(); - public static native void setModvols(boolean volumes); - public static native boolean getClipping(); - public static native void setClipping(boolean clipping); - public static native void bootdisk(String disk); - public static native boolean getUsereios(); - public static native void setUsereios(boolean reios); - public static native boolean getCustomtextures(); - public static native void setCustomtextures(boolean customtex); - public static native boolean getShowfps(); - public static native void setShowfps(boolean showfps); - public static native boolean getRenderToTextureBuffer(); - public static native void setRenderToTextureBuffer(boolean render); - public static native int getRenderToTextureUpscale(); - public static native void setRenderToTextureUpscale(int upscale); - public static native int getTextureUpscale(); - public static native void setTextureUpscale(int upscale); - public static native int getMaxFilteredTextureSize(); - public static native void setMaxFilteredTextureSize(int maxSize); - public static native int getMaxThreads(); - public static native void setMaxThreads(int maxThreads); + public static native int getVirtualGamepadVibration(); public static native void screenDpi(int screenDpi); public static native void guiOpenSettings(); @@ -98,8 +43,4 @@ public final class JNIdc public static void show_osd() { JNIdc.vjoy(13, 1,0,0,0); } - - public static void hide_osd() { - JNIdc.vjoy(13, 0,0,0,0); - } // FIXME use HideOSD() } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java index 05e9f8eb9..f1de97446 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java @@ -16,6 +16,7 @@ import android.util.Log; import android.view.InputDevice; import android.view.MotionEvent; import android.view.ScaleGestureDetector; +import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Toast; @@ -27,9 +28,7 @@ import com.reicast.emulator.config.Config; import com.reicast.emulator.periph.InputDeviceManager; import com.reicast.emulator.periph.VJoy; -public class NativeGLView extends SurfaceView implements IEmulatorView { - private static String fileName; - private EmuThread ethd; +public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback { private Handler handler = new Handler(); private Vibrator vib; @@ -42,9 +41,8 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { private static final float[][] vjoy = VJoy.baseVJoy(); - private boolean touchVibrationEnabled; - private int vibrationDuration; private Context context; + private boolean paused = false; public void restoreCustomVjoyValues(float[][] vjoy_d_cached) { vjoy_d_custom = vjoy_d_cached; @@ -54,19 +52,15 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { requestLayout(); } - public NativeGLView(Context context) { - super(context); - } - - public NativeGLView(Context context, AttributeSet attrs) { - super(context, attrs); - } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public NativeGLView(final Context context, String newFileName, boolean editVjoyMode) { - super(context); + public NativeGLView(Context context) { + this(context, null); + } + + public NativeGLView(final Context context, AttributeSet attrs) { + super(context, attrs); + getHolder().addCallback(this); this.context = context; - this.editVjoyMode = editVjoyMode; setKeepScreenOn(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { @@ -90,56 +84,31 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { DisplayMetrics dm = context.getResources().getDisplayMetrics(); JNIdc.screenDpi((int)Math.max(dm.xdpi, dm.ydpi)); - //JNIdc.config(prefs.getString(Config.pref_home, - // Environment.getExternalStorageDirectory().getAbsolutePath())); - - ethd = new EmuThread(this); - - touchVibrationEnabled = prefs.getBoolean(Config.pref_touchvibe, true); - vibrationDuration = prefs.getInt(Config.pref_vibrationDuration, 20); - this.setLayerType(prefs.getInt(Config.pref_rendertype, LAYER_TYPE_HARDWARE), null); vjoy_d_custom = VJoy.readCustomVjoyValues(context); scaleGestureDetector = new ScaleGestureDetector(context, new OscOnScaleGestureListener()); - // This is the game we are going to run - fileName = newFileName; - if (NativeGLActivity.syms != null) JNIdc.data(1, NativeGLActivity.syms); -/* - final String initStatus = JNIdc.init(fileName); - if (initStatus != null) - { - handler.post(new Runnable() { - public void run() { - Log.e("initialization", "dc_init: " + initStatus); - Toast.makeText(context, initStatus, Toast.LENGTH_SHORT).show(); - } - }); - throw new EmulatorInitFailed(); - } - JNIdc.query(ethd); -*/ - // Continuously render frames until the emulator stops + startRendering(); + } + + private void startRendering() { + // Continuously render frames + handler.removeCallbacksAndMessages(null); handler.post(new Runnable() { @Override public void run() { - //if (ethd.getState() == Thread.State.TERMINATED) - // ((Activity)getContext()).finish(); - //else + if (!paused) { JNIdc.rendframeNative(); handler.post(this); } } }); - - ethd.run(); // FIXME Not a thread anymore - } private void reset_analog() @@ -185,6 +154,10 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { float a_x = -tx+ 24*scl; float a_y=- 24*scl; + // Not sure how this can happen + if (vjoy_d_custom == null) + return; + float[][] vjoy_d = VJoy.getVjoy_d(vjoy_d_custom); for (int i=0;i vjoy[j][1] && y <= (vjoy[j][1] + vjoy[j][3])) { if (vjoy[j][4] >= -2) { if (vjoy[j][5] == 0) - if (!editVjoyMode && touchVibrationEnabled) - vib.vibrate(vibrationDuration); + if (!editVjoyMode && Emulator.vibrationDuration > 0) + vib.vibrate(Emulator.vibrationDuration); vjoy[j][5] = 2; } @@ -448,40 +421,37 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { int joyy = get_anal(11, 1); InputDeviceManager.getInstance().virtualGamepadEvent(rv, joyx, joyy, left_trigger, right_trigger); // Only register the mouse event if no virtual gamepad button is down - if (!editVjoyMode && rv == 0xFFFF) + if ((!editVjoyMode && rv == 0xFFFF) || JNIdc.guiIsOpen()) InputDeviceManager.getInstance().mouseEvent(mouse_pos[0], mouse_pos[1], mouse_btns); return(true); } @Override - public boolean hasSound() { - return !Emulator.nosound; + public void surfaceCreated(SurfaceHolder surfaceHolder) { + } @Override - public void reiosInfo(String reiosId, String reiosSoftware) { - if (fileName != null) { - String gameId = reiosId.replaceAll("[^a-zA-Z0-9]+", "").toLowerCase(); - SharedPreferences mPrefs = context.getSharedPreferences(gameId, Activity.MODE_PRIVATE); - Emulator app = (Emulator) context.getApplicationContext(); - app.loadGameConfiguration(gameId); - mPrefs.edit().putString(Config.game_title, reiosSoftware.trim()).apply(); - } + public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int w, int h) { + //Log.i("reicast", "NativeGLView.surfaceChanged: " + w + "x" + h); + JNIdc.rendinitNative(surfaceHolder.getSurface(), w, h); } @Override - public void postMessage(final String msg) { - handler.post(new Runnable() { - public void run() { - Log.d(context.getPackageName(), msg); - Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); - } - }); + public void surfaceDestroyed(SurfaceHolder surfaceHolder) { + //Log.i("reicast", "NativeGLView.surfaceDestroyed"); + JNIdc.rendinitNative(null, 0, 0); } - @Override - public void finish() { - ((Activity) context).finish(); + public void pause() { + paused = true; + JNIdc.pause(); + } + + public void resume() { + paused = false; + JNIdc.resume(); + startRendering(); } private class OscOnScaleGestureListener extends @@ -505,20 +475,6 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { } } - public void stop() { - Log.i("NativeGLView", "Stopping emulator"); - //JNIdc.destroy(); - JNIdc.stop(); - /* - try { - ethd.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - */ - Log.i("NativeGLView", "Stopping emulator completed"); - } - @TargetApi(19) @Override public void onWindowFocusChanged(boolean hasFocus) { @@ -535,6 +491,8 @@ public class NativeGLView extends SurfaceView implements IEmulatorView { } } - public static class EmulatorInitFailed extends RuntimeException { + public void setEditVjoyMode(boolean editVjoyMode) { + this.editVjoyMode = editVjoyMode; + selectedVjoyElement = -1; } } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/OnScreenMenu.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/OnScreenMenu.java index ba0fc0c93..f309aabc8 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/OnScreenMenu.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/OnScreenMenu.java @@ -1,49 +1,9 @@ package com.reicast.emulator.emu; -import android.app.Activity; import android.content.Context; -import android.content.SharedPreferences; -import android.view.Gravity; -import android.widget.PopupWindow; -import android.widget.TextView; - -import com.reicast.emulator.GL2JNIActivity; -import com.reicast.emulator.R; - -import java.util.Vector; public class OnScreenMenu { - private Activity mContext; - - public OnScreenMenu(Activity context, SharedPreferences prefs) { - if (context instanceof GL2JNIActivity) { - this.mContext = context; - } - } - - - public class FpsPopup extends PopupWindow { - - private TextView fpsText; - - public FpsPopup(Context c) { - super(c); - setBackgroundDrawable(null); - fpsText = new TextView(mContext); - fpsText.setTextAppearance(mContext, R.style.fpsOverlayText); - fpsText.setGravity(Gravity.CENTER); - fpsText.setText("XX"); - setContentView(fpsText); - setFocusable(false); - } - - public void setText(int frames) { - fpsText.setText(String.valueOf(frames)); - fpsText.invalidate(); - } - } - public static int getPixelsFromDp(float dps, Context context) { return (int) (dps * context.getResources().getDisplayMetrics().density + 0.5f); } diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java index 323065aef..ec533e842 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/periph/InputDeviceManager.java @@ -63,7 +63,7 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene } // Called from native code - private boolean Rumble(int i, float power, float inclination, int duration_ms) { + private boolean rumble(int i, float power, float inclination, int duration_ms) { Vibrator vibrator; if (i == VIRTUAL_GAMEPAD_ID) { vibrator = (Vibrator)Emulator.getAppContext().getSystemService(Context.VIBRATOR_SERVICE); diff --git a/shell/android-studio/reicast/src/main/jni/src/Android.cpp b/shell/android-studio/reicast/src/main/jni/src/Android.cpp index a7ee30be3..7df9543a8 100644 --- a/shell/android-studio/reicast/src/main/jni/src/Android.cpp +++ b/shell/android-studio/reicast/src/main/jni/src/Android.cpp @@ -7,11 +7,10 @@ #include #include -#include -#include -#include +#include "types.h" #include #include +#include #include "hw/maple/maple_cfg.h" #include "hw/pvr/Renderer_if.h" @@ -21,9 +20,9 @@ #include "hw/maple/maple_if.h" #include "hw/naomi/naomi_cart.h" #include "oslib/audiobackend_android.h" -#include "reios/reios.h" #include "imgread/common.h" #include "rend/gui.h" +#include "cfg/cfg.h" JavaVM* g_jvm; @@ -31,65 +30,58 @@ JavaVM* g_jvm; // Also attach the threads, and detach it on destruction, if needed. class JVMAttacher { public: - JVMAttacher() : env(NULL), detach_thread(false) { - if (g_jvm == NULL) { - log_error("g_jvm == NULL"); - return; - } - int rc = g_jvm->GetEnv((void **)&env, JNI_VERSION_1_6); - if (rc == JNI_EDETACHED) { - if (g_jvm->AttachCurrentThread(&env, NULL) != 0) { - log_error("AttachCurrentThread failed"); - return; + JVMAttacher() : _env(NULL), _detach_thread(false) { + } + JNIEnv *getEnv() + { + if (_env == NULL) + { + if (g_jvm == NULL) { + die("g_jvm == NULL"); + return NULL; + } + int rc = g_jvm->GetEnv((void **)&_env, JNI_VERSION_1_6); + if (rc == JNI_EDETACHED) { + if (g_jvm->AttachCurrentThread(&_env, NULL) != 0) { + die("AttachCurrentThread failed"); + return NULL; + } + _detach_thread = true; + } + else if (rc == JNI_EVERSION) { + die("JNI version error"); + return NULL; } - detach_thread = true; - } - else if (rc == JNI_EVERSION) { - log_error("JNI version error"); - return; } + return _env; } ~JVMAttacher() { - if (detach_thread) + if (_detach_thread) g_jvm->DetachCurrentThread(); } - bool failed() { return env == NULL; } - - JNIEnv *env; - private: - void log_error(const char *reason) - { - LOGE("JVMAttacher cannot attach to JVM: %s", reason); - } - - bool detach_thread = false; + JNIEnv *_env; + bool _detach_thread; }; +static thread_local JVMAttacher jvm_attacher; #include "android_gamepad.h" #define SETTINGS_ACCESSORS(jsetting, csetting, type) \ JNIEXPORT type JNICALL Java_com_reicast_emulator_emu_JNIdc_get ## jsetting(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); \ -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_set ## jsetting(JNIEnv *env, jobject obj, type v) __attribute__((visibility("default"))); \ JNIEXPORT type JNICALL Java_com_reicast_emulator_emu_JNIdc_get ## jsetting(JNIEnv *env, jobject obj) \ { \ return settings.csetting; \ -} \ -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_set ## jsetting(JNIEnv *env, jobject obj, type v) \ -{ \ - /* settings.csetting = v; */ \ } extern "C" { JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_initEnvironment(JNIEnv *env, jobject obj, jobject emulator, jstring homeDirectory) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_config(JNIEnv *env,jobject obj,jstring dirName) __attribute__((visibility("default"))); -JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_init(JNIEnv *env,jobject obj,jstring fileName) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_query(JNIEnv *env,jobject obj,jobject emu_thread) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_run(JNIEnv *env,jobject obj,jobject emu_thread) __attribute__((visibility("default"))); +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setExternalStorageDirectories(JNIEnv *env, jobject obj, jobjectArray pathList) __attribute__((visibility("default"))); +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setGameUri(JNIEnv *env,jobject obj,jstring fileName) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_pause(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_stop(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); @@ -104,45 +96,15 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv * JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeJava(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendtermJava(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_vjoy(JNIEnv * env, jobject obj,u32 id,float x, float y, float w, float h) __attribute__((visibility("default"))); +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_vjoy(JNIEnv * env, jobject obj,int id,float x, float y, float w, float h) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_initControllers(JNIEnv *env, jobject obj, jintArray controllers, jobjectArray peripherals) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_getControllers(JNIEnv *env, jobject obj, jintArray controllers, jobjectArray peripherals) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(JNIEnv *env,jobject obj,jobject sip) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_diskSwap(JNIEnv *env,jobject obj,jstring disk) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_vmuSwap(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupVmu(JNIEnv *env,jobject obj,jobject sip) __attribute__((visibility("default"))); -SETTINGS_ACCESSORS(Dynarec, dynarec.Enable, jboolean) -SETTINGS_ACCESSORS(Idleskip, dynarec.idleskip, jboolean) -SETTINGS_ACCESSORS(Unstable, dynarec.unstable_opt, jboolean) -SETTINGS_ACCESSORS(Safemode, dynarec.safemode, jboolean) -SETTINGS_ACCESSORS(Cable, dreamcast.cable, jint) -SETTINGS_ACCESSORS(Region, dreamcast.region, jint) -SETTINGS_ACCESSORS(Broadcast, dreamcast.broadcast, jint) -SETTINGS_ACCESSORS(Language, dreamcast.language, jint) -SETTINGS_ACCESSORS(Limitfps, aica.LimitFPS, jboolean) -SETTINGS_ACCESSORS(Nobatch, aica.NoBatch, jboolean) SETTINGS_ACCESSORS(Nosound, aica.NoSound, jboolean) -SETTINGS_ACCESSORS(Mipmaps, rend.UseMipmaps, jboolean) SETTINGS_ACCESSORS(Widescreen, rend.WideScreen, jboolean) -SETTINGS_ACCESSORS(Frameskip, pvr.ta_skip, jint) -SETTINGS_ACCESSORS(Pvrrender, pvr.rend, jint) -SETTINGS_ACCESSORS(Syncedrender, pvr.SynchronousRender, jboolean) -SETTINGS_ACCESSORS(Modvols, rend.ModifierVolumes, jboolean) -SETTINGS_ACCESSORS(Clipping, rend.Clipping, jboolean) -SETTINGS_ACCESSORS(Usereios, bios.UseReios, jboolean) -SETTINGS_ACCESSORS(Customtextures, rend.CustomTextures, jboolean) -SETTINGS_ACCESSORS(Showfps, rend.ShowFPS, jboolean) -SETTINGS_ACCESSORS(RenderToTextureBuffer, rend.RenderToTextureBuffer, jboolean) -SETTINGS_ACCESSORS(RenderToTextureUpscale, rend.RenderToTextureUpscale, jint) -SETTINGS_ACCESSORS(TextureUpscale, rend.TextureUpscale, jint) -SETTINGS_ACCESSORS(MaxFilteredTextureSize, rend.MaxFilteredTextureSize, jint) -SETTINGS_ACCESSORS(MaxThreads, pvr.MaxThreads, jint) - -JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_getBootdisk(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_bootdisk(JNIEnv *env,jobject obj, jstring disk) __attribute__((visibility("default"))); +SETTINGS_ACCESSORS(VirtualGamepadVibration, input.VirtualGamepadVibration, jint); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_screenDpi(JNIEnv *env,jobject obj, jint screenDpi) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_guiOpenSettings(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); @@ -155,6 +117,10 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_virtu JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickButtonEvent(JNIEnv *env, jobject obj, jint id, jint key, jboolean pressed) __attribute__((visibility("default"))); JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAxisEvent(JNIEnv *env, jobject obj, jint id, jint key, jint value) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_mouseEvent(JNIEnv *env, jobject obj, jint xpos, jint ypos, jint buttons) __attribute__((visibility("default"))); + +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_AudioBackend_setInstance(JNIEnv *env, jobject obj, jobject instance) __attribute__((visibility("default"))); + +JNIEXPORT void JNICALL Java_com_reicast_emulator_NativeGLActivity_register(JNIEnv *env, jobject obj, jobject activity) __attribute__((visibility("default"))); }; JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_screenDpi(JNIEnv *env,jobject obj, jint screenDpi) @@ -238,9 +204,14 @@ JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_initEnvironment(JN // Initialize platform-specific stuff common_linux_setup(); + bool first_init = false; + // Keep reference to global JVM and Emulator objects if (g_jvm == NULL) + { + first_init = true; env->GetJavaVM(&g_jvm); + } if (g_emulator == NULL) { g_emulator = env->NewGlobalRef(emulator); saveAndroidSettingsMid = env->GetMethodID(env->GetObjectClass(emulator), "SaveAndroidSettings", "(Ljava/lang/String;)V"); @@ -254,27 +225,37 @@ JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_initEnvironment(JN if (homeDirectory != NULL) env->ReleaseStringUTFChars(homeDirectory, path); - jstring msg = NULL; - int rc = reicast_init(0, NULL); - if (rc == -4) - msg = env->NewStringUTF("Cannot find configuration"); - else if (rc == 69) - msg = env->NewStringUTF("Invalid command line"); - else if (rc == -1) - msg = env->NewStringUTF("Memory initialization failed"); - return msg; + if (first_init) + { + // Do one-time initialization + jstring msg = NULL; + int rc = reicast_init(0, NULL); + if (rc == -4) + msg = env->NewStringUTF("Cannot find configuration"); + else if (rc == 69) + msg = env->NewStringUTF("Invalid command line"); + else if (rc == -1) + msg = env->NewStringUTF("Memory initialization failed"); + return msg; + } + else + return NULL; } -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_config(JNIEnv *env,jobject obj,jstring dirName) +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setExternalStorageDirectories(JNIEnv *env, jobject obj, jobjectArray pathList) { - // Set home directory based on User config - const char* D = dirName? env->GetStringUTFChars(dirName,0):0; -// set_user_config_dir(D); -// set_user_data_dir(D); -// printf("Config dir is: %s\n", get_writable_config_path("").c_str()); -// printf("Data dir is: %s\n", get_writable_data_path("").c_str()); - setenv("REICAST_HOME", D, 1); - env->ReleaseStringUTFChars(dirName,D); + std::string paths; + int obj_len = env->GetArrayLength(pathList); + for (int i = 0; i < obj_len; ++i) { + jstring dir = (jstring)env->GetObjectArrayElement(pathList, i); + const char* p = env->GetStringUTFChars(dir, 0); + if (!paths.empty()) + paths += ":"; + paths += p; + env->ReleaseStringUTFChars(dir, p); + env->DeleteLocalRef(dir); + } + setenv("REICAST_HOME", paths.c_str(), 1); } JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_bootdisk(JNIEnv *env,jobject obj, jstring disk) { @@ -291,41 +272,19 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_bootdisk(JNIEnv *env, } } -JNIEXPORT jstring JNICALL Java_com_reicast_emulator_emu_JNIdc_init(JNIEnv *env,jobject obj,jstring fileName) +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setGameUri(JNIEnv *env,jobject obj,jstring fileName) { - /* FIXME - // Get filename string from Java - const char* P = fileName ? env->GetStringUTFChars(fileName,0) : 0; - if (!P) gamedisk[0] = '\0'; - else + if (fileName != NULL) { - printf("Game Disk URI: '%s'\n",P); - strncpy(gamedisk,(strlen(P)>=7)&&!memcmp(P,"file://",7)? P+7:P,sizeof(gamedisk)); - gamedisk[sizeof(gamedisk)-1] = '\0'; - env->ReleaseStringUTFChars(fileName,P); + // Get filename string from Java + const char* file_path = env->GetStringUTFChars(fileName, 0); + printf("Game Disk URI: '%s'\n", file_path); + strncpy(gamedisk, strlen(file_path) >= 7 && !memcmp(file_path, "file://", 7) ? file_path + 7 : file_path, sizeof(gamedisk)); + gamedisk[sizeof(gamedisk) - 1] = '\0'; + env->ReleaseStringUTFChars(fileName, file_path); + + cfgSetVirtual("config", "image", file_path); } - - // Set configuration - settings.profile.run_counts = 0; - - // Run nullDC emulator - int rc = dc_start_game(gamedisk); - - jstring msg = NULL; - if (rc == -5) - msg = env->NewStringUTF("BIOS files cannot be found"); - else if (rc == -4) - msg = env->NewStringUTF("Cannot find configuration"); - else if (rc == -3) - msg = env->NewStringUTF("Sound/GPU initialization failed"); - else if (rc == 69) - msg = env->NewStringUTF("Invalid command line"); - else if (rc == -1) - msg = env->NewStringUTF("Memory initialization failed"); - - return msg; - */ - return NULL; } JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_diskSwap(JNIEnv *env,jobject obj,jstring disk) @@ -349,16 +308,6 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_diskSwap(JNIEnv *env, } } -#define SAMPLE_COUNT 512 - -JNIEnv* jenv; //we are abusing the f*** out of this poor guy -//JavaVM* javaVM = NULL; //this seems like the right way to go -//stuff for audio -jshortArray jsamples; -jmethodID writemid; -jmethodID coreMessageMid; -jmethodID dieMid; -jobject emu; //stuff for microphone jobject sipemu; jmethodID getmicdata; @@ -368,62 +317,11 @@ jbyteArray jpix = NULL; jmethodID updatevmuscreen; extern bool game_started; -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_query(JNIEnv *env,jobject obj,jobject emu_thread) -{ - /* FIXME - jmethodID reiosInfoMid=env->GetMethodID(env->GetObjectClass(emu_thread),"reiosInfo","(Ljava/lang/String;Ljava/lang/String;)V"); - - char *id = (char*)malloc(11); - strcpy(id, reios_disk_id()); - jstring reios_id = env->NewStringUTF(id); - - char *name = (char*)malloc(129); - strcpy(name, reios_software_name); - jstring reios_name = env->NewStringUTF(name); - - env->CallVoidMethod(emu_thread, reiosInfoMid, reios_id, reios_name); - */ -} - -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_run(JNIEnv *env,jobject obj,jobject emu_thread) -{ - install_prof_handler(0); - jenv = env; - emu = env->NewGlobalRef(emu_thread); // FIXME Delete ref - - jsamples=env->NewShortArray(SAMPLE_COUNT*2); - jsamples = (jshortArray)env->NewGlobalRef(jsamples); // FIXME Delete ref - writemid=env->GetMethodID(env->GetObjectClass(emu),"WriteBuffer","([SI)I"); - coreMessageMid=env->GetMethodID(env->GetObjectClass(emu),"coreMessage","([B)I"); - dieMid=env->GetMethodID(env->GetObjectClass(emu),"Die","()V"); - - //dc_run(NULL); - - //env->DeleteGlobalRef(emu); - //emu = NULL; -} - -int msgboxf(const wchar* text,unsigned int type,...) { - va_list args; - - wchar temp[2048]; - va_start(args, type); - vsprintf(temp, text, args); - va_end(args); - LOGE("%s", temp); - - if (emu == NULL) - return 0; - JVMAttacher attacher; - if (attacher.failed()) - return 0; - - int byteCount = strlen(temp); - jbyteArray bytes = attacher.env->NewByteArray(byteCount); - attacher.env->SetByteArrayRegion(bytes, 0, byteCount, (jbyte *) temp); - - return (int)attacher.env->CallIntMethod(emu, coreMessageMid, bytes); -} +//stuff for audio +#define SAMPLE_COUNT 512 +jshortArray jsamples; +jmethodID writeBufferMid; +static jobject g_audioBackend; JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(JNIEnv *env,jobject obj,jobject sip) { @@ -433,10 +331,8 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(JNIEnv *env, JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupVmu(JNIEnv *env,jobject obj,jobject vmu) { - //env->GetJavaVM(&javaVM); vmulcd = env->NewGlobalRef(vmu); updatevmuscreen = env->GetMethodID(env->GetObjectClass(vmu),"updateBytes","([B)V"); - //jpix=env->NewByteArray(1536); } JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_pause(JNIEnv *env,jobject obj) @@ -577,7 +473,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendtermJava(JNIEnv * rend_term_renderer(); } -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_vjoy(JNIEnv * env, jobject obj,u32 id,float x, float y, float w, float h) +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_vjoy(JNIEnv * env, jobject obj,int id,float x, float y, float w, float h) { if(idGetIntArrayElements(controllers, 0); - memcpy(settings.input.maple_devices, controllers_body, sizeof(settings.input.maple_devices)); - env->ReleaseIntArrayElements(controllers, controllers_body, 0); - - int obj_len = env->GetArrayLength(peripherals); - for (int i = 0; i < obj_len; ++i) { - jintArray port = (jintArray) env->GetObjectArrayElement(peripherals, i); - jint *items = env->GetIntArrayElements(port, 0); - settings.input.maple_expansion_devices[i][0] = items[0]; - settings.input.maple_expansion_devices[i][1] = items[1]; - env->ReleaseIntArrayElements(port, items, 0); - env->DeleteLocalRef(port); - } -} - JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_getControllers(JNIEnv *env, jobject obj, jintArray controllers, jobjectArray peripherals) { jint *controllers_body = env->GetIntArrayElements(controllers, 0); @@ -636,12 +515,9 @@ JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsOpen(JNIEnv u32 androidaudio_push(void* frame, u32 amt, bool wait) { verify(amt==SAMPLE_COUNT); - JVMAttacher attacher; // FIXME don't attach/detach every call... - if (attacher.failed()) - return 0; //yeah, do some audio piping magic here ! - attacher.env->SetShortArrayRegion(jsamples, 0, amt * 2, (jshort *)frame); - return attacher.env->CallIntMethod(emu, writemid, jsamples, wait); + jvm_attacher.getEnv()->SetShortArrayRegion(jsamples, 0, amt * 2, (jshort *)frame); + return jvm_attacher.getEnv()->CallIntMethod(g_audioBackend, writeBufferMid, jsamples, wait); } void androidaudio_init() @@ -662,15 +538,36 @@ audiobackend_t audiobackend_android = { &androidaudio_term }; +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_AudioBackend_setInstance(JNIEnv *env, jobject obj, jobject instance) +{ + if (g_audioBackend != NULL) + env->DeleteGlobalRef(g_audioBackend); + if (instance == NULL) { + g_audioBackend = NULL; + if (jsamples != NULL) { + env->DeleteGlobalRef(jsamples); + jsamples = NULL; + } + } + else { + g_audioBackend = env->NewGlobalRef(instance); + writeBufferMid = env->GetMethodID(env->GetObjectClass(g_audioBackend), "writeBuffer", "([SZ)I"); + if (jsamples == NULL) { + jsamples = env->NewShortArray(SAMPLE_COUNT * 2); + jsamples = (jshortArray) env->NewGlobalRef(jsamples); + } + } +} + int get_mic_data(u8* buffer) { - jbyteArray jdata = (jbyteArray)jenv->CallObjectMethod(sipemu,getmicdata); + jbyteArray jdata = (jbyteArray)jvm_attacher.getEnv()->CallObjectMethod(sipemu,getmicdata); if(jdata==NULL){ //LOGW("get_mic_data NULL"); return 0; } - jenv->GetByteArrayRegion(jdata, 0, SIZE_OF_MIC_DATA, (jbyte*)buffer); - jenv->DeleteLocalRef(jdata); + jvm_attacher.getEnv()->GetByteArrayRegion(jdata, 0, SIZE_OF_MIC_DATA, (jbyte*)buffer); + jvm_attacher.getEnv()->DeleteLocalRef(jdata); return 1; } @@ -679,13 +576,11 @@ int push_vmu_screen(u8* buffer) if(vmulcd==NULL){ return 0; } - JNIEnv *env = jenv; - //javaVM->AttachCurrentThread(&env, NULL); if(jpix==NULL){ - jpix=env->NewByteArray(1536); + jpix = jvm_attacher.getEnv()->NewByteArray(1536); } - env->SetByteArrayRegion(jpix,0,1536,(jbyte*)buffer); - env->CallVoidMethod(vmulcd,updatevmuscreen,jpix); + jvm_attacher.getEnv()->SetByteArrayRegion(jpix, 0, 1536, (jbyte*)buffer); + jvm_attacher.getEnv()->CallVoidMethod(vmulcd, updatevmuscreen, jpix); return 1; } @@ -702,20 +597,16 @@ void os_DebugBreak() void SaveAndroidSettings() { - JVMAttacher attacher; - if (attacher.failed()) - return; + jstring homeDirectory = jvm_attacher.getEnv()->NewStringUTF(get_writable_config_path("").c_str()); - jstring homeDirectory = attacher.env->NewStringUTF(get_writable_config_path("").c_str()); - - attacher.env->CallVoidMethod(g_emulator, saveAndroidSettingsMid, homeDirectory); - attacher.env->DeleteLocalRef(homeDirectory); + jvm_attacher.getEnv()->CallVoidMethod(g_emulator, saveAndroidSettingsMid, homeDirectory); + jvm_attacher.getEnv()->DeleteLocalRef(homeDirectory); } JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_init(JNIEnv *env, jobject obj) { input_device_manager = env->NewGlobalRef(obj); - input_device_manager_rumble = env->GetMethodID(env->GetObjectClass(obj), "Rumble", "(IFFI)Z"); + input_device_manager_rumble = env->GetMethodID(env->GetObjectClass(obj), "rumble", "(IFFI)Z"); } JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_joystickAdded(JNIEnv *env, jobject obj, jint id, jstring name, jint maple_port) @@ -773,3 +664,45 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_periph_InputDeviceManager_mouse mouse_gamepad.gamepad_btn_input(2, (buttons & 2) != 0); mouse_gamepad.gamepad_btn_input(4, (buttons & 4) != 0); } + +static jobject g_activity; +static jmethodID VJoyStartEditingMID; +static jmethodID VJoyStopEditingMID; +static jmethodID VJoyResetEditingMID; + +JNIEXPORT void JNICALL Java_com_reicast_emulator_NativeGLActivity_register(JNIEnv *env, jobject obj, jobject activity) +{ + if (g_activity != NULL) + { + env->DeleteGlobalRef(g_activity); + g_activity = NULL; + } + if (activity != NULL) { + g_activity = env->NewGlobalRef(activity); + VJoyStartEditingMID = env->GetMethodID(env->GetObjectClass(activity), "VJoyStartEditing", "()V"); + VJoyStopEditingMID = env->GetMethodID(env->GetObjectClass(activity), "VJoyStopEditing", "(Z)V"); + VJoyResetEditingMID = env->GetMethodID(env->GetObjectClass(activity), "VJoyResetEditing", "()V"); + } +} + +void vjoy_start_editing() +{ + jvm_attacher.getEnv()->CallVoidMethod(g_activity, VJoyStartEditingMID); +} + +void vjoy_reset_editing() +{ + jvm_attacher.getEnv()->CallVoidMethod(g_activity, VJoyResetEditingMID); +} + +void vjoy_stop_editing(bool canceled) +{ + jvm_attacher.getEnv()->CallVoidMethod(g_activity, VJoyStopEditingMID, canceled); +} + +void android_send_logs() +{ + JNIEnv *env = jvm_attacher.getEnv(); + jmethodID generateErrorLogMID = env->GetMethodID(env->GetObjectClass(g_activity), "generateErrorLog", "()V"); + env->CallVoidMethod(g_activity, generateErrorLogMID); +} diff --git a/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h b/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h index 2fee7b5f7..18e7fcf9e 100644 --- a/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h +++ b/shell/android-studio/reicast/src/main/jni/src/android_gamepad.h @@ -143,12 +143,10 @@ public: void rumble(float power, float inclination, u32 duration_ms) override { - JVMAttacher jvm_attacher; - if (jvm_attacher.failed()) - return; - jboolean has_vibrator = jvm_attacher.env->CallBooleanMethod(input_device_manager, input_device_manager_rumble, android_id, power, inclination, duration_ms); + jboolean has_vibrator = jvm_attacher.getEnv()->CallBooleanMethod(input_device_manager, input_device_manager_rumble, android_id, power, inclination, duration_ms); _rumble_enabled = has_vibrator; } + bool is_virtual_gamepad() override { return android_id == VIRTUAL_GAMEPAD_ID; } static const int VIRTUAL_GAMEPAD_ID = 0x12345678; // must match the Java definition @@ -198,7 +196,7 @@ public: if (!find_mapping()) input_mapper = new MouseInputMapping(); } - virtual ~AndroidMouseGamepadDevice() {} + bool gamepad_btn_input(u32 code, bool pressed) override { if (gui_is_open()) diff --git a/shell/android-studio/reicast/src/main/res/layout/about_fragment.xml b/shell/android-studio/reicast/src/main/res/layout/about_fragment.xml deleted file mode 100644 index 159643ec2..000000000 --- a/shell/android-studio/reicast/src/main/res/layout/about_fragment.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - diff --git a/shell/android-studio/reicast/src/main/res/layout/activity_main.xml b/shell/android-studio/reicast/src/main/res/layout/activity_main.xml index 48e95d478..69d972ec2 100644 --- a/shell/android-studio/reicast/src/main/res/layout/activity_main.xml +++ b/shell/android-studio/reicast/src/main/res/layout/activity_main.xml @@ -8,11 +8,6 @@ android:fitsSystemWindows="false" tools:openDrawer="start"> - - - - - - - - - - - - - - - - - diff --git a/shell/android-studio/reicast/src/main/res/layout/content_main.xml b/shell/android-studio/reicast/src/main/res/layout/content_main.xml index f47ff3664..357129494 100644 --- a/shell/android-studio/reicast/src/main/res/layout/content_main.xml +++ b/shell/android-studio/reicast/src/main/res/layout/content_main.xml @@ -6,8 +6,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" - tools:context=".MainActivity" - tools:showIn="@layout/app_bar_main"> + tools:context=".MainActivity"> + + + \ No newline at end of file diff --git a/shell/apple/emulator-ios/emulator/ios_main.mm b/shell/apple/emulator-ios/emulator/ios_main.mm index 00cad0b12..d0a092504 100644 --- a/shell/apple/emulator-ios/emulator/ios_main.mm +++ b/shell/apple/emulator-ios/emulator/ios_main.mm @@ -23,21 +23,6 @@ #include #include "hw/maple/maple_cfg.h" - -int msgboxf(const wchar* text,unsigned int type,...) -{ - va_list args; - - wchar temp[2048]; - va_start(args, type); - vsprintf(temp, text, args); - va_end(args); - - //printf(NULL,temp,VER_SHORTNAME,type | MB_TASKMODAL); - puts(temp); - return 0; -} - int darw_printf(const wchar* text,...) { va_list args; diff --git a/shell/apple/emulator-osx/emulator-osx/osx-main.mm b/shell/apple/emulator-osx/emulator-osx/osx-main.mm index a23e53e63..4cbe78a51 100644 --- a/shell/apple/emulator-osx/emulator-osx/osx-main.mm +++ b/shell/apple/emulator-osx/emulator-osx/osx-main.mm @@ -20,19 +20,6 @@ OSXKeyboardDevice keyboard(0); static std::shared_ptr kb_gamepad(0); static std::shared_ptr mouse_gamepad(0); -int msgboxf(const wchar* text,unsigned int type,...) -{ - va_list args; - - wchar temp[2048]; - va_start(args, type); - vsprintf(temp, text, args); - va_end(args); - - puts(temp); - return 0; -} - int darw_printf(const wchar* text,...) { va_list args; diff --git a/shell/apple/reicast.xcworkspace/xcshareddata/xcschemes/reicast-osx.xcscheme b/shell/apple/reicast.xcworkspace/xcshareddata/xcschemes/reicast-osx.xcscheme index 3677feecf..1301943e5 100644 --- a/shell/apple/reicast.xcworkspace/xcshareddata/xcschemes/reicast-osx.xcscheme +++ b/shell/apple/reicast.xcworkspace/xcshareddata/xcschemes/reicast-osx.xcscheme @@ -82,8 +82,9 @@