Moved most android settings into the new gui

virtual gamepad editing and settings
home directory setup during onboarding
start content browser at app startup after getting permission
Use imgui osd to display error messages (msgboxf)
Added About tab in settings with version, git hash and Send logcat
button (android)
This commit is contained in:
Flyinghead 2019-03-05 00:54:01 +01:00
parent 71ea60cc36
commit ca58c323cd
48 changed files with 796 additions and 2556 deletions

View File

@ -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

View File

@ -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; }
};

View File

@ -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() {}

View File

@ -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;

View File

@ -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];

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -21,6 +21,7 @@
#include <dirent.h>
#include <sys/stat.h>
#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<GamepadDevice> 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;
}

View File

@ -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();

68
core/rend/gui_android.cpp Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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

20
core/rend/gui_android.h Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
void gui_display_vjoy_commands(int screen_width, int screen_height, float scaling);
void vjoy_start_editing();

View File

@ -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));

View File

@ -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;
};

1
core/version/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/version.cpp

View File

@ -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];

View File

@ -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">
</activity>
<activity
android:name="com.dropbox.client2.android.AuthActivity"
@ -81,11 +81,6 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.reicast.emulator.config.EditVJoyActivity"
android:configChanges="orientation|navigation|screenSize|screenLayout|uiMode|keyboard|keyboardHidden"
android:screenOrientation="sensorLandscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"

View File

@ -32,34 +32,6 @@ import javax.microedition.khronos.opengles.GL10;
public class FileUtils {
public void saveArray(String filename, List<String> 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<String> loadArray(String filename) {
try {
FileInputStream fis = new FileInputStream(filename);
GZIPInputStream gzis = new GZIPInputStream(fis);
ObjectInputStream in = new ObjectInputStream(gzis);
List<String> read_field = (List<String>) in.readObject();
in.close();
return read_field;
} catch (Exception e) {
e.getStackTrace();
}
return null;
}
public Collection<File> listFiles(File directory, FilenameFilter[] filter,
int recurse) {

View File

@ -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<String, Integer, ArrayList<HashMap<String, String>>> {
private WeakReference<AboutFragment> ref;
retrieveGitTask(AboutFragment context) {
ref = new WeakReference<>(context);
}
@Override
protected ArrayList<HashMap<String, String>> doInBackground(
String... paths) {
ArrayList<HashMap<String, String>> 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<String, String> 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<HashMap<String, String>> 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();
}
}

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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<ResolveInfo> 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();
}
}

View File

@ -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<String> 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);
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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<String, Integer, List<File>> {
private WeakReference<PGConfigFragment> options;
LocateConfigs(PGConfigFragment context) {
options = new WeakReference<>(context);
}
@Override
protected List<File> 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<File> files = fileUtils.listFiles(storage, filter, 0);
return (List<File>) files;
}
@Override
protected void onPostExecute(List<File> items) {
if (items != null && !items.isEmpty()) {
final Map<String, String> 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<String> configAdapter = new ArrayAdapter<String>(
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();
}
}

View File

@ -93,7 +93,11 @@ public class GenerateLogs extends AsyncTask<String, Integer, String> {
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<String, Integer, String> {
}
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(

View File

@ -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);
}

View File

@ -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<newdata)
return 0;
}
pos+=newdata;
Player.write(samples, 0, samples.length);
}
return 1;
}
private void showMessage(final String msg) {
view.postMessage(msg);
}
// Called by native code
int coreMessage(byte[] msg) {
try {
showMessage(new String(msg, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
showMessage("coreMessage: Failed to display error");
}
return 1;
}
// Called by native code
void Die() {
showMessage("Something went wrong and reicast crashed.\nPlease report this on the reicast forums.");
view.finish();
}
// Called by native code
void reiosInfo(String reiosId, String reiosSoftware) {
view.reiosInfo(reiosId, reiosSoftware);
}
}

View File

@ -28,7 +28,6 @@ import com.reicast.emulator.Emulator;
import com.reicast.emulator.GL2JNIActivity;
import com.reicast.emulator.R;
import com.reicast.emulator.config.Config;
import com.reicast.emulator.emu.OnScreenMenu.FpsPopup;
import com.reicast.emulator.periph.Gamepad;
import com.reicast.emulator.periph.InputDeviceManager;
import com.reicast.emulator.periph.VJoy;
@ -56,15 +55,13 @@ import javax.microedition.khronos.opengles.GL10;
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
*/
public class GL2JNIView extends GLSurfaceView implements IEmulatorView
public class GL2JNIView extends GLSurfaceView
{
public static final boolean DEBUG = false;
public static final int LAYER_TYPE_SOFTWARE = 1;
public static final int LAYER_TYPE_HARDWARE = 2;
private static String fileName;
private EmuThread ethd;
private Handler handler = new Handler();
Vibrator vib;
@ -79,8 +76,6 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView
Renderer rend;
private boolean touchVibrationEnabled;
private int vibrationDuration;
Context context;
public void restoreCustomVjoyValues(float[][] vjoy_d_cached) {
@ -91,10 +86,6 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView
requestLayout();
}
public void setFpsDisplay(FpsPopup fpsPop) {
rend.fpsPop = fpsPop;
}
public GL2JNIView(Context context) {
super(context);
}
@ -104,7 +95,7 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public GL2JNIView(final Context context, String newFileName, boolean translucent,
public GL2JNIView(final Context context, boolean translucent,
int depth, int stencil, boolean editVjoyMode) {
super(context);
this.context = context;
@ -134,41 +125,15 @@ public class GL2JNIView extends GLSurfaceView 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 (GL2JNIActivity.syms != null)
JNIdc.data(1, GL2JNIActivity.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);
// By default, GLSurfaceView() creates a RGB_565 opaque surface.
// If we want a translucent one, we should change the surface's
// format here, using PixelFormat.TRANSLUCENT for GL Surfaces
@ -191,9 +156,6 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView
// Set the renderer responsible for frame rendering
setRenderer(rend = new Renderer(this));
ethd.start();
}
public GLSurfaceView.Renderer getRenderer()
@ -364,8 +326,8 @@ public class GL2JNIView extends GLSurfaceView implements IEmulatorView
if (y > 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 {
}
}

View File

@ -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();
}

View File

@ -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()
}

View File

@ -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.length;i++)
@ -305,8 +278,8 @@ public class NativeGLView extends SurfaceView implements IEmulatorView {
if (y > 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;
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -7,11 +7,10 @@
#include <unistd.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <types.h>
#include "types.h"
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <types.h>
#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(id<sizeof(vjoy_pos)/sizeof(vjoy_pos[0]))
{
@ -588,23 +484,6 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_vjoy(JNIEnv * env, jo
}
}
JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_initControllers(JNIEnv *env, jobject obj, jintArray controllers, jobjectArray peripherals)
{
jint *controllers_body = env->GetIntArrayElements(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);
}

View File

@ -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())

View File

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="@+id/about_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginTop="10dp"
android:ems="12"
android:gravity="center"
android:text="@string/about_text" />
<TextView
android:id="@+id/revision_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginTop="10dp"
android:ems="12"
android:gravity="center"
android:text="@string/revision_text" />
<LinearLayout
android:id="@+id/changelist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:orientation="vertical" >
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#b5b5b5"
android:dividerHeight="1dp" />
</LinearLayout>
</LinearLayout>

View File

@ -8,11 +8,6 @@
android:fitsSystemWindows="false"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.reicast.emulator.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@android:color/black"
app:popupTheme="@style/AppTheme.PopupOverlay">
<android.support.v7.widget.SearchView
android:id="@+id/searchView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="right"
android:iconifiedByDefault="true" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -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">
<FrameLayout
android:id="@+id/fragment_container"

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.reicast.emulator.NativeGLActivity">
<com.reicast.emulator.emu.NativeGLView
android:id="@+id/glView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>

View File

@ -23,21 +23,6 @@
#include <unistd.h>
#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;

View File

@ -20,19 +20,6 @@ OSXKeyboardDevice keyboard(0);
static std::shared_ptr<OSXKbGamepadDevice> kb_gamepad(0);
static std::shared_ptr<OSXMouseGamepadDevice> 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;

View File

@ -82,8 +82,9 @@
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"