diff --git a/build.sh b/build.sh index cc7854d17..d8607d463 100755 --- a/build.sh +++ b/build.sh @@ -55,7 +55,8 @@ fi rm -f project/src/Globals.java } -[ -z "$GCCVER" ] && GCCVER=4.6 +NDK_TOOLCHAIN_VERSION=$GCCVER +[ -z "$NDK_TOOLCHAIN_VERSION" ] && NDK_TOOLCHAIN_VERSION=4.6 # Set here your own NDK path if needed # export PATH=$PATH:~/src/endless_space/android-ndk-r7 @@ -95,46 +96,67 @@ $quick_rebuild || rm -r -f project/bin/* # New Android SDK introduced some lame- cd ../../../.. } -cd project && env PATH=$NDKBUILDPATH BUILD_NUM_CPUS=$NCPU nice -n19 ndk-build -j$NCPU V=1 && \ - { grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ +strip_libs() { + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ echo Stripping libapplication-armeabi.so by hand && \ rm obj/local/armeabi/libapplication.so && \ cp jni/application/src/libapplication-armeabi.so obj/local/armeabi/libapplication.so && \ cp jni/application/src/libapplication-armeabi.so libs/armeabi/libapplication.so && \ - `which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-${GCCVER}/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi/libapplication.so \ - || true ; } && \ - { grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-${NDK_TOOLCHAIN_VERSION}/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ grep "MultiABI=" ../AndroidAppSettings.cfg | grep "y\\|all\\|armeabi-v7a" > /dev/null && \ echo Stripping libapplication-armeabi-v7a.so by hand && \ rm obj/local/armeabi-v7a/libapplication.so && \ cp jni/application/src/libapplication-armeabi-v7a.so obj/local/armeabi-v7a/libapplication.so && \ cp jni/application/src/libapplication-armeabi-v7a.so libs/armeabi-v7a/libapplication.so && \ - `which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-${GCCVER}/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi-v7a/libapplication.so \ - || true ; } && \ - { grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-${NDK_TOOLCHAIN_VERSION}/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi-v7a/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ grep "MultiABI=" ../AndroidAppSettings.cfg | grep "armeabi-v7a-hard" > /dev/null && \ echo Stripping libapplication-armeabi-v7a-hard.so by hand && \ rm obj/local/armeabi-v7a-hard/libapplication.so && \ cp jni/application/src/libapplication-armeabi-v7a-hard.so obj/local/armeabi-v7a-hard/libapplication.so && \ cp jni/application/src/libapplication-armeabi-v7a-hard.so libs/armeabi-v7a/libapplication.so && \ - `which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-${GCCVER}/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi-v7a/libapplication.so \ - || true ; } && \ - { grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/arm-linux-androideabi-${NDK_TOOLCHAIN_VERSION}/prebuilt/$MYARCH/bin/arm-linux-androideabi-strip --strip-unneeded libs/armeabi-v7a/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ grep "MultiABI=" ../AndroidAppSettings.cfg | grep "all\\|mips" > /dev/null && \ echo Stripping libapplication-mips.so by hand && \ rm obj/local/mips/libapplication.so && \ cp jni/application/src/libapplication-mips.so obj/local/mips/libapplication.so && \ cp jni/application/src/libapplication-mips.so libs/mips/libapplication.so && \ - `which ndk-build | sed 's@/ndk-build@@'`/toolchains/mipsel-linux-android-${GCCVER}/prebuilt/$MYARCH/bin/mipsel-linux-android-strip --strip-unneeded libs/mips/libapplication.so \ - || true ; } && \ - { grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/mipsel-linux-android-${NDK_TOOLCHAIN_VERSION}/prebuilt/$MYARCH/bin/mipsel-linux-android-strip --strip-unneeded libs/mips/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ grep "MultiABI=" ../AndroidAppSettings.cfg | grep "all\\|x86" > /dev/null && \ echo Stripping libapplication-x86.so by hand && \ rm obj/local/x86/libapplication.so && \ cp jni/application/src/libapplication-x86.so obj/local/x86/libapplication.so && \ cp jni/application/src/libapplication-x86.so libs/x86/libapplication.so && \ - `which ndk-build | sed 's@/ndk-build@@'`/toolchains/x86-${GCCVER}/prebuilt/$MYARCH/bin/i686-linux-android-strip --strip-unneeded libs/x86/libapplication.so \ - || true ; } && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/x86-${NDK_TOOLCHAIN_VERSION}/prebuilt/$MYARCH/bin/i686-linux-android-strip --strip-unneeded libs/x86/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + grep "MultiABI=" ../AndroidAppSettings.cfg | grep "all\\|x86_64" > /dev/null && \ + echo Stripping libapplication-x86_64.so by hand && \ + rm obj/local/x86_64/libapplication.so && \ + cp jni/application/src/libapplication-x86_64.so obj/local/x86_64/libapplication.so && \ + cp jni/application/src/libapplication-x86_64.so libs/x86_64/libapplication.so && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/x86_64-4.9/prebuilt/$MYARCH/bin/x86_64-linux-android-strip --strip-unneeded libs/x86_64/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + grep "MultiABI=" ../AndroidAppSettings.cfg | grep "all\\|arm64-v8a" > /dev/null && \ + echo Stripping libapplication-arm64-v8a.so by hand && \ + rm obj/local/arm64-v8a/libapplication.so && \ + cp jni/application/src/libapplication-arm64-v8a.so obj/local/arm64-v8a/libapplication.so && \ + cp jni/application/src/libapplication-arm64-v8a.so libs/arm64-v8a/libapplication.so && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/aarch64-linux-android-4.9/prebuilt/$MYARCH/bin/aarch64-linux-android-strip --strip-unneeded libs/arm64-v8a/libapplication.so + grep "CustomBuildScript=y" ../AndroidAppSettings.cfg > /dev/null && \ + grep "MultiABI=" ../AndroidAppSettings.cfg | grep "all\\|mips64" > /dev/null && \ + echo Stripping libapplication-mips64.so by hand && \ + rm obj/local/mips64/libapplication.so && \ + cp jni/application/src/libapplication-mips64.so obj/local/mips64/libapplication.so && \ + cp jni/application/src/libapplication-mips64.so libs/mips64/libapplication.so && \ + `which ndk-build | sed 's@/ndk-build@@'`/toolchains/mips64el-linux-android-4.9/prebuilt/$MYARCH/bin/mips64el-linux-android-strip --strip-unneeded libs/mips64/libapplication.so + return 0 +} + +cd project && env PATH=$NDKBUILDPATH BUILD_NUM_CPUS=$NCPU nice -n19 ndk-build -j$NCPU V=1 && \ + strip_libs && \ cd .. && ./copyAssets.sh && cd project && \ { if $build_release ; then \ $quick_rebuild && { \ diff --git a/changeAppSettings.sh b/changeAppSettings.sh index 2ed5a9507..f490caa86 100755 --- a/changeAppSettings.sh +++ b/changeAppSettings.sh @@ -127,7 +127,7 @@ echo "# If you'll start Description with '!' symbol it will be enabled by defaul echo "# If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped" >> AndroidAppSettings.cfg echo "# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -" >> AndroidAppSettings.cfg echo "# these files are put inside .apk package by build system" >> AndroidAppSettings.cfg -echo "# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS" >> AndroidAppSettings.cfg +echo "# You can specify Google Play expansion files in the form 'obb:main.12345' or 'obb:patch.12345' where 12345 is the app version, first associated with the file" >> AndroidAppSettings.cfg echo AppDataDownloadUrl=\"$AppDataDownloadUrl\" >> AndroidAppSettings.cfg echo >> AndroidAppSettings.cfg echo "# Reset SDL config when updating application to the new version (y) / (n)" >> AndroidAppSettings.cfg @@ -321,13 +321,16 @@ echo "# Available menu items:" >> AndroidAppSettings.cfg echo "# $MenuOptionsAvailable" >> AndroidAppSettings.cfg echo FirstStartMenuOptions=\'$FirstStartMenuOptions\' >> AndroidAppSettings.cfg echo >> AndroidAppSettings.cfg +echo "# Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower" >> AndroidAppSettings.cfg +echo AppMinimumRAM=$AppMinimumRAM >> AndroidAppSettings.cfg +echo >> AndroidAppSettings.cfg +echo "# GCC version, 4.6 (default) or 4.8, CLANG is not supported yet" >> AndroidAppSettings.cfg +echo NDK_TOOLCHAIN_VERSION=$NDK_TOOLCHAIN_VERSION >> AndroidAppSettings.cfg +echo >> AndroidAppSettings.cfg echo "# Specify architectures to compile, 'all' or 'y' to compile for all architectures." >> AndroidAppSettings.cfg echo "# Available architectures: armeabi armeabi-v7a armeabi-v7a-hard x86 mips" >> AndroidAppSettings.cfg echo MultiABI=\'$MultiABI\' >> AndroidAppSettings.cfg echo >> AndroidAppSettings.cfg -echo "# Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower" >> AndroidAppSettings.cfg -echo AppMinimumRAM=$AppMinimumRAM >> AndroidAppSettings.cfg -echo >> AndroidAppSettings.cfg echo "# Optional shared libraries to compile - removing some of them will save space" >> AndroidAppSettings.cfg echo "# MP3 support by libMAD is encumbered by patents and libMAD is GPL-ed" >> AndroidAppSettings.cfg grep 'Available' project/jni/SettingsTemplate.mk >> AndroidAppSettings.cfg @@ -837,7 +840,8 @@ cat project/jni/SettingsTemplate.mk | \ sed "s^APPLICATION_SUBDIRS_BUILD :=.*^APPLICATION_SUBDIRS_BUILD := $AppSubdirsBuild^" | \ sed "s^APPLICATION_BUILD_EXCLUDE :=.*^APPLICATION_BUILD_EXCLUDE := $AppBuildExclude^" | \ sed "s^APPLICATION_CUSTOM_BUILD_SCRIPT :=.*^APPLICATION_CUSTOM_BUILD_SCRIPT := $CustomBuildScript^" | \ - sed "s^SDL_VERSION :=.*^SDL_VERSION := $LibSdlVersion^" >> \ + sed "s^SDL_VERSION :=.*^SDL_VERSION := $LibSdlVersion^" | \ + sed "s^NDK_TOOLCHAIN_VERSION :=.*^NDK_TOOLCHAIN_VERSION := $NDK_TOOLCHAIN_VERSION^" >> \ project/jni/Settings.mk echo Patching strings.xml @@ -856,6 +860,7 @@ if [ "$GooglePlayGameServicesId" = "n" -o -z "$GooglePlayGameServicesId" ] ; the GooglePlayGameServicesId="" grep 'google-play-services' project/local.properties > /dev/null && { $SEDI 's/.*google-play-services.*//g' project/local.properties + rm -f project/libs/android-support-v4.jar } else for F in $JAVA_SRC_PATH/googleplaygameservices/*.java; do @@ -863,7 +868,6 @@ else echo Patching $F echo '// DO NOT EDIT THIS FILE - it is automatically generated, edit file under $JAVA_SRC_PATH dir' > project/src/$OUT cat $F | sed "s/^package .*;/package $AppFullName;/" >> project/src/$OUT - rm -f project/libs/android-support-v4.jar done $SEDI "s/==GOOGLEPLAYGAMESERVICES_APP_ID==/$GooglePlayGameServicesId/g" project/res/values/strings.xml SDK_DIR=`grep '^sdk.dir' project/local.properties | sed 's/.*=//'` @@ -877,6 +881,8 @@ else android update project -p $SDK_DIR/extras/google/google_play_services/libproject/google-play-services_lib fi +if [ -e project/jni/application/src/project.patch ]; then patch -p1 --no-backup-if-mismatch < project/jni/application/src/project.patch || exit 1 ; fi + echo Cleaning up dependencies rm -rf project/libs/*/* project/gen for OUT in obj; do @@ -887,6 +893,8 @@ rm -rf project/$OUT/local/*/objs*/sdl-*/src/*/android rm -rf project/$OUT/local/*/objs*/sdl-*/src/video/SDL_video.o rm -rf project/$OUT/local/*/objs*/sdl-*/SDL_renderer_gles.o rm -rf project/$OUT/local/*/objs*/sdl_* +rm -rf project/obj/local/*/objs*/lzma/src/XZInputStream.o +rm -rf project/obj/local/*/objs*/liblzma.so # Do not rebuild several huge libraries that do not depend on SDL version for LIB in freetype intl jpeg png lua mad tremor xerces xml2 curl lua mikmod \ boost boost_signals boost_thread boost_filesystem boost_date_time boost_system boost_regex boost_iostreams boost_program_options \ @@ -901,15 +909,6 @@ done rm -rf project/bin/classes rm -rf project/bin/res -rm -rf project/res/drawable-xhdpi/ouya_icon.png project/res/drawable/app_icon.png -if which convert > /dev/null; then - mkdir -p project/res/drawable-xhdpi - convert project/res/drawable/icon.png -resize '732x412!' project/res/drawable-xhdpi/ouya_icon.png - convert project/res/drawable/icon.png -resize '96x96!' project/res/drawable/app_icon.png -else - echo "Install ImageMagick to auto-resize Ouya icon from icon.png" -fi - ./copyAssets.sh || exit 1 rm -rf project/jni/android-support diff --git a/project/AndroidManifestTemplate.xml b/project/AndroidManifestTemplate.xml index 7506b297e..777b44b78 100644 --- a/project/AndroidManifestTemplate.xml +++ b/project/AndroidManifestTemplate.xml @@ -31,7 +31,7 @@ - + diff --git a/project/java/DataDownloader.java b/project/java/DataDownloader.java index 1f1e35fea..c2e16e81a 100644 --- a/project/java/DataDownloader.java +++ b/project/java/DataDownloader.java @@ -55,13 +55,11 @@ import java.io.InputStream; import android.content.Context; import android.content.res.Resources; -import java.lang.String; +import java.util.Arrays; import android.text.SpannedString; import android.app.AlertDialog; import android.content.DialogInterface; -import org.tukaani.xz.XZInputStream; - class CountingInputStream extends BufferedInputStream { @@ -284,22 +282,28 @@ class DataDownloader extends Thread catch( FileNotFoundException e ) {} catch( IOException e ) {}; - HttpResponse response = null, responseError = null; HttpGet request; + HttpResponse response = null, responseError = null; long totalLen = 0; + long partialDownloadLen = 0; CountingInputStream stream; - byte[] buf = new byte[16384]; boolean DoNotUnzip = false; boolean FileInAssets = false; + boolean FileInExpansion = false; String url = ""; - long partialDownloadLen = 0; int downloadUrlIndex = 1; while( downloadUrlIndex < downloadUrls.length ) { Log.i("SDL", "Processing download " + downloadUrls[downloadUrlIndex]); - url = new String(downloadUrls[downloadUrlIndex]); + DoNotUnzip = false; + FileInAssets = false; + FileInExpansion = false; + partialDownloadLen = 0; + totalLen = 0; + + url = new String(downloadUrls[downloadUrlIndex]); if(url.indexOf(":") == 0) { path = getOutFilePath(url.substring( 1, url.indexOf(":", 1) )); @@ -311,7 +315,26 @@ class DataDownloader extends Thread partialDownloadLen = partialDownload.length(); } Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.connecting_to, url) ); - if( url.indexOf("http://") == -1 && url.indexOf("https://") == -1 ) // File inside assets + if( url.indexOf("obb:") == 0 ) // APK expansion file provided by Google Play + { + url = url.substring("obb:".length()); + url = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/obb/" + + Parent.getPackageName() + "/" + url + "." + Parent.getPackageName() + ".obb"; + InputStream stream1 = null; + try { + stream1 = new FileInputStream(url); + stream1.read(); + stream1.close(); + Log.i("SDL", "Fetching file from expansion: " + url); + FileInExpansion = true; + break; + } catch( Exception e ) { + Log.i("SDL", "Failed to open file: " + url); + downloadUrlIndex++; + continue; + } + } + else if( url.indexOf("http://") == -1 && url.indexOf("https://") == -1 ) // File inside assets { InputStream stream1 = null; try { @@ -346,7 +369,6 @@ class DataDownloader extends Thread response = client.execute(request); } catch (IOException e) { Log.i("SDL", "Failed to connect to " + url); - downloadUrlIndex++; }; if( response != null ) { @@ -356,13 +378,32 @@ class DataDownloader extends Thread responseError = response; response = null; downloadUrlIndex++; + continue; } - else - break; + break; + } + else + { + downloadUrlIndex++; + continue; } } } - if( FileInAssets ) + + if( FileInExpansion ) + { + Log.i("SDL", "Count file size: '" + url); + try { + totalLen = new File(url).length(); + stream = new CountingInputStream(new FileInputStream(url), 8192); + Log.i("SDL", "Count file size: '" + url + " = " + totalLen); + } catch( IOException e ) { + Log.i("SDL", "Unpacking from filesystem '" + url + "' - error: " + e.toString()); + Status.setText( res.getString(R.string.error_dl_from, url) ); + return false; + } + } + else if( FileInAssets ) { int multipartCounter = 0; InputStream multipart = null; @@ -393,7 +434,7 @@ class DataDownloader extends Thread try { stream = new CountingInputStream(Parent.getAssets().open(url), 8192); while( stream.skip(65536) > 0 ) { }; - totalLen += stream.getBytesRead(); + totalLen = stream.getBytesRead(); stream.close(); stream = new CountingInputStream(Parent.getAssets().open(url), 8192); } catch( IOException e ) { @@ -421,9 +462,49 @@ class DataDownloader extends Thread return false; } } - + + if( !copyUnpackFileStream(stream, path, url, DoNotUnzip, FileInAssets, FileInExpansion, totalLen, partialDownloadLen, response, downloadCount, downloadTotal) ) + return false; + + OutputStream out = null; + path = getOutFilePath(DownloadFlagFileName); + try { + out = new FileOutputStream( path ); + out.write(downloadUrls[downloadUrlIndex].getBytes("UTF-8")); + out.flush(); + out.close(); + } catch( java.io.IOException e ) { + Status.setText( res.getString(R.string.error_write, path) + ": " + e.getMessage() ); + return false; + }; + Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.dl_finished) ); + + try { + stream.close(); + if( FileInExpansion ) + { + Writer writer = new OutputStreamWriter(new FileOutputStream(url), "UTF-8"); + writer.write("Extracted and truncated\n"); + writer.close(); + Log.i("SDL", "Truncated file from expansion: " + url); + } + } catch( java.io.IOException e ) { + Log.i("SDL", "Error truncating file from expansion: " + url); + }; + + return true; + }; + + // Moved part of code to a separate method, because Android imposes a stupid limit on Java method size + private boolean copyUnpackFileStream( CountingInputStream stream, String path, String url, + boolean DoNotUnzip, boolean FileInAssets, boolean FileInExpansion, + long totalLen, long partialDownloadLen, HttpResponse response, + int downloadCount, int downloadTotal) + { long updateStatusTime = 0; - + byte[] buf = new byte[16384]; + Resources res = Parent.getResources(); + if(DoNotUnzip) { Log.i("SDL", "Saving file '" + path + "'"); @@ -504,6 +585,8 @@ class DataDownloader extends Thread if (url.endsWith(".zip.xz") || url.endsWith(".zip.xz/download")) try { + if (!Arrays.asList(Globals.AppLibraries).contains("lzma")) + throw new IOException("LZMA support not compiled in - add lzma to CompiledLibraries inside AndroidAppSettings.cfg"); zip = new ZipInputStream(new XZInputStream(stream)); } catch (Exception eeeee) @@ -651,30 +734,9 @@ class DataDownloader extends Thread Log.i("SDL", "Saving file '" + path + "' done"); } }; - - OutputStream out = null; - path = getOutFilePath(DownloadFlagFileName); - try { - out = new FileOutputStream( path ); - out.write(downloadUrls[downloadUrlIndex].getBytes("UTF-8")); - out.flush(); - out.close(); - } catch( FileNotFoundException e ) { - } catch( SecurityException e ) { - } catch( java.io.IOException e ) { - Status.setText( res.getString(R.string.error_write, path) + ": " + e.getMessage() ); - return false; - }; - Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.dl_finished) ); - - try { - stream.close(); - } catch( java.io.IOException e ) { - }; - return true; - }; - + } + private void initParent() { class Callback implements Runnable diff --git a/project/java/GLSurfaceView_SDL.java b/project/java/GLSurfaceView_SDL.java index af7ccbd20..e079b8c9a 100644 --- a/project/java/GLSurfaceView_SDL.java +++ b/project/java/GLSurfaceView_SDL.java @@ -32,6 +32,8 @@ import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; +import android.opengl.EGL14; // Android 4.2 or newer + import android.content.Context; import android.util.AttributeSet; import android.util.Log; @@ -919,7 +921,6 @@ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Call mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); - GL gl = mEglContext.getGL(); if (mGLWrapper != null) { gl = mGLWrapper.wrap(gl); diff --git a/project/java/Globals.java b/project/java/Globals.java index 4bb21aa8b..8943b18ad 100644 --- a/project/java/Globals.java +++ b/project/java/Globals.java @@ -80,7 +80,6 @@ class Globals public static boolean HorizontalOrientation = true; public static boolean ImmersiveMode = true; public static boolean DownloadToSdcard = true; - public static boolean PhoneHasTrackball = false; public static boolean PhoneHasArrowKeys = false; public static boolean UseAccelerometerAsArrowKeys = false; public static boolean UseTouchscreenKeyboard = true; @@ -92,7 +91,6 @@ class Globals public static boolean FloatingScreenJoystick = false; public static int AccelerometerSensitivity = 2; public static int AccelerometerCenterPos = 2; - public static int TrackballDampening = 0; public static int AudioBufferConfig = 0; public static boolean OptionalDataDownload[] = null; public static int LeftClickMethod = ForceRelativeMouseMode ? Mouse.LEFT_CLICK_WITH_TAP_OR_TIMEOUT : Mouse.LEFT_CLICK_NORMAL; diff --git a/project/java/Settings.java b/project/java/Settings.java index 5d83abf81..12af4bb89 100644 --- a/project/java/Settings.java +++ b/project/java/Settings.java @@ -92,13 +92,13 @@ class Settings out.writeInt(SETTINGS_FILE_VERSION); out.writeBoolean(Globals.DownloadToSdcard); out.writeBoolean(Globals.PhoneHasArrowKeys); - out.writeBoolean(Globals.PhoneHasTrackball); + out.writeBoolean(false); out.writeBoolean(Globals.UseAccelerometerAsArrowKeys); out.writeBoolean(Globals.UseTouchscreenKeyboard); out.writeInt(Globals.TouchscreenKeyboardSize); out.writeInt(Globals.AccelerometerSensitivity); out.writeInt(Globals.AccelerometerCenterPos); - out.writeInt(Globals.TrackballDampening); + out.writeInt(0); out.writeInt(Globals.AudioBufferConfig); out.writeInt(Globals.TouchscreenKeyboardTheme); out.writeInt(Globals.RightClickMethod); @@ -274,13 +274,13 @@ class Settings throw new IOException(); Globals.DownloadToSdcard = settingsFile.readBoolean(); Globals.PhoneHasArrowKeys = settingsFile.readBoolean(); - Globals.PhoneHasTrackball = settingsFile.readBoolean(); + settingsFile.readBoolean(); Globals.UseAccelerometerAsArrowKeys = settingsFile.readBoolean(); Globals.UseTouchscreenKeyboard = settingsFile.readBoolean(); Globals.TouchscreenKeyboardSize = settingsFile.readInt(); Globals.AccelerometerSensitivity = settingsFile.readInt(); Globals.AccelerometerCenterPos = settingsFile.readInt(); - Globals.TrackballDampening = settingsFile.readInt(); + settingsFile.readInt(); Globals.AudioBufferConfig = settingsFile.readInt(); Globals.TouchscreenKeyboardTheme = settingsFile.readInt(); Globals.RightClickMethod = settingsFile.readInt(); @@ -546,8 +546,6 @@ class Settings nativeSetVideoForceSoftwareMode(); if( Globals.SwVideoMode && Globals.MultiThreadedVideo ) nativeSetVideoMultithreaded(); - if( Globals.PhoneHasTrackball ) - nativeSetTrackballUsed(); applyMouseEmulationOptions(); nativeSetJoystickUsed( Globals.AppUsesThirdJoystick ? 3 : (Globals.AppUsesSecondJoystick ? 2 : (Globals.AppUsesJoystick ? 1 : 0)) ); if( Globals.AppUsesAccelerometer ) @@ -555,7 +553,6 @@ class Settings if( Globals.AppUsesMultitouch ) nativeSetMultitouchUsed(); nativeSetAccelerometerSettings(Globals.AccelerometerSensitivity, Globals.AccelerometerCenterPos); - nativeSetTrackballDampening(Globals.TrackballDampening); if( Globals.UseTouchscreenKeyboard ) { boolean screenKbReallyUsed = false; @@ -856,8 +853,6 @@ class Settings return true; } - private static native void nativeSetTrackballUsed(); - private static native void nativeSetTrackballDampening(int value); private static native void nativeSetAccelerometerSettings(int sensitivity, int centerPos); private static native void nativeSetMouseUsed(int RightClickMethod, int ShowScreenUnderFinger, int LeftClickMethod, int MoveMouseWithJoystick, int ClickMouseWithDpad, int MaxForce, int MaxRadius, diff --git a/project/java/Video.java b/project/java/Video.java index 52318e1a4..b7733aef1 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -123,8 +123,6 @@ abstract class DifferentTouchInput Log.i("SDL", "Device board: " + android.os.Build.BOARD); if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH ) { - if( DetectCrappyDragonRiseDatexGamepad() ) - return CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad.Holder.sInstance; //return IcsTouchInput.Holder.sInstance; return AutoDetectTouchInput.Holder.sInstance; } @@ -145,12 +143,6 @@ abstract class DifferentTouchInput } } } - private static boolean DetectCrappyDragonRiseDatexGamepad() - { - if( CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad.Holder.sInstance == null ) - return false; - return CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad.Holder.sInstance.detect(); - } private static class SingleTouchInput extends DifferentTouchInput { @@ -388,10 +380,6 @@ abstract class DifferentTouchInput // Joysticks are supported since Honeycomb, but I don't care about it, because very little devices have it if( (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK ) { - DemoGLSurfaceView.nativeGamepadAnalogJoystickInput( - event.getAxisValue(MotionEvent.AXIS_X), event.getAxisValue(MotionEvent.AXIS_Y), - event.getAxisValue(MotionEvent.AXIS_Z), event.getAxisValue(MotionEvent.AXIS_RZ), - event.getAxisValue(MotionEvent.AXIS_RTRIGGER), event.getAxisValue(MotionEvent.AXIS_LTRIGGER) ); // event.getAxisValue(AXIS_HAT_X) and event.getAxisValue(AXIS_HAT_Y) are joystick arrow keys, on Nvidia Shield and some other joysticks if( event.getAxisValue(MotionEvent.AXIS_HAT_X) != hatX ) { @@ -415,6 +403,11 @@ abstract class DifferentTouchInput else DemoGLSurfaceView.nativeKey(hatY < 0.0f ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN, 1, 0); } + DemoGLSurfaceView.nativeGamepadAnalogJoystickInput( + event.getAxisValue(MotionEvent.AXIS_X), event.getAxisValue(MotionEvent.AXIS_Y), + event.getAxisValue(MotionEvent.AXIS_Z), event.getAxisValue(MotionEvent.AXIS_RZ), + event.getAxisValue(MotionEvent.AXIS_RTRIGGER), event.getAxisValue(MotionEvent.AXIS_LTRIGGER), + (hatX == 0.0f && hatY == 0.0f) ? 0 : 1 ); return; } // Process mousewheel @@ -454,36 +447,6 @@ abstract class DifferentTouchInput super.process(event); } } - private static class CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad extends IcsTouchInput - { - private static class Holder - { - private static final CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad sInstance = new CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad(); - } - public void processGenericEvent(final MotionEvent event) - { - super.processGenericEvent(event); - } - public boolean detect() - { - int[] devIds = InputDevice.getDeviceIds(); - for( int id : devIds ) - { - InputDevice device = InputDevice.getDevice(id); - if( device == null ) - continue; - System.out.println("libSDL: input device ID " + id + " type " + device.getSources() + " name " + device.getName() ); - if( (device.getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD && - (device.getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && - device.getName().indexOf("DragonRise Inc") == 0 ) - { - System.out.println("libSDL: Detected crappy DragonRise gamepad, enabling special hack for it. Please press button labeled 'Analog', otherwise it won't work, because it's cheap and crappy"); - return true; - } - } - return false; - } - } private static class CrappyMtkTabletWithBrokenTouchDrivers extends IcsTouchInput { private static class Holder @@ -1073,7 +1036,7 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { public static native void nativeHardwareMouseDetected( int detected ); public static native void nativeMouseButtonsPressed( int buttonId, int pressedState ); public static native void nativeMouseWheel( int scrollX, int scrollY ); - public static native void nativeGamepadAnalogJoystickInput( float stick1x, float stick1y, float stick2x, float stick2y, float rtrigger, float ltrigger ); + public static native void nativeGamepadAnalogJoystickInput( float stick1x, float stick1y, float stick2x, float stick2y, float rtrigger, float ltrigger, int usingHat ); } diff --git a/project/java/XZInputStream.java b/project/java/XZInputStream.java new file mode 100644 index 000000000..2563a190e --- /dev/null +++ b/project/java/XZInputStream.java @@ -0,0 +1,160 @@ +/* +Simple DirectMedia Layer +Java source code (C) 2009-2014 Sergii Pylypenko + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +package net.sourceforge.clonekeenplus; + +import java.io.InputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.EOFException; +import android.util.Log; + +/** + * Decompresses a .xz file in streamed mode (no seeking). + * This is a copy of code from http://git.tukaani.org/xz-java.git + * but using liblzma and JNI instead of Java, because Java heap + * is very limited, and we're hitting memory limit on emulator. + */ +public class XZInputStream extends InputStream +{ + private long nativeData = 0; + private InputStream in = null; + private final byte[] inBuf = new byte[8192]; + private int inOffset = 0; + private int inAvailable = 0; + private boolean outBufEof = false; + private int offsets[] = new int[2]; + + private final byte[] tempBuf = new byte[1]; + + public XZInputStream(InputStream in) throws IOException + { + this.in = in; + if (in == null) + { + throw new NullPointerException("InputStream == null"); + } + nativeData = nativeInit(); + if (nativeData == 0) + { + throw new OutOfMemoryError("Cannot initialize JNI liblzma object"); + } + } + + @Override + public int available() throws IOException + { + return 0; // Don't care + } + + @Override + public void close() throws IOException + { + synchronized (this) + { + if (nativeData != 0) + nativeClose(nativeData); + nativeData = 0; + if (in != null) + { + try { + in.close(); + } finally { + in = null; + } + } + } + } + + @Override + protected void finalize() throws IOException + { + try { + close(); + } finally { + try { + super.finalize(); + } catch (Throwable t) { + throw new AssertionError(t); + } + } + } + + @Override + public int read() throws IOException + { + return read(tempBuf, 0, 1) == -1 ? -1 : (tempBuf[0] & 0xFF); + } + + @Override + public int read(byte[] outBuf, int outOffset, int outCount) throws IOException + { + //Log.i("SDL", "XZInputStream.read: outOffset " + outOffset + " outCount " + outCount + " outBufEof " + outBufEof + + // " inOffset " + inOffset + " inAvailable " + inAvailable); + if (outBufEof) + return -1; + if (outCount <= 0) + return 0; + + int oldOutOffset = outOffset; + + if (inOffset >= inAvailable && inAvailable != -1) + { + inAvailable = in.read(inBuf, 0, inBuf.length); + inOffset = 0; + //Log.i("SDL", "XZInputStream.read: in.read: inOffset " + inOffset + " inAvailable " + inAvailable); + } + + offsets[0] = inOffset; + offsets[1] = outOffset; + int ret = nativeRead(nativeData, inBuf, inAvailable, outBuf, outCount, offsets); + inOffset = offsets[0]; + outOffset = offsets[1]; + //Log.i("SDL", "XZInputStream.read: nativeRead: outOffset " + outOffset + " outCount " + outCount + " outBufEof " + outBufEof + + // " inOffset " + inOffset + " inAvailable " + inAvailable + " ret " + ret); + + if (ret != 0) + { + if (ret == 1) + { + if (inOffset < inAvailable) + throw new IOException("Garbage at the end of LZMA stream"); + if (inAvailable != -1) + inAvailable = in.read(inBuf, 0, inBuf.length); + if (inAvailable != -1) + throw new IOException("Garbage at the end of LZMA stream"); + outBufEof = true; + } + else + { + throw new IOException("LZMA error " + ret); + } + } + + //Log.i("SDL", "XZInputStream.read: returning " + (outOffset - oldOutOffset)); + return outOffset - oldOutOffset; + } + + private native long nativeInit(); + private native void nativeClose(long nativeData); + private native int nativeRead(long nativeData, byte[] inBuf, int inAvailable, byte[] outBuf, int outCount, int[] offsets); +} + diff --git a/project/jni/Application.mk b/project/jni/Application.mk index dd4e6b12f..ea9e2e0ee 100644 --- a/project/jni/Application.mk +++ b/project/jni/Application.mk @@ -6,13 +6,3 @@ APP_STL := gnustl_static APP_CFLAGS := -O3 -DNDEBUG -g # arm-linux-androideabi-4.4.3 crashes in -O0 mode on SDL sources APP_PLATFORM := android-14 # Android 4.0, it should be backward compatible to previous versions APP_PIE := false # This feature makes executables incompatible to Android API 15 or lower - -# Global compiler flags -ifneq ($(filter armeabi-v7a-hard, $(APP_ABI)),) -# Link-time optimization enabled for optimization junkies. -O999 etc -#APP_CFLAGS := -flto -#APP_CXXFLAGS := -flto -#APP_LDFLAGS := -flto -# Latest GCC got better LTO support -#NDK_TOOLCHAIN_VERSION := 4.8 -endif diff --git a/project/jni/SettingsTemplate.mk b/project/jni/SettingsTemplate.mk index a6e724b75..5669a5f28 100644 --- a/project/jni/SettingsTemplate.mk +++ b/project/jni/SettingsTemplate.mk @@ -46,3 +46,9 @@ SDL_ADDITIONAL_CFLAGS := -DSDL_ANDROID_KEYCODE_MOUSE=UNKNOWN -DSDL_ANDROID_KEYCO SDL_VERSION := 1.2 +# Link-time optimization enabled for optimization junkies. -O999 etc +#APP_CFLAGS := -flto +#APP_CXXFLAGS := -flto +#APP_LDFLAGS := -flto +# Latest GCC got better LTO support +NDK_TOOLCHAIN_VERSION := 4.6 diff --git a/project/jni/application/ballfield/AndroidAppSettings.cfg b/project/jni/application/ballfield/AndroidAppSettings.cfg index 2deffa62a..eef046bfd 100644 --- a/project/jni/application/ballfield/AndroidAppSettings.cfg +++ b/project/jni/application/ballfield/AndroidAppSettings.cfg @@ -213,7 +213,7 @@ FirstStartMenuOptions='SettingsMenu.DummyMenu' # Specify architectures to compile, 'all' or 'y' to compile for all architectures. # Available architectures: armeabi armeabi-v7a armeabi-v7a-hard x86 mips -MultiABI='armeabi-v7a' +MultiABI='armeabi-v7a armeabi' # Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower AppMinimumRAM=0 @@ -221,7 +221,7 @@ AppMinimumRAM=0 # Optional shared libraries to compile - removing some of them will save space # MP3 support by libMAD is encumbered by patents and libMAD is GPL-ed # Available libraries: mad (GPL-ed!) sdl_mixer sdl_image sdl_ttf sdl_net sdl_blitpool sdl_gfx sdl_sound intl xml2 lua jpeg png ogg flac tremor vorbis freetype xerces curl theora fluidsynth lzma lzo2 mikmod openal timidity zzip bzip2 yaml-cpp python boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread glu avcodec avdevice avfilter avformat avresample avutil swscale swresample bzip2 -CompiledLibraries="sdl_image android_support" +CompiledLibraries="sdl_image" # Application uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n) CustomBuildScript=n diff --git a/project/jni/application/ballfield/ballfield.cpp b/project/jni/application/ballfield/ballfield.cpp index 578feda0b..d4feed749 100644 --- a/project/jni/application/ballfield/ballfield.cpp +++ b/project/jni/application/ballfield/ballfield.cpp @@ -445,6 +445,7 @@ int main(int argc, char* argv[]) SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); SDL_Joystick * joysticks[6]; for( i = 0; i < 6; i++ ) joysticks[i] = SDL_JoystickOpen(i); @@ -555,6 +556,7 @@ int main(int argc, char* argv[]) memset(gamepads, 0, sizeof(gamepads)); __android_log_print(ANDROID_LOG_INFO, "Ballfield", "sizeof(int) %d long %d long long %d size_t %d", sizeof(int), sizeof(long), sizeof(long long), sizeof(size_t)); + /* wchar_t ss[256]; const wchar_t *ss2 = L"String 2 ЕНГ ---"; swprintf(ss, 256, L"String ЙЦУК --- %ls", ss2); @@ -568,6 +570,7 @@ int main(int argc, char* argv[]) sprintf(ss4, "%ls", ss); } __android_log_print(ANDROID_LOG_VERBOSE, "Ballfield", "swprintf: len %d data %s: %s", wcslen(ss), ss3, ss4); + */ __android_log_print(ANDROID_LOG_VERBOSE, "Ballfield", "On-screen buttons:"); for(i = 0; i < SDL_ANDROID_SCREENKEYBOARD_BUTTON_NUM; i++) @@ -746,6 +749,14 @@ int main(int argc, char* argv[]) x_speed = 500.0 * sin(t * 0.37); y_speed = 500.0 * sin(t * 0.53); z_speed = 400.0 * sin(t * 0.21); + if( SDL_GetKeyState(NULL)[SDLK_LEFT] ) + x_speed -= 100000 * dt; + if( SDL_GetKeyState(NULL)[SDLK_RIGHT] ) + x_speed += 100000 * dt; + if( SDL_GetKeyState(NULL)[SDLK_UP] ) + y_speed -= 100000 * dt; + if( SDL_GetKeyState(NULL)[SDLK_DOWN] ) + y_speed += 100000 * dt; ballfield_move(balls, x_speed, y_speed, z_speed); x_offs -= x_speed; diff --git a/project/jni/application/guichan-widgets/AndroidAppSettings.cfg b/project/jni/application/guichan-widgets/AndroidAppSettings.cfg index d80c938de..9eed1b81a 100644 --- a/project/jni/application/guichan-widgets/AndroidAppSettings.cfg +++ b/project/jni/application/guichan-widgets/AndroidAppSettings.cfg @@ -23,7 +23,7 @@ InhibitSuspend=n # If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir - # these files are put inside .apk package by build system # Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS -AppDataDownloadUrl="data file|files.zip" +AppDataDownloadUrl="!!data file|files.zip" # Video color depth - 16 BPP is the fastest and supported for all modes, 24 bpp is supported only # with SwVideoMode=y, SDL_OPENGL mode supports everything. (16)/(24)/(32) @@ -161,7 +161,7 @@ StartupMenuButtonTimeout=3000 # Menu items to hide from startup menu, available menu items: # SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout -HiddenMenuOptions='' +HiddenMenuOptions='SettingsMenuMisc.OptionalDownloadConfig' # Menu items to show at startup - this is Java code snippet, leave empty for default # new SettingsMenuMisc.ShowReadme(), (AppUsesMouse \&\& \! ForceRelativeMouseMode \? new SettingsMenuMouse.DisplaySizeConfig(true) : new SettingsMenu.DummyMenu()), new SettingsMenuMisc.OptionalDownloadConfig(true), new SettingsMenuMisc.GyroscopeCalibration() @@ -171,7 +171,7 @@ FirstStartMenuOptions='' # Enable multi-ABI binary, with hardware FPU support - it will also work on old devices, # but .apk size is 2x bigger (y) / (n) / (x86) / (all) -MultiABI=all +MultiABI='armeabi-v7a' # Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower AppMinimumRAM=256 @@ -191,7 +191,7 @@ DeleteFilesOnUpgrade="%" # Optional shared libraries to compile - removing some of them will save space # MP3 support by libMAD is encumbered by patents and libMAD is GPL-ed # Available libraries: mad (GPL-ed!) sdl_mixer sdl_image sdl_ttf sdl_net sdl_blitpool sdl_gfx sdl_sound intl xml2 lua jpeg png ogg flac tremor vorbis freetype xerces curl theora fluidsynth lzma lzo2 mikmod openal timidity zzip bzip2 yaml-cpp python boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread glu avcodec avdevice avfilter avformat avresample avutil swscale swresample bzip2 -CompiledLibraries="sdl_image guichan" +CompiledLibraries="sdl_image sdl_ttf guichan" # Application uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n) CustomBuildScript=n diff --git a/project/jni/application/guichan-widgets/AndroidData/files.zip b/project/jni/application/guichan-widgets/AndroidData/files.zip index 314551ebb..64ef108dc 100644 Binary files a/project/jni/application/guichan-widgets/AndroidData/files.zip and b/project/jni/application/guichan-widgets/AndroidData/files.zip differ diff --git a/project/jni/application/guichan-widgets/gui.xml b/project/jni/application/guichan-widgets/gui.xml index 8514f2f4e..39c783775 100644 --- a/project/jni/application/guichan-widgets/gui.xml +++ b/project/jni/application/guichan-widgets/gui.xml @@ -1,23 +1,23 @@ - -