diff --git a/.gitignore b/.gitignore
index 9c2c9cbc2..5a01e7d20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,8 @@ build/*
*Karen_angelXwind*
local.properties
ant.properties
+
+# Linux stuff
+shell/lin86/.map
+shell/lin86/nosym-reicast.elf
+shell/lin86/reicast.elf
diff --git a/.travis.yml b/.travis.yml
index a38e3eeb6..1b0b7028d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ before_install:
- sudo apt-get -qq update
- sudo apt-get -qq -y install openjdk-7-jdk ant lib32z1-dev lib32stdc++6
- GIT_HASH=`git log --pretty=format:'%h' -n 1`
-- GIT_BUILD=`git rev-parse --abbrev-ref HEAD`-$GIT_HASH
+- GIT_BUILD=`git describe --all`-$GIT_HASH
install:
- download_extract http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2
android-ndk-r9c-linux-x86_64.tar.bz2
diff --git a/README.md b/README.md
index d9862b508..7e663621b 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,22 @@ cd shell/ios/
xcodebuild -configuration Release
```
+Building for Linux
+------------------
+
+The code is only currently compatible with 32bit architectures so you will need
+to install 32bit libs to build reicast.
+
+Requirements:
+* build-essential
+* libasound
+* libegl1-mesa-dev
+* libgles2-mesa-dev
+* libasound2-dev
+
+To build the project, go to shell/lin86 and run make
+
+
Translations
------------
New and updated translations are always appreciated!
@@ -82,7 +98,9 @@ Well, glad you liked the project so far!
We're currently short on hardware.
-If you would like to donate some devices, get in touch at team@reicast.com. GLES3 capable stuff, some mainstream hardware and rarities would be extremely appreciated.
+If you would like to donate some devices, get in touch at team@reicast.com.
+GLES3 capable stuff, some mainstream hardware and rarities would be extremely
+appreciated.
Keep in mind we're located in Greece for the most part
This has been tested/developed on
@@ -94,14 +112,17 @@ This has been tested/developed on
* Various development boards
* GCW Zero
-We had to buy all of these, except the GCW Zero and a BeagleBone which were donated (Thanks! You rock!)
+We had to buy all of these, except the GCW Zero and a BeagleBone which were
+donated (Thanks! You rock!)
Apart from that, we don't accept monetary donations right now.
We also don't plan to be releasing a premium version at any store.
-Most of the project has been developed by drk||Raziel (aka, skmp, drk, Raz, etc) but it has been based on the
-works of multiple people. It would be extremely unfair to charge for it and get all the credit :)
+Most of the project has been developed by drk||Raziel (aka, skmp, drk, Raz,
+etc) but it has been based on the works of multiple people. It would be
+extremely unfair to charge for it and get all the credit :)
-We're planning for an indiegogo campaign later on to help with sustained development and running costs, so follow @reicastdc on twitter for updates
+We're planning for an indiegogo campaign later on to help with sustained
+development and running costs, so follow @reicastdc on twitter for updates
Other Testing
-------------
@@ -124,14 +145,16 @@ Team
You can check the currently active committers on [the pretty graphs page](https://github.com/reicast/reicast-emulator/graphs/contributors)
-Our IRC channel is [#reicast @ chat.freenode.net](irc://chat.freenode.net/reicast).
+Our IRC channel is [#reicast @ chat.freenode.net](irc://chat.freenode.net/reicast).
-The original reicast team consisted of drk||Raziel (mostly just writing code), PsyMan (debugging/testing and everything else) and a little bit of gb_away
+The original reicast team consisted of drk||Raziel (mostly just writing code),
+PsyMan (debugging/testing and everything else) and a little bit of gb_away
Special thanks
--------------
-In previous iterations a lot of people have worked on this, notably David Miller (aka, ZeZu), the nullDC team, friends from #pcsx2 and all over the world :)
+In previous iterations a lot of people have worked on this, notably David
+Miller (aka, ZeZu), the nullDC team, friends from #pcsx2 and all over the world :)
[](https://bitdeli.com/free "Bitdeli Badge")
diff --git a/shell/android/res/values-ko/strings.xml b/shell/android/res/values-ko/strings.xml
index 58f405ea1..b57e98f11 100644
--- a/shell/android/res/values-ko/strings.xml
+++ b/shell/android/res/values-ko/strings.xml
@@ -7,12 +7,12 @@
기본 게임 저장
부팅 드림 캐스트 바이오스
- BIOS는 없음.드림 캐스트 BIOS가 작동하려면이 에뮬레이터가 필요합니다.BIOS 파일에 배치 %1$s/데이터/dc_boot.bin
- 누락 플래시.드림 캐스트 플래시가 작동하려면이 에뮬레이터가 필요합니다.플래시 파일에 배치 %1$s/데이터/dc_flash.bin
- 당신은 BIOS를 제공해야
+ BIOS가 없음.드림캐스트가 작동하려면 BIOS가 필요합니다.BIOS 파일에 배치 %1$s/데이터/dc_boot.bin
+ 플래시파일 없음.드림 캐스트가 에뮬레이터가 작동하려면 플레시파일이필요합니다.%1$s/데이터/dc_flash.bin에 넣으십시오
+ BIOS가 필요합니다
BOOT의 BIOS
- 현재 폴더를 선택
+ 이 폴더를 선택
실험 (광범위한 패닉이 발생할 수 있음)
Dynarec 옵션
@@ -34,7 +34,7 @@
제어 장치 B
제어 장치 C
제어 장치 D
- 컨트롤러 연결되지 않음
+ 컨트롤러가 연결되지 않음
선정 된 제어기가 없습니다
선택
제거
diff --git a/shell/android/res/values/strings.xml b/shell/android/res/values/strings.xml
index d2d027818..9c0396c89 100644
--- a/shell/android/res/values/strings.xml
+++ b/shell/android/res/values/strings.xml
@@ -113,4 +113,7 @@
be created in VmuBackups folder!
Upload VMU
Download VMU
+
+ Copying logcat content to clipboard\nPlease paste in the issue report
+ Log saved to \"Files Dir\" path
\ No newline at end of file
diff --git a/shell/android/src/com/reicast/emulator/FileBrowser.java b/shell/android/src/com/reicast/emulator/FileBrowser.java
index 80347ba2f..cb5095ecb 100644
--- a/shell/android/src/com/reicast/emulator/FileBrowser.java
+++ b/shell/android/src/com/reicast/emulator/FileBrowser.java
@@ -66,11 +66,6 @@ public class FileBrowser extends Fragment {
super.onCreate(savedInstanceState);
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- sdcard = getActivity().getExternalFilesDir(null);
- home_directory = sdcard + "/dc";
- game_directory = sdcard + "/dc";
- }
home_directory = mPrefs.getString(Config.pref_home, home_directory);
game_directory = mPrefs.getString(Config.pref_games, game_directory);
diff --git a/shell/android/src/com/reicast/emulator/GL2JNIActivity.java b/shell/android/src/com/reicast/emulator/GL2JNIActivity.java
index beef10062..b180bea4e 100644
--- a/shell/android/src/com/reicast/emulator/GL2JNIActivity.java
+++ b/shell/android/src/com/reicast/emulator/GL2JNIActivity.java
@@ -282,10 +282,10 @@ public class GL2JNIActivity extends Activity {
GL2JNIView.rt[playerNum] = (int) (R2 * 255);
if (prefs.getBoolean("right_buttons", true)) {
- if (RS_Y > 0.5) {
+ if (RS_Y > 0.25) {
handle_key(playerNum, pad.map[playerNum][0]/* A */, true);
pad.wasKeyStick[playerNum] = true;
- } else if (RS_Y < 0.5) {
+ } else if (RS_Y < 0.25) {
handle_key(playerNum, pad.map[playerNum][1]/* B */, true);
pad.wasKeyStick[playerNum] = true;
} else if (pad.wasKeyStick[playerNum]){
@@ -294,10 +294,10 @@ public class GL2JNIActivity extends Activity {
pad.wasKeyStick[playerNum] = false;
}
} else {
- if (RS_Y > 0.5) {
+ if (RS_Y > 0.25) {
GL2JNIView.rt[playerNum] = (int) (RS_Y * 255);
GL2JNIView.lt[playerNum] = (int) (L2 * 255);
- } else if (RS_Y < 0.5) {
+ } else if (RS_Y < 0.25) {
GL2JNIView.rt[playerNum] = (int) (R2 * 255);
GL2JNIView.lt[playerNum] = (int) (-(RS_Y) * 255);
}
diff --git a/shell/android/src/com/reicast/emulator/GL2JNINative.java b/shell/android/src/com/reicast/emulator/GL2JNINative.java
index 7c8bcb6f7..8d69f40cc 100644
--- a/shell/android/src/com/reicast/emulator/GL2JNINative.java
+++ b/shell/android/src/com/reicast/emulator/GL2JNINative.java
@@ -372,10 +372,10 @@ public class GL2JNINative extends NativeActivity {
GL2JNIView.rt[playerNum] = (int) (R2 * 255);
if (prefs.getBoolean("right_buttons", true)) {
- if (RS_Y > 0.5) {
+ if (RS_Y > 0.25) {
handle_key(playerNum, pad.map[playerNum][0]/* A */, true);
pad.wasKeyStick[playerNum] = true;
- } else if (RS_Y < 0.5) {
+ } else if (RS_Y < 0.25) {
handle_key(playerNum, pad.map[playerNum][1]/* B */, true);
pad.wasKeyStick[playerNum] = true;
} else if (pad.wasKeyStick[playerNum]){
@@ -384,10 +384,10 @@ public class GL2JNINative extends NativeActivity {
pad.wasKeyStick[playerNum] = false;
}
} else {
- if (RS_Y > 0.5) {
+ if (RS_Y > 0.25) {
GL2JNIView.rt[playerNum] = (int) (RS_Y * 255);
GL2JNIView.lt[playerNum] = (int) (L2 * 255);
- } else if (RS_Y < 0.5) {
+ } else if (RS_Y < 0.25) {
GL2JNIView.rt[playerNum] = (int) (R2 * 255);
GL2JNIView.lt[playerNum] = (int) (-(RS_Y) * 255);
}
diff --git a/shell/android/src/com/reicast/emulator/MainActivity.java b/shell/android/src/com/reicast/emulator/MainActivity.java
index 75c6d4428..68d9b7964 100644
--- a/shell/android/src/com/reicast/emulator/MainActivity.java
+++ b/shell/android/src/com/reicast/emulator/MainActivity.java
@@ -13,6 +13,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
@@ -22,10 +23,10 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnSystemUiVisibilityChangeListener;
import android.view.View.OnTouchListener;
+import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
@@ -35,6 +36,7 @@ import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;
import com.reicast.emulator.config.Config;
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 com.reicast.emulator.periph.Gamepad;
@@ -322,7 +324,11 @@ public class MainActivity extends SlidingFragmentActivity implements
}
});
} else {
- messages.setVisibility(View.GONE);
+ messages.setOnClickListener(new OnClickListener() {
+ public void onClick(View view) {
+ generateErrorLog();
+ }
+ });
}
}
});
@@ -336,6 +342,17 @@ public class MainActivity extends SlidingFragmentActivity implements
}
});
}
+
+ public void generateErrorLog() {
+ GenerateLogs mGenerateLogs = new GenerateLogs(MainActivity.this);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ mGenerateLogs.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
+ getFilesDir().getAbsolutePath());
+ } else {
+ mGenerateLogs.execute(getFilesDir().getAbsolutePath());
+ }
+
+ }
/**
* Display a dialog to notify the user of prior crash
diff --git a/shell/android/src/com/reicast/emulator/config/Config.java b/shell/android/src/com/reicast/emulator/config/Config.java
index 44a35db83..c6e670fad 100644
--- a/shell/android/src/com/reicast/emulator/config/Config.java
+++ b/shell/android/src/com/reicast/emulator/config/Config.java
@@ -58,6 +58,10 @@ public class Config {
public static String cheatdisk = "null";
public static boolean nativeact = false;
public static int vibrationDuration = 20;
+
+ public static String git_issues = "https://github.com/reicast/reicast-emulator/issues/";
+ public static String log_url = "http://loungekatt.no-ip.biz:3194/ReicastBot/report/submit.php";
+ public static String report_url = "http://loungekatt.no-ip.biz:3194/ReicastBot/report/logs/";
private SharedPreferences mPrefs;
diff --git a/shell/android/src/com/reicast/emulator/config/OptionsFragment.java b/shell/android/src/com/reicast/emulator/config/OptionsFragment.java
index 4c76beef4..8c3985152 100644
--- a/shell/android/src/com/reicast/emulator/config/OptionsFragment.java
+++ b/shell/android/src/com/reicast/emulator/config/OptionsFragment.java
@@ -1,12 +1,10 @@
package com.reicast.emulator.config;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.channels.FileChannel;
import android.app.Activity;
import android.content.SharedPreferences;
@@ -85,11 +83,6 @@ public class OptionsFragment extends Fragment {
// setContentView(R.layout.activity_main);
//parentActivity = getActivity();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- sdcard = getActivity().getExternalFilesDir(null);
- home_directory = sdcard + "/dc";
- game_directory = sdcard + "/dc";
- }
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
@@ -124,11 +117,6 @@ public class OptionsFragment extends Fragment {
Toast.makeText(getActivity(), R.string.data_folder,
Toast.LENGTH_SHORT).show();
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- cleanHouse(getActivity().getExternalFilesDir(null));
- buildHouse(new File(home_directory), getActivity().getExternalFilesDir(null));
- home_directory = sdcard + "/dc";
- }
mPrefs.edit().putString("home_directory", home_directory)
.commit();
}
@@ -518,43 +506,6 @@ public class OptionsFragment extends Fragment {
});
}
- private void cleanHouse(File dir) {
- File[] existing = dir.listFiles();
- for (File item: existing) {
- if (item.isDirectory()) {
- cleanHouse(item);
- } else {
- item.delete();
- }
- }
- }
-
- private void buildHouse(File dir, File root) {
- File[] existing = dir.listFiles();
- for (File item: existing) {
- if (item.isDirectory()) {
- item.mkdirs();
- buildHouse(item, item);
- } else {
- try {
- copy(item, new File(root + "/" + item));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- public void copy(File src, File dst) throws IOException {
- FileInputStream inStream = new FileInputStream(src);
- FileOutputStream outStream = new FileOutputStream(dst);
- FileChannel inChannel = inStream.getChannel();
- FileChannel outChannel = outStream.getChannel();
- inChannel.transferTo(0, inChannel.size(), outChannel);
- inStream.close();
- outStream.close();
- }
-
private void flashBios(String localized) {
File local = new File(home_directory, "data/dc_flash[" + localized
+ "].bin");
diff --git a/shell/android/src/com/reicast/emulator/debug/GenerateLogs.java b/shell/android/src/com/reicast/emulator/debug/GenerateLogs.java
new file mode 100644
index 000000000..b22db1606
--- /dev/null
+++ b/shell/android/src/com/reicast/emulator/debug/GenerateLogs.java
@@ -0,0 +1,246 @@
+package com.reicast.emulator.debug;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import com.reicast.emulator.R;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.widget.Toast;
+
+public class GenerateLogs extends AsyncTask {
+
+ public static final String build_model = android.os.Build.MODEL;
+ public static final String build_device = android.os.Build.DEVICE;
+ public static final String build_board = android.os.Build.BOARD;
+ public static final int build_sdk = android.os.Build.VERSION.SDK_INT;
+
+ public static final String DN = "Donut";
+ public static final String EC = "Eclair";
+ public static final String FR = "Froyo";
+ public static final String GB = "Gingerbread";
+ public static final String HC = "Honeycomb";
+ public static final String IC = "Ice Cream Sandwich";
+ public static final String JB = "JellyBean";
+ public static final String KK = "KitKat";
+ public static final String NF = "Not Found";
+
+ private String unHandledIOE;
+
+ private Context mContext;
+ private String currentTime;
+
+ public GenerateLogs(Context mContext) {
+ this.mContext = mContext;
+ this.currentTime = String.valueOf(System.currentTimeMillis());
+ }
+
+ /**
+ * Obtain the specific parameters of the current device
+ *
+ */
+ private String discoverCPUData() {
+ String s = "MODEL: " + Build.MODEL;
+ s += "\r\n";
+ s += "DEVICE: " + build_device;
+ s += "\r\n";
+ s += "BOARD: " + build_board;
+ s += "\r\n";
+ if (String.valueOf(build_sdk) != null) {
+ String build_version = NF;
+ if (build_sdk >= 4 && build_sdk < 7) {
+ build_version = DN;
+ } else if (build_sdk == 7) {
+ build_version = EC;
+ } else if (build_sdk == 8) {
+ build_version = FR;
+ } else if (build_sdk >= 9 && build_sdk < 11) {
+ build_version = GB;
+ } else if (build_sdk >= 11 && build_sdk < 14) {
+ build_version = HC;
+ } else if (build_sdk >= 14 && build_sdk < 16) {
+ build_version = IC;
+ } else if (build_sdk >= 16 && build_sdk < 19) {
+ build_version = JB;
+ } else if (build_sdk >= 19) {
+ build_version = KK;
+ }
+ s += build_version + " (" + build_sdk + ")";
+ } else {
+ String prop_build_version = "ro.build.version.release";
+ String prop_sdk_version = "ro.build.version.sdk";
+ String build_version = readOutput("/system/bin/getprop "
+ + prop_build_version);
+ String sdk_version = readOutput("/system/bin/getprop "
+ + prop_sdk_version);
+ s += build_version + " (" + sdk_version + ")";
+ }
+ return s;
+ }
+
+ /**
+ * 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 = null;
+ 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();
+ }
+ }
+
+ public void setUnhandled(String unHandledIOE) {
+ this.unHandledIOE = unHandledIOE;
+ }
+
+ @Override
+ protected String doInBackground(String... params) {
+ File logFile = new File(params[0], currentTime + ".txt");
+ Process mLogcatProc = null;
+ BufferedReader reader = null;
+ final StringBuilder log = new StringBuilder();
+ String separator = System.getProperty("line.separator");
+ log.append(discoverCPUData());
+ if (unHandledIOE != null) {
+ log.append(separator);
+ log.append(separator);
+ log.append("Unhandled Exceptions");
+ log.append(separator);
+ log.append(separator);
+ log.append(unHandledIOE);
+ }
+ try {
+ mLogcatProc = Runtime.getRuntime().exec(
+ new String[] { "logcat", "-d", "AndroidRuntime:E *:S" });
+ reader = new BufferedReader(new InputStreamReader(
+ mLogcatProc.getInputStream()));
+ String line;
+ log.append(separator);
+ log.append(separator);
+ log.append("AndroidRuntime Output");
+ log.append(separator);
+ log.append(separator);
+ while ((line = reader.readLine()) != null) {
+ log.append(line);
+ log.append(separator);
+ }
+ reader.close();
+ mLogcatProc = null;
+ reader = null;
+ int PID = android.os.Process.getUidForName("com.reicast.emulator");
+ mLogcatProc = Runtime.getRuntime().exec(
+ new String[] { "logcat", "-d", "|", "grep " + PID });
+ reader = new BufferedReader(new InputStreamReader(
+ mLogcatProc.getInputStream()));
+ log.append(separator);
+ log.append(separator);
+ log.append("Application Core Output");
+ log.append(separator);
+ log.append(separator);
+ while ((line = reader.readLine()) != null) {
+ log.append(line);
+ log.append(separator);
+ }
+ reader.close();
+ mLogcatProc = null;
+ reader = null;
+ mLogcatProc = Runtime.getRuntime().exec(
+ new String[] { "logcat", "-d", "reidc:V *:S" });
+ reader = new BufferedReader(new InputStreamReader(
+ mLogcatProc.getInputStream()));
+ log.append(separator);
+ log.append(separator);
+ log.append("Native Interface Output");
+ log.append(separator);
+ log.append(separator);
+ while ((line = reader.readLine()) != null) {
+ log.append(line);
+ log.append(separator);
+ }
+ reader.close();
+ mLogcatProc = null;
+ reader = null;
+ mLogcatProc = Runtime.getRuntime().exec(
+ new String[] { "logcat", "-d", "GL2JNIView:E *:S" });
+ reader = new BufferedReader(new InputStreamReader(
+ mLogcatProc.getInputStream()));
+ log.append(separator);
+ log.append(separator);
+ log.append("Open GLES View Output");
+ log.append(separator);
+ log.append(separator);
+ while ((line = reader.readLine()) != null) {
+ log.append(line);
+ log.append(separator);
+ }
+ reader.close();
+ mLogcatProc = null;
+ reader = null;
+ File memory = new File(mContext.getFilesDir(), "mem_alloc.txt");
+ if (memory.exists()) {
+ log.append(separator);
+ log.append(separator);
+ log.append("Memory Allocation Table");
+ log.append(separator);
+ log.append(separator);
+ FileInputStream fis = new FileInputStream(memory);
+ reader = new BufferedReader(new InputStreamReader(fis));
+ while ((line = reader.readLine()) != null) {
+ log.append(line);
+ log.append(separator);
+ }
+ fis.close();
+ fis = null;
+ reader.close();
+ reader = null;
+ }
+ BufferedWriter writer = new BufferedWriter(new FileWriter(logFile));
+ writer.write(log.toString());
+ writer.flush();
+ writer.close();
+ return log.toString();
+ } catch (IOException e) {
+
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(final String response) {
+ if (response != null && !response.equals(null)) {
+ Toast.makeText(mContext, mContext.getString(R.string.log_saved),
+ Toast.LENGTH_SHORT).show();
+ Toast.makeText(mContext, mContext.getString(R.string.platform),
+ Toast.LENGTH_SHORT).show();
+ UploadLogs mUploadLogs = new UploadLogs(mContext, currentTime);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ mUploadLogs.executeOnExecutor(
+ AsyncTask.THREAD_POOL_EXECUTOR, response);
+ } else {
+ mUploadLogs.execute(response);
+ }
+ }
+ }
+}
diff --git a/shell/android/src/com/reicast/emulator/debug/UploadLogs.java b/shell/android/src/com/reicast/emulator/debug/UploadLogs.java
new file mode 100644
index 000000000..a776e3a99
--- /dev/null
+++ b/shell/android/src/com/reicast/emulator/debug/UploadLogs.java
@@ -0,0 +1,140 @@
+package com.reicast.emulator.debug;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+
+import com.reicast.emulator.config.Config;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.StrictMode;
+
+/**
+ * Upload the specialized logcat to reicast issues
+ *
+ * @param mContext
+ * The context this method will be executed from
+ * @param currentTime
+ * The system time at which the log was made
+ */
+public class UploadLogs extends AsyncTask {
+
+ private String currentTime;
+ private String logUrl;
+ private Context mContext;
+
+ public UploadLogs(Context mContext, String currentTime) {
+ this.mContext = mContext;
+ this.currentTime = currentTime;
+ }
+
+ private void RedirectSubmission(Header[] headers, String content) {
+ UploadLogs mUploadLogs = new UploadLogs(mContext,
+ currentTime);
+ mUploadLogs.setPostUrl(headers[headers.length - 1]
+ .getValue());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ mUploadLogs.executeOnExecutor(
+ AsyncTask.THREAD_POOL_EXECUTOR, content);
+ } else {
+ mUploadLogs.execute(content);
+ }
+ }
+
+ /**
+ * Set the URL for where the log will be uploaded
+ *
+ * @param logUrl
+ * The URL of the log upload server
+ */
+ public void setPostUrl(String logUrl) {
+ this.logUrl = logUrl;
+ }
+
+ @SuppressLint("NewApi")
+ protected void onPreExecute() {
+ if (logUrl == null || logUrl.equals(null)) {
+ logUrl = Config.log_url;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
+ .permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ @Override
+ protected Object doInBackground(String... params) {
+ HttpClient client = new DefaultHttpClient();
+ HttpPost post = new HttpPost(logUrl);
+ try {
+ ArrayList mPairs = new ArrayList();
+ mPairs.add(new BasicNameValuePair("name", currentTime));
+ mPairs.add(new BasicNameValuePair("issue", params[0]));
+ post.setEntity(new UrlEncodedFormEntity(mPairs));
+ HttpResponse getResponse = client.execute(post);
+ final int statusCode = getResponse.getStatusLine().getStatusCode();
+ if (statusCode != HttpStatus.SC_OK) {
+ Header[] headers = getResponse.getHeaders("Location");
+ if (headers != null && headers.length != 0) {
+ RedirectSubmission(headers, params[0]);
+ } else {
+ return null;
+ }
+ } else {
+ return EntityUtils.toString(getResponse.getEntity());
+ }
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ post.abort();
+ } catch (IOException e) {
+ e.printStackTrace();
+ post.abort();
+ } catch (Exception e) {
+ e.printStackTrace();
+ post.abort();
+ }
+ return null;
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onPostExecute(Object response) {
+ if (response != null && !response.equals(null)) {
+ String logLink = Config.report_url + currentTime + ".txt";
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ android.content.ClipboardManager clipboard = (android.content.ClipboardManager) mContext
+ .getSystemService(Context.CLIPBOARD_SERVICE);
+ android.content.ClipData clip = android.content.ClipData
+ .newPlainText("logcat", logLink);
+ clipboard.setPrimaryClip(clip);
+ } else {
+ android.text.ClipboardManager clipboard = (android.text.ClipboardManager) mContext
+ .getSystemService(Context.CLIPBOARD_SERVICE);
+ clipboard.setText(logLink);
+ }
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse(Config.git_issues));
+ mContext.startActivity(browserIntent);
+ }
+ }
+}