diff options
Diffstat (limited to 'build/android')
19 files changed, 1925 insertions, 0 deletions
diff --git a/build/android/AndroidManifest.xml.template b/build/android/AndroidManifest.xml.template new file mode 100644 index 000000000..dcffa35f6 --- /dev/null +++ b/build/android/AndroidManifest.xml.template @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.minetest.minetest" + android:versionCode="###ANDROID_VERSION###" + android:versionName="###BASE_VERSION###.###ANDROID_VERSION###" + android:installLocation="auto"> + <uses-sdk android:minSdkVersion="9"/> + <uses-feature android:glEsVersion="0x00010000" android:required="true"/> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + ###DEBUG_BUILD### + <application android:icon="@drawable/irr_icon" android:label="Minetest" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ###DEBUG_FLAG###> + <activity android:name=".MtNativeActivity" + android:label="Minetest" + android:launchMode="singleTask" + android:configChanges="orientation|keyboardHidden" + android:screenOrientation="landscape" + android:clearTaskOnLaunch="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <meta-data android:name="android.app.lib_name" android:value="minetest" /> + </activity> + <activity android:name=".MinetestTextEntry" + android:theme="@style/Theme.Transparent" + android:excludeFromRecents="true"> + </activity> + <activity android:name=".MinetestAssetCopy" + android:theme="@style/Theme.Transparent" + android:excludeFromRecents="true"> + </activity> + </application> +</manifest> diff --git a/build/android/Makefile b/build/android/Makefile new file mode 100644 index 000000000..9e693432b --- /dev/null +++ b/build/android/Makefile @@ -0,0 +1,724 @@ +# build options + +OS := $(shell uname) + +#automaticaly set number of jobs +ifeq ($(OS),Linux) + PARALLEL := $(shell grep -c ^processor /proc/cpuinfo) +else + PARALLEL := 1 +endif + +# compile with GPROF +# GPROF = 1 + +# build for build platform +APP_PLATFORM = android-9 + +# paths used for timestaps, dependencys, tree config and libs +PATHCFGFILE = path.cfg + +ROOT = $(shell pwd) + +################################################################################ +# Android Version code +# Increase for each build! +################################################################################ +ANDROID_VERSION_CODE = 3 + +################################################################################ +# toolchain config for arm old processors +################################################################################ +TARGET_HOST = arm-linux +TARGET_ABI = armeabi +TARGET_LIBDIR = armeabi +TARGET_TOOLCHAIN = arm-linux-androideabi- +TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfp +CROSS_PREFIX = arm-linux-androideabi- +COMPILER_VERSION = 4.8 + +################################################################################ +# toolchain config for arm new processors +################################################################################ +#TARGET_HOST = arm-linux +#TARGET_ABI = armeabi-v7a-hard +#TARGET_LIBDIR = armeabi-v7a +#TARGET_TOOLCHAIN = arm-linux-androideabi- +#TARGET_CFLAGS_ADDON = -mfpu=vfpv3-d16 -D_NDK_MATH_NO_SOFTFP=1 \ +# -mfloat-abi=hard -march=armv7-a +#TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON) +#TARGET_LDFLAGS_ADDON = -Wl,--no-warn-mismatch -lm_hard +#CROSS_PREFIX = arm-linux-androideabi- +#COMPILER_VERSION = 4.8 + +################################################################################ +# toolchain config for little endian mips +################################################################################ +#TARGET_HOST = mipsel-linux +#TARGET_ABI = mips +#TARGET_LIBDIR = mips +#TARGET_TOOLCHAIN = mipsel-linux-android- +#CROSS_PREFIX = mipsel-linux-android- +#COMPILER_VERSION = 4.8 + +################################################################################ +# toolchain config for x86 +################################################################################ +#TARGET_HOST = x86-linux +#TARGET_ABI = x86 +#TARGET_LIBDIR = x86 +#TARGET_TOOLCHAIN = x86- +#CROSS_PREFIX = i686-linux-android- +#COMPILER_VERSION = 4.8 + +################################################################################ +ASSETS_TIMESTAMP = deps/assets_timestamp + +LEVELDB_DIR = $(ROOT)/deps/leveldb/ +LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a +LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp +LEVELDB_TIMESTAMP_INT = $(ROOT)/deps/leveldb_timestamp +LEVELDB_URL_GIT = https://code.google.com/p/leveldb/ + +OPENAL_DIR = $(ROOT)/deps/openal-soft/ +OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so +OPENAL_TIMESTAMP = $(OPENAL_DIR)/timestamp +OPENAL_TIMESTAMP_INT = $(ROOT)/deps/openal_timestamp +OPENAL_URL_GIT = https://github.com/apportable/openal-soft + +OGG_DIR = $(ROOT)/deps/libvorbis-libogg-android/ +OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so +VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so +OGG_TIMESTAMP = $(OGG_DIR)timestamp +OGG_TIMESTAMP_INT = $(ROOT)/deps/ogg_timestamp +OGG_URL_GIT = https://github.com/vincentjames501/libvorbis-libogg-android + +IRRLICHT_DIR = $(ROOT)/deps/irrlicht/ +IRRLICHT_LIB = $(IRRLICHT_DIR)lib/Android/libIrrlicht.a +IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)timestamp +IRRLICHT_TIMESTAMP_INT = $(ROOT)/deps/irrlicht_timestamp +IRRLICHT_URL_SVN = http://svn.code.sf.net/p/irrlicht/code/branches/ogl-es/ + +OPENSSL_BASEDIR = openssl-android +OPENSSL_DIR = $(ROOT)/deps/$(OPENSSL_BASEDIR)/ +OPENSSL_LIB = $(OPENSSL_DIR)libs/$(TARGET_ABI)/libopenssl.so +OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp +OPENSSL_TIMESTAMP_INT = $(ROOT)/deps/openssl_timestamp +OPENSSL_URL_GIT = https://github.com/wobbals/openssl-android + +CURL_VERSION = 7.35.0 +CURL_DIR = $(ROOT)/deps/curl-$(CURL_VERSION) +CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a +CURL_TIMESTAMP = $(CURL_DIR)/timestamp +CURL_TIMESTAMP_INT = $(ROOT)/deps/curl_timestamp +CURL_URL_HTTP = http://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2 + +FREETYPE_DIR = $(ROOT)/deps/freetype2-android/ +FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGER_ABI)/libfreetype2-static.a +FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp +FREETYPE_TIMESTAMP_INT = $(ROOT)/deps/freetype_timestamp +FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android + +-include $(PATHCFGFILE) + +.PHONY : debug release reconfig delconfig \ + leveldb_download clean_leveldb leveldb\ + irrlicht_download clean_irrlicht irrlicht \ + clean_assets assets \ + freetype_download clean_freetype freetype \ + apk clean_apk \ + clean_all clean prep_srcdir \ + install_debug install envpaths all \ + manifest clean_manifest\ + $(ASSETS_TIMESTAMP) $(LEVELDB_TIMESTAMP) \ + $(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \ + $(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \ + $(OPENSSL_TIMESTAMP) curl_binary \ + $(ROOT)/jni/src/android_version.h + +debug : $(PATHCFGFILE) + export NDEBUG=; \ + export BUILD_TYPE=debug; \ + $(MAKE) -j${PARALLEL} apk + +all : debug release + +release : $(PATHCFGFILE) + @export NDEBUG=1; \ + export BUILD_TYPE=release; \ + $(MAKE) -j${PARALLEL} apk + +reconfig: delconfig + @$(MAKE) -j${PARALLEL} $(PATHCFGFILE) + +delconfig : + $(RM) ${PATHCFGFILE} + +$(PATHCFGFILE) : + @echo "Please specify path of ANDROID NDK"; \ + echo "e.g. /home/user/android-ndk-r9c/"; \ + read ANDROID_NDK ; \ + if [ ! -d $$ANDROID_NDK ] ; then \ + echo "$$ANDROID_NDK is not a valid folder"; \ + exit 1; \ + fi; \ + echo "ANDROID_NDK = $$ANDROID_NDK" > ${PATHCFGFILE}; \ + echo "NDK_MODULE_PATH = $$ANDROID_NDK/tools" >> ${PATHCFGFILE}; \ + echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\ + echo "+ Note: NDK_MODULE_PATH is set to $$ANDROID_NDK/tools"; \ + echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\ + echo "Please specify path of ANDROID SDK"; \ + echo "e.g. /home/user/adt-bundle-linux-x86_64-20131030/sdk/"; \ + read SDKFLDR ; \ + if [ ! -d $$SDKFLDR ] ; then \ + echo "$$SDKFLDR is not a valid folder"; \ + exit 1; \ + fi; \ + echo "SDKFOLDER = $$SDKFLDR" >> ${PATHCFGFILE}; + +$(OPENAL_TIMESTAMP) : openal_download + @LAST_MODIF=$$(find ${OPENAL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${OPENAL_TIMESTAMP}; \ + fi + +openal_download : + @if [ ! -d ${OPENAL_DIR} ] ; then \ + echo "openal sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${OPENAL_URL_GIT} || exit 1; \ + fi + +openal : $(OPENAL_LIB) + +$(OPENAL_LIB): $(OPENAL_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${OPENAL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${OPENAL_TIMESTAMP} -nt ${OPENAL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for openal detected building..."; \ + cd ${OPENAL_DIR}; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${OPENAL_TIMESTAMP}; \ + touch ${OPENAL_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for openal"; \ + fi + +clean_openal : + $(RM) -rf ${OPENAL_DIR} + +$(OGG_TIMESTAMP) : ogg_download + @LAST_MODIF=$$(find ${OGG_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${OGG_TIMESTAMP}; \ + fi + +ogg_download : + @if [ ! -d ${OGG_DIR} ] ; then \ + echo "ogg sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${OGG_URL_GIT}|| exit 1; \ + cd libvorbis-libogg-android ; \ + patch -p1 < ../../libvorbis-libogg-fpu.patch || exit 1; \ + fi + +ogg : $(OGG_LIB) + +$(OGG_LIB): $(OGG_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${OGG_TIMESTAMP_INT} ] ; then \ + echo "${OGG_TIMESTAMP_INT} doesn't exist"; \ + REFRESH=1; \ + fi; \ + if [ ${OGG_TIMESTAMP} -nt ${OGG_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for ogg detected building..."; \ + cd ${OGG_DIR}; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${OGG_TIMESTAMP}; \ + touch ${OGG_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for libogg/libvorbis"; \ + fi + +clean_ogg : + $(RM) -rf ${OGG_DIR} + +$(OPENSSL_TIMESTAMP) : openssl_download + @LAST_MODIF=$$(find ${OPENSSL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${OPENSSL_TIMESTAMP}; \ + fi + +openssl_download : + @if [ ! -d ${OPENSSL_DIR} ] ; then \ + echo "openssl sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${OPENSSL_URL_GIT} || exit 1; \ + fi + +openssl : $(OPENSSL_LIB) + +$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \ + echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \ + REFRESH=1; \ + fi; \ + if [ ${OPENSSL_TIMESTAMP} -nt ${OPENSSL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for openssl detected building..."; \ + cd ${OPENSSL_DIR}; \ + cat jni/Application.mk | grep -v NDK_TOOLCHAIN_VERSION >jni/Application.mk.new;\ + mv jni/Application.mk.new jni/Application.mk; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${OPENSSL_TIMESTAMP}; \ + touch ${OPENSSL_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for openssl"; \ + fi + +clean_openssl : + $(RM) -rf ${OPENSSL_DIR} + +$(LEVELDB_TIMESTAMP) : leveldb_download + @LAST_MODIF=$$(find ${LEVELDB_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${LEVELDB_TIMESTAMP}; \ + fi + +leveldb_download : + @if [ ! -d ${LEVELDB_DIR} ] ; then \ + echo "leveldb sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd ${ROOT}/deps ; \ + git clone ${LEVELDB_URL_GIT} || exit 1; \ + fi + +leveldb : $(LEVELDB_LIB) + +$(LEVELDB_LIB): $(LEVELDB_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${LEVELDB_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${LEVELDB_TIMESTAMP} -nt ${LEVELDB_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + export PATH=$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for leveldb detected building..."; \ + cd deps/leveldb; \ + export CROSS_PREFIX=${CROSS_PREFIX}; \ + export TOOLCHAIN=/tmp/ndk-arm; \ + ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ + --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ + --install-dir=$${TOOLCHAIN} --system=linux-x86_64; \ + export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ + export CC=${CROSS_PREFIX}gcc; \ + export CXX=${CROSS_PREFIX}g++; \ + export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ + export CPPFLAGS="$${CPPFLAGS} ${TARGET_CFLAGS_ADDON}"; \ + export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \ + export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ + $(MAKE) -j${PARALLEL} -s || exit 1; \ + touch ${LEVELDB_TIMESTAMP}; \ + touch ${LEVELDB_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for leveldb"; \ + fi + +clean_leveldb : + $(RM) -rf deps/leveldb + +$(FREETYPE_TIMESTAMP) : freetype_download + @LAST_MODIF=$$(find ${FREETYPE_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${FREETYPE_TIMESTAMP}; \ + fi + +freetype_download : + @if [ ! -d ${FREETYPE_DIR} ] ; then \ + echo "freetype sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + git clone ${FREETYPE_URL_GIT} || exit 1; \ + fi + +$(IRRLICHT_TIMESTAMP) : irrlicht_download + @LAST_MODIF=$$(find ${IRRLICHT_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${IRRLICHT_TIMESTAMP}; \ + fi + +freetype : $(FREETYPE_LIB) + +$(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${FREETYPE_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -e ${FREETYPE_LIB} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${FREETYPE_TIMESTAMP} -nt ${FREETYPE_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + mkdir -p ${FREETYPE_DIR}; \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for freetype detected building..."; \ + cd ${FREETYPE_DIR}/Android/jni; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${FREETYPE_TIMESTAMP}; \ + touch ${FREETYPE_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for freetype"; \ + fi + +clean_freetype : + $(RM) -rf ${FREETYPE_DIR} + +#Note: Texturehack patch is required for gpu's not supporting color format +# correctly. Known bad GPU: +# -geforce on emulator +# -Vivante Corporation GC1000 core (e.g. Galaxy Tab 3) + +irrlicht_download : + @if [ ! -d "deps/irrlicht" ] ; then \ + echo "irrlicht sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + svn co ${IRRLICHT_URL_SVN} irrlicht || exit 1; \ + cd irrlicht; \ + patch -p1 < ../../irrlicht-touchcount.patch || exit 1; \ + patch -p1 < ../../irrlicht-back_button.patch || exit 1; \ + patch -p1 < ../../irrlicht-texturehack.patch || exit 1; \ + fi + +irrlicht : $(IRRLICHT_LIB) + +$(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB) + @REFRESH=0; \ + if [ ! -e ${IRRLICHT_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -e ${IRRLICHT_LIB} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${IRRLICHT_TIMESTAMP} -nt ${IRRLICHT_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + mkdir -p ${IRRLICHT_DIR}; \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + echo "changed timestamp for irrlicht detected building..."; \ + cd deps/irrlicht/source/Irrlicht/Android; \ + ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \ + APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \ + touch ${IRRLICHT_TIMESTAMP}; \ + touch ${IRRLICHT_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for irrlicht"; \ + fi + +clean_irrlicht : + $(RM) -rf deps/irrlicht + +$(CURL_TIMESTAMP) : curl_download + @LAST_MODIF=$$(find ${CURL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${CURL_TIMESTAMP}; \ + fi + +curl_download : + @if [ ! -d "deps/curl-${CURL_VERSION}" ] ; then \ + echo "curl sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + wget ${CURL_URL_HTTP} || exit 1; \ + tar -xjf curl-${CURL_VERSION}.tar.bz2 || exit 1; \ + rm curl-${CURL_VERSION}.tar.bz2; \ + fi + +curl : $(CURL_LIB) + +$(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB) + @REFRESH=0; \ + if [ ! -e ${CURL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -e ${CURL_LIB} ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${CURL_TIMESTAMP} -nt ${CURL_TIMESTAMP_INT} ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + mkdir -p ${CURL_DIR}; \ + export PATH="$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}"; \ + echo "changed timestamp for curl detected building..."; \ + cd deps/curl-${CURL_VERSION}; \ + export CROSS_PREFIX=${CROSS_PREFIX}; \ + export TOOLCHAIN=/tmp/ndk-arm; \ + ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \ + --toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \ + --install-dir=$${TOOLCHAIN} --system=linux-x86_64; \ + export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \ + export CC=${CROSS_PREFIX}gcc; \ + export CXX=${CROSS_PREFIX}g++; \ + export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \ + export CPPFLAGS="$${CPPFLAGS} -I${OPENSSL_DIR}/include \ + -L${OPENSSL_DIR}/libs/${TARGET_ABI}/ ${TARGET_CFLAGS_ADDON}"; \ + export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \ + export LDFLAGS="$${LDFLAGS} -L${OPENSSL_DIR}/libs/${TARGET_ABI}/ \ + ${TARGET_LDFLAGS_ADDON}"; \ + ./configure --host=${TARGET_HOST} --disable-shared --enable-static --with-ssl; \ + $(MAKE) -j${PARALLEL} -s || exit 1; \ + touch ${CURL_TIMESTAMP}; \ + touch ${CURL_TIMESTAMP_INT}; \ + else \ + echo "nothing to be done for curl"; \ + fi + +clean_curl : + $(RM) -rf deps/curl-${CURL_VERSION} + + +curl_binary: + @if [ ! -d "deps/curl-${CURL_VERSION_BINARY}" ] ; then \ + echo "curl sources missing, downloading..."; \ + mkdir -p ${ROOT}/deps; \ + cd deps; \ + wget http://curl.haxx.se/gknw.net/7.34.0/dist-android/curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\ + tar -xzf curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\ + mv curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android curl-${CURL_VERSION_BINARY};\ + rm curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz; \ + fi + +$(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB) + @mkdir -p ${ROOT}/deps; \ + LAST_MODIF=$$(find ${ROOT}/../../builtin -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../builtin/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + echo builtin changed $$LAST_MODIF; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../client -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../client/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../doc -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../doc/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../fonts -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../fonts/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../games -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../games/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../mods -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../mods/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../po -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../po/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${ROOT}/../../textures -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${ROOT}/../../textures/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + LAST_MODIF=$$(find ${IRRLICHT_DIR}/media -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \ + if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \ + touch ${IRRLICHT_DIR}/media/timestamp; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + if [ ${ROOT}/../../minetest.conf.example -nt ${ASSETS_TIMESTAMP} ] ; then \ + echo "conf changed"; \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + if [ ${ROOT}/../../README.txt -nt ${ASSETS_TIMESTAMP} ] ; then \ + touch ${ASSETS_TIMESTAMP}; \ + fi; \ + if [ ! -e $(ASSETS_TIMESTAMP) ] ; then \ + touch $(ASSETS_TIMESTAMP); \ + fi + +assets : $(ASSETS_TIMESTAMP) + @REFRESH=0; \ + if [ ! -e ${ASSETS_TIMESTAMP}.old ] ; then \ + REFRESH=1; \ + fi; \ + if [ ${ASSETS_TIMESTAMP} -nt ${ASSETS_TIMESTAMP}.old ] ; then \ + REFRESH=1; \ + fi; \ + if [ ! -d ${ROOT}/assets ] ; then \ + REFRESH=1; \ + fi; \ + if [ $$REFRESH -ne 0 ] ; then \ + echo "assets changed, refreshing..."; \ + $(MAKE) -j${PARALLEL} clean_assets; \ + mkdir -p ${ROOT}/assets/Minetest; \ + cp ${ROOT}/../../minetest.conf.example ${ROOT}/assets/Minetest; \ + cp ${ROOT}/../../README.txt ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../builtin ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../client ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../doc ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../fonts ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../games ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../mods ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../po ${ROOT}/assets/Minetest; \ + cp -r ${ROOT}/../../textures ${ROOT}/assets/Minetest; \ + mkdir -p ${ROOT}/assets/Minetest/media; \ + cp -r ${IRRLICHT_DIR}/media/Shaders ${ROOT}/assets/Minetest/media; \ + cd ${ROOT}/assets; \ + find . -name "timestamp" -exec rm {} \; ; \ + find . -name "*.blend" -exec rm {} \; ; \ + ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \ + cp ${ROOT}/${ASSETS_TIMESTAMP} ${ROOT}/${ASSETS_TIMESTAMP}.old; \ + else \ + echo "nothing to be done for assets"; \ + fi + +clean_assets : + @$(RM) -r assets + +apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) \ + $(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ROOT)/jni/src/android_version.h + @export NDEBUG=$$NDEBUG; $(MAKE) -j${PARALLEL} manifest; \ + export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \ + export ANDROID_HOME=${SDKFOLDER}; \ + mkdir -p ${ROOT}/src; \ + ndk-build NDK_MODULE_PATH=${NDK_MODULE_PATH} -j${PARALLEL} \ + GPROF=${GPROF} APP_ABI=${TARGET_ABI} \ + APP_PLATFORM=${APP_PLATFORM} \ + TARGET_LIBDIR=${TARGET_LIBDIR} \ + TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \ + TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \ + TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" && \ + ant $$BUILD_TYPE && \ + echo "++ Success!" && \ + echo "APK: bin/Minetest-$$BUILD_TYPE.apk" && \ + echo "You can install it with \`adb install -r bin/Minetest-$$BUILD_TYPE.apk\`" + +prep_srcdir : + @rm ${ROOT}/jni/src; \ + ln -s ${ROOT}/../../src ${ROOT}/jni/src + +clean_apk : manifest + @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ + export ANDROID_HOME=${SDKFOLDER}; \ + ant clean + +install_debug : + @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ + adb install -r ${ROOT}/bin/Minetest-debug.apk + +install : + @export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \ + adb install -r ${ROOT}/bin/Minetest-release.apk + +envpaths : + @echo "export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}" > and_env;\ + echo "export ANDROID_HOME=${SDKFOLDER}" >> and_env; + +clean_all : + @$(MAKE) -j${PARALLEL} clean_apk; \ + $(MAKE) clean_assets clean_irrlicht clean_leveldb clean_curl clean_openssl \ + clean_openal clean_ogg clean_manifest; \ + sleep 1; \ + $(RM) -r gen libs obj deps bin Debug and_env + +$(ROOT)/jni/src/android_version.h : + @echo "#define STR_HELPER(x) #x" \ + >${ROOT}/jni/src/android_version.h; \ + echo "#define STR(x) STR_HELPER(x)" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_MAJOR $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_MINOR $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_PATCH $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define VERSION_PATCH_ORIG $$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define CMAKE_VERSION_GITHASH \"$$(git rev-parse --short=8 HEAD)\"" \ + >> ${ROOT}/jni/src/android_version.h; \ + echo "#define CMAKE_VERSION_STRING STR(VERSION_MAJOR)\".\"STR(VERSION_MINOR)\ + \".\"STR(VERSION_PATCH)" \ + >> ${ROOT}/jni/src/android_version.h; + +manifest : + @VERS_MAJOR=$$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}'); \ + VERS_MINOR=$$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}'); \ + VERS_PATCH=$$(cat ${ROOT}/../../CMakeLists.txt | \ + grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}'); \ + BASE_VERSION="$$VERS_MAJOR.$$VERS_MINOR.$$VERS_PATCH"; \ + if [ "${NDEBUG}x" != "x" ] ; then \ + DBG=''; \ + DBG_FLAG="android:debuggable=\"false\""; \ + else \ + DBG="<uses-permission android:name=\"android.permission.SET_DEBUG_APP\" />"; \ + DBG_FLAG="android:debuggable=\"true\""; \ + fi; \ + cat ${ROOT}/AndroidManifest.xml.template | \ + sed s/###ANDROID_VERSION###/${ANDROID_VERSION_CODE}/g | \ + sed s/###BASE_VERSION###/$$BASE_VERSION/g | \ + sed -e "s@###DEBUG_BUILD###@$$DBG@g" | \ + sed -e "s@###DEBUG_FLAG###@$$DBG_FLAG@g" >${ROOT}/AndroidManifest.xml + +clean_manifest : + rm -rf ${ROOT}/AndroidManifest.xml + +clean : clean_apk clean_assets diff --git a/build/android/build.xml b/build/android/build.xml new file mode 100644 index 000000000..50a3e95ac --- /dev/null +++ b/build/android/build.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="Minetest" default="help"> + <property file="local.properties" /> + <property file="ant.properties" /> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + <loadproperties srcFile="project.properties" /> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." + unless="sdk.dir" + /> + <import file="custom_rules.xml" optional="true" /> + <import file="${sdk.dir}/tools/ant/build.xml" /> +</project> diff --git a/build/android/irrlicht-back_button.patch b/build/android/irrlicht-back_button.patch new file mode 100644 index 000000000..227749ba7 --- /dev/null +++ b/build/android/irrlicht-back_button.patch @@ -0,0 +1,19 @@ +--- irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 20:56:21.289559503 +0200 ++++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp.orig 2014-06-03 20:57:39.281556749 +0200 +@@ -423,6 +423,7 @@ + }
+
+ device->postEventFromUser(event);
++ status = 1;
+ }
+ break;
+ default:
+@@ -479,7 +480,7 @@ + KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT
+ KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT
+ KeyMap[3] = KEY_HOME; // AKEYCODE_HOME
+- KeyMap[4] = KEY_BACK; // AKEYCODE_BACK
++ KeyMap[4] = KEY_CANCEL; // AKEYCODE_BACK
+ KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL
+ KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL
+ KeyMap[7] = KEY_KEY_0; // AKEYCODE_0
diff --git a/build/android/irrlicht-texturehack.patch b/build/android/irrlicht-texturehack.patch new file mode 100644 index 000000000..a458ede72 --- /dev/null +++ b/build/android/irrlicht-texturehack.patch @@ -0,0 +1,240 @@ +--- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-22 17:01:13.266568869 +0200 ++++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-22 17:03:59.298572810 +0200 +@@ -366,112 +366,140 @@ + void(*convert)(const void*, s32, void*) = 0;
+ getFormatParameters(ColorFormat, InternalFormat, filtering, PixelFormat, PixelType, convert);
+
+- // make sure we don't change the internal format of existing images
+- if (!newTexture)
+- InternalFormat = oldInternalFormat;
+-
+- Driver->setActiveTexture(0, this);
+-
+- if (Driver->testGLError())
+- os::Printer::log("Could not bind Texture", ELL_ERROR);
+-
+- // mipmap handling for main texture
+- if (!level && newTexture)
+- {
+- // auto generate if possible and no mipmap data is given
+- if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
+- {
+- if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
+- glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
+- else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
+- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
+- else
+- glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
++ bool retry = false;
++
++ do {
++ if (retry) {
++ InternalFormat = GL_RGBA;
++ PixelFormat = GL_RGBA;
++ convert = CColorConverter::convert_A8R8G8B8toA8B8G8R8;
++ }
++ // make sure we don't change the internal format of existing images
++ if (!newTexture)
++ InternalFormat = oldInternalFormat;
+
+- glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
+- AutomaticMipmapUpdate=true;
+- }
++ Driver->setActiveTexture(0, this);
+
+- // enable bilinear filter without mipmaps
+- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
+- }
++ if (Driver->testGLError())
++ os::Printer::log("Could not bind Texture", ELL_ERROR);
+
+- // now get image data and upload to GPU
++ // mipmap handling for main texture
++ if (!level && newTexture)
++ {
++ // auto generate if possible and no mipmap data is given
++ if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
++ {
++ if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
++ glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
++ else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
++ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
++ else
++ glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
++
++ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
++ AutomaticMipmapUpdate=true;
++ }
++
++ // enable bilinear filter without mipmaps
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
++ }
+
+- u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height);
++ // now get image data and upload to GPU
+
+- void* source = image->lock();
++ u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height);
+
+- IImage* tmpImage = 0;
++ void* source = image->lock();
+
+- if (convert)
+- {
+- tmpImage = new CImage(image->getColorFormat(), image->getDimension());
+- void* dest = tmpImage->lock();
+- convert(source, image->getDimension().getArea(), dest);
+- image->unlock();
+- source = dest;
+- }
++ IImage* tmpImage = 0;
+
+- if (newTexture)
+- {
+- if (IsCompressed)
++ if (convert)
+ {
+- glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width,
+- image->getDimension().Height, 0, compressedImageSize, source);
++ tmpImage = new CImage(image->getColorFormat(), image->getDimension());
++ void* dest = tmpImage->lock();
++ convert(source, image->getDimension().getArea(), dest);
++ image->unlock();
++ source = dest;
+ }
+- else
+- glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
+- image->getDimension().Height, 0, PixelFormat, PixelType, source);
+- }
+- else
+- {
+- if (IsCompressed)
++
++ if (newTexture)
+ {
+- glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
+- image->getDimension().Height, PixelFormat, compressedImageSize, source);
++ if (IsCompressed)
++ {
++ glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width,
++ image->getDimension().Height, 0, compressedImageSize, source);
++ }
++ else
++ glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
++ image->getDimension().Height, 0, PixelFormat, PixelType, source);
+ }
+ else
+- glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
+- image->getDimension().Height, PixelFormat, PixelType, source);
+- }
+-
+- if (convert)
+- {
+- tmpImage->unlock();
+- tmpImage->drop();
+- }
+- else
+- image->unlock();
+-
+- if (!level && newTexture)
+- {
+- if (IsCompressed && !mipmapData)
+ {
+- if (image->hasMipMaps())
+- mipmapData = static_cast<u8*>(image->lock())+compressedImageSize;
++ if (IsCompressed)
++ {
++ glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
++ image->getDimension().Height, PixelFormat, compressedImageSize, source);
++ }
+ else
+- HasMipMaps = false;
++ glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
++ image->getDimension().Height, PixelFormat, PixelType, source);
+ }
+
+- regenerateMipMapLevels(mipmapData);
+-
+- if (HasMipMaps) // might have changed in regenerateMipMapLevels
++ if (convert)
+ {
+- // enable bilinear mipmap filter
+- GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST;
+-
+- if (filtering != GL_LINEAR)
+- filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST;
++ tmpImage->unlock();
++ tmpImage->drop();
++ }
++ else
++ image->unlock();
++
++ if (glGetError() != GL_NO_ERROR) {
++ static bool warned = false;
++ if ((!retry) && (ColorFormat == ECF_A8R8G8B8)) {
++
++ if (!warned) {
++ os::Printer::log("Your driver claims to support GL_BGRA but fails on trying to upload a texture, converting to GL_RGBA and trying again", ELL_ERROR);
++ warned = true;
++ }
++ }
++ else if (retry) {
++ os::Printer::log("Neither uploading texture as GL_BGRA nor, converted one using GL_RGBA succeeded", ELL_ERROR);
++ }
++ retry = !retry;
++ continue;
++ } else {
++ retry = false;
++ }
+
+- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps);
+- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
++ if (!level && newTexture)
++ {
++ if (IsCompressed && !mipmapData)
++ {
++ if (image->hasMipMaps())
++ mipmapData = static_cast<u8*>(image->lock())+compressedImageSize;
++ else
++ HasMipMaps = false;
++ }
++
++ regenerateMipMapLevels(mipmapData);
++
++ if (HasMipMaps) // might have changed in regenerateMipMapLevels
++ {
++ // enable bilinear mipmap filter
++ GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST;
++
++ if (filtering != GL_LINEAR)
++ filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST;
++
++ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps);
++ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
++ }
+ }
+- }
+
+- if (Driver->testGLError())
+- os::Printer::log("Could not glTexImage2D", ELL_ERROR);
++ if (Driver->testGLError())
++ os::Printer::log("Could not glTexImage2D", ELL_ERROR);
++ }
++ while(retry);
+ }
+
+
+--- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-25 00:28:50.820501856 +0200 ++++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-25 00:08:37.712544692 +0200 +@@ -422,6 +422,9 @@ + source = dest;
+ }
+
++ //clear old error
++ glGetError();
++
+ if (newTexture)
+ {
+ if (IsCompressed)
diff --git a/build/android/irrlicht-touchcount.patch b/build/android/irrlicht-touchcount.patch new file mode 100644 index 000000000..d4e4b9c3e --- /dev/null +++ b/build/android/irrlicht-touchcount.patch @@ -0,0 +1,30 @@ +--- irrlicht.orig/include/IEventReceiver.h 2014-06-03 19:43:50.433713133 +0200 ++++ irrlicht/include/IEventReceiver.h 2014-06-03 19:44:36.993711489 +0200 +@@ -375,6 +375,9 @@ + // Y position of simple touch.
+ s32 Y;
+
++ // number of current touches
++ s32 touchedCount;
++
+ //! Type of touch event.
+ ETOUCH_INPUT_EVENT Event;
+ };
+--- irrlicht.orig/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:43:50.505713130 +0200 ++++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:45:37.265709359 +0200 +@@ -315,6 +315,7 @@ + event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i);
+ event.TouchInput.X = AMotionEvent_getX(androidEvent, i);
+ event.TouchInput.Y = AMotionEvent_getY(androidEvent, i);
++ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent);
+
+ device->postEventFromUser(event);
+ }
+@@ -326,6 +327,7 @@ + event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex);
+ event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex);
+ event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex);
++ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent);
+
+ device->postEventFromUser(event);
+ }
diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk new file mode 100644 index 000000000..3559c2b6d --- /dev/null +++ b/build/android/jni/Android.mk @@ -0,0 +1,310 @@ +LOCAL_PATH := $(call my-dir)/.. + +#LOCAL_ADDRESS_SANITIZER:=true + +include $(CLEAR_VARS) +LOCAL_MODULE := Irrlicht +LOCAL_SRC_FILES := deps/irrlicht/lib/Android/libIrrlicht.a +include $(PREBUILT_STATIC_LIBRARY) + +#include $(CLEAR_VARS) +#LOCAL_MODULE := LevelDB +#LOCAL_SRC_FILES := deps/leveldb/libleveldb.a +#include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := curl +LOCAL_SRC_FILES := deps/curl-7.35.0/lib/.libs/libcurl.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := freetype +LOCAL_SRC_FILES := deps/freetype2-android/Android/obj/local/$(TARGET_ARCH_ABI)/libfreetype2-static.a +include $(PREBUILT_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := openal +LOCAL_SRC_FILES := deps/openal-soft/libs/$(TARGET_LIBDIR)/libopenal.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := ogg +LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libogg.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := vorbis +LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libvorbis.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := ssl +LOCAL_SRC_FILES := deps/openssl-android/libs/$(TARGET_LIBDIR)/libssl.so +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := crypto +LOCAL_SRC_FILES := deps/openssl-android/libs/$(TARGET_LIBDIR)/libcrypto.so +include $(PREBUILT_SHARED_LIBRARY) + + +include $(CLEAR_VARS) +LOCAL_MODULE := minetest + +LOCAL_CPP_FEATURES += exceptions + +ifdef GPROF +GPROF_DEF=-DGPROF +endif + +LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ \ + -DHAVE_TOUCHSCREENGUI \ + -DUSE_CURL=1 \ + -DUSE_SOUND=1 \ + -DUSE_FREETYPE=1 \ + $(GPROF_DEF) \ + -pipe -fstrict-aliasing + +ifndef NDEBUG +LOCAL_CFLAGS += -g -D_DEBUG -O0 -fno-omit-frame-pointer +else +LOCAL_CFLAGS += -fexpensive-optimizations -O3 +endif + +ifdef GPROF +PROFILER_LIBS := android-ndk-profiler +LOCAL_CFLAGS += -pg +endif + +# LOCAL_CFLAGS += -fsanitize=address +# LOCAL_LDFLAGS += -fsanitize=address + +ifeq ($(TARGET_ARCH_ABI),x86) +LOCAL_CFLAGS += -fno-stack-protector +endif + +LOCAL_C_INCLUDES := \ + jni/src jni/src/sqlite \ + jni/src/script \ + jni/src/lua/src \ + jni/src/json \ + jni/src/cguittfont \ + deps/irrlicht/include \ + deps/freetype2-android/include \ + deps/curl-7.35.0/include \ + deps/openal-soft/jni/OpenAL/include \ + deps/libvorbis-libogg-android/jni/include + +# deps/leveldb/include \ + +LOCAL_SRC_FILES := \ + jni/src/ban.cpp \ + jni/src/base64.cpp \ + jni/src/biome.cpp \ + jni/src/camera.cpp \ + jni/src/cavegen.cpp \ + jni/src/chat.cpp \ + jni/src/client.cpp \ + jni/src/clientiface.cpp \ + jni/src/clientmap.cpp \ + jni/src/clientmedia.cpp \ + jni/src/clientobject.cpp \ + jni/src/clouds.cpp \ + jni/src/collision.cpp \ + jni/src/connection.cpp \ + jni/src/content_abm.cpp \ + jni/src/content_cao.cpp \ + jni/src/content_cso.cpp \ + jni/src/content_mapblock.cpp \ + jni/src/content_mapnode.cpp \ + jni/src/content_nodemeta.cpp \ + jni/src/content_sao.cpp \ + jni/src/convert_json.cpp \ + jni/src/craftdef.cpp \ + jni/src/database-dummy.cpp \ + jni/src/database-sqlite3.cpp \ + jni/src/database.cpp \ + jni/src/debug.cpp \ + jni/src/defaultsettings.cpp \ + jni/src/drawscene.cpp \ + jni/src/dungeongen.cpp \ + jni/src/emerge.cpp \ + jni/src/environment.cpp \ + jni/src/filecache.cpp \ + jni/src/filesys.cpp \ + jni/src/game.cpp \ + jni/src/genericobject.cpp \ + jni/src/gettext.cpp \ + jni/src/guiChatConsole.cpp \ + jni/src/guiEngine.cpp \ + jni/src/guiFileSelectMenu.cpp \ + jni/src/guiFormSpecMenu.cpp \ + jni/src/guiKeyChangeMenu.cpp \ + jni/src/guiPasswordChange.cpp \ + jni/src/guiTable.cpp \ + jni/src/guiVolumeChange.cpp \ + jni/src/httpfetch.cpp \ + jni/src/hud.cpp \ + jni/src/inventory.cpp \ + jni/src/inventorymanager.cpp \ + jni/src/itemdef.cpp \ + jni/src/keycode.cpp \ + jni/src/light.cpp \ + jni/src/localplayer.cpp \ + jni/src/log.cpp \ + jni/src/main.cpp \ + jni/src/map.cpp \ + jni/src/mapblock.cpp \ + jni/src/mapblock_mesh.cpp \ + jni/src/mapgen.cpp \ + jni/src/mapgen_indev.cpp \ + jni/src/mapgen_math.cpp \ + jni/src/mapgen_singlenode.cpp \ + jni/src/mapgen_v6.cpp \ + jni/src/mapgen_v7.cpp \ + jni/src/mapnode.cpp \ + jni/src/mapsector.cpp \ + jni/src/mesh.cpp \ + jni/src/mods.cpp \ + jni/src/nameidmapping.cpp \ + jni/src/nodedef.cpp \ + jni/src/nodemetadata.cpp \ + jni/src/nodetimer.cpp \ + jni/src/noise.cpp \ + jni/src/object_properties.cpp \ + jni/src/particles.cpp \ + jni/src/pathfinder.cpp \ + jni/src/player.cpp \ + jni/src/porting_android.cpp \ + jni/src/porting.cpp \ + jni/src/quicktune.cpp \ + jni/src/rollback.cpp \ + jni/src/rollback_interface.cpp \ + jni/src/serialization.cpp \ + jni/src/server.cpp \ + jni/src/serverlist.cpp \ + jni/src/serverobject.cpp \ + jni/src/sha1.cpp \ + jni/src/shader.cpp \ + jni/src/sky.cpp \ + jni/src/socket.cpp \ + jni/src/sound.cpp \ + jni/src/sound_openal.cpp \ + jni/src/staticobject.cpp \ + jni/src/subgame.cpp \ + jni/src/test.cpp \ + jni/src/tile.cpp \ + jni/src/tool.cpp \ + jni/src/treegen.cpp \ + jni/src/version.cpp \ + jni/src/voxel.cpp \ + jni/src/voxelalgorithms.cpp \ + jni/src/util/directiontables.cpp \ + jni/src/util/numeric.cpp \ + jni/src/util/pointedthing.cpp \ + jni/src/util/serialize.cpp \ + jni/src/util/string.cpp \ + jni/src/util/timetaker.cpp \ + jni/src/touchscreengui.cpp + +# jni/src/database-leveldb.cpp \ + +# lua api +LOCAL_SRC_FILES += \ + jni/src/script/common/c_content.cpp \ + jni/src/script/common/c_converter.cpp \ + jni/src/script/common/c_internal.cpp \ + jni/src/script/common/c_types.cpp \ + jni/src/script/cpp_api/s_base.cpp \ + jni/src/script/cpp_api/s_entity.cpp \ + jni/src/script/cpp_api/s_env.cpp \ + jni/src/script/cpp_api/s_inventory.cpp \ + jni/src/script/cpp_api/s_item.cpp \ + jni/src/script/cpp_api/s_mainmenu.cpp \ + jni/src/script/cpp_api/s_node.cpp \ + jni/src/script/cpp_api/s_nodemeta.cpp \ + jni/src/script/cpp_api/s_player.cpp \ + jni/src/script/cpp_api/s_server.cpp \ + jni/src/script/cpp_api/s_async.cpp \ + jni/src/script/lua_api/l_base.cpp \ + jni/src/script/lua_api/l_craft.cpp \ + jni/src/script/lua_api/l_env.cpp \ + jni/src/script/lua_api/l_inventory.cpp \ + jni/src/script/lua_api/l_item.cpp \ + jni/src/script/lua_api/l_mainmenu.cpp \ + jni/src/script/lua_api/l_mapgen.cpp \ + jni/src/script/lua_api/l_nodemeta.cpp \ + jni/src/script/lua_api/l_nodetimer.cpp \ + jni/src/script/lua_api/l_noise.cpp \ + jni/src/script/lua_api/l_object.cpp \ + jni/src/script/lua_api/l_particles.cpp \ + jni/src/script/lua_api/l_rollback.cpp \ + jni/src/script/lua_api/l_server.cpp \ + jni/src/script/lua_api/l_settings.cpp \ + jni/src/script/lua_api/l_util.cpp \ + jni/src/script/lua_api/l_vmanip.cpp \ + jni/src/script/scripting_game.cpp \ + jni/src/script/scripting_mainmenu.cpp + +#freetype2 support +LOCAL_SRC_FILES += \ + jni/src/cguittfont/xCGUITTFont.cpp + +# lua +LOCAL_SRC_FILES += \ + jni/src/lua/src/lapi.c \ + jni/src/lua/src/lauxlib.c \ + jni/src/lua/src/lbaselib.c \ + jni/src/lua/src/lcode.c \ + jni/src/lua/src/ldblib.c \ + jni/src/lua/src/ldebug.c \ + jni/src/lua/src/ldo.c \ + jni/src/lua/src/ldump.c \ + jni/src/lua/src/lfunc.c \ + jni/src/lua/src/lgc.c \ + jni/src/lua/src/linit.c \ + jni/src/lua/src/liolib.c \ + jni/src/lua/src/llex.c \ + jni/src/lua/src/lmathlib.c \ + jni/src/lua/src/lmem.c \ + jni/src/lua/src/loadlib.c \ + jni/src/lua/src/lobject.c \ + jni/src/lua/src/lopcodes.c \ + jni/src/lua/src/loslib.c \ + jni/src/lua/src/lparser.c \ + jni/src/lua/src/lstate.c \ + jni/src/lua/src/lstring.c \ + jni/src/lua/src/lstrlib.c \ + jni/src/lua/src/ltable.c \ + jni/src/lua/src/ltablib.c \ + jni/src/lua/src/ltm.c \ + jni/src/lua/src/lundump.c \ + jni/src/lua/src/lvm.c \ + jni/src/lua/src/lzio.c \ + jni/src/lua/src/print.c + +# sqlite +LOCAL_SRC_FILES += jni/src/sqlite/sqlite3.c + +# jthread +LOCAL_SRC_FILES += \ + jni/src/jthread/pthread/jevent.cpp \ + jni/src/jthread/pthread/jmutex.cpp \ + jni/src/jthread/pthread/jsemaphore.cpp \ + jni/src/jthread/pthread/jthread.cpp + +# json +LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp + +LOCAL_SHARED_LIBRARIES := openal ogg vorbis ssl crypto +LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl android_native_app_glue $(PROFILER_LIBS) +# LevelDB +LOCAL_LDLIBS := -lEGL -llog -lGLESv1_CM -lGLESv2 -lz -landroid + +include $(BUILD_SHARED_LIBRARY) + +# at the end of Android.mk +ifdef GPROF +$(call import-module,android-ndk-profiler) +endif +$(call import-module,android/native_app_glue) diff --git a/build/android/jni/Application.mk b/build/android/jni/Application.mk new file mode 100644 index 000000000..b7ffc56a1 --- /dev/null +++ b/build/android/jni/Application.mk @@ -0,0 +1,8 @@ +# NDK_TOOLCHAIN_VERSION := clang3.3 + +APP_PLATFORM := android-9 +APP_MODULES := minetest +APP_STL := gnustl_static + +APP_CPPFLAGS += -fexceptions +APP_GNUSTL_FORCE_CPP_FEATURES := rtti diff --git a/build/android/libvorbis-libogg-fpu.patch b/build/android/libvorbis-libogg-fpu.patch new file mode 100644 index 000000000..52ab397ac --- /dev/null +++ b/build/android/libvorbis-libogg-fpu.patch @@ -0,0 +1,37 @@ +--- libvorbis-libogg-android/jni/libvorbis-jni/Android.mk.orig 2014-06-17 19:22:50.621559073 +0200 ++++ libvorbis-libogg-android/jni/libvorbis-jni/Android.mk 2014-06-17 19:38:20.641581140 +0200 +@@ -4,9 +4,6 @@ + + LOCAL_MODULE := vorbis-jni + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -fsigned-char +-ifeq ($(TARGET_ARCH),arm) +- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp +-endif + + LOCAL_SHARED_LIBRARIES := libogg libvorbis + +--- libvorbis-libogg-android/jni/libvorbis/Android.mk.orig 2014-06-17 19:22:39.077558797 +0200 ++++ libvorbis-libogg-android/jni/libvorbis/Android.mk 2014-06-17 19:38:52.121581887 +0200 +@@ -4,9 +4,6 @@ + + LOCAL_MODULE := libvorbis + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char +-ifeq ($(TARGET_ARCH),arm) +- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp +-endif + LOCAL_SHARED_LIBRARIES := libogg + + LOCAL_SRC_FILES := \ +--- libvorbis-libogg-android/jni/libogg/Android.mk.orig 2014-06-17 19:22:33.965558675 +0200 ++++ libvorbis-libogg-android/jni/libogg/Android.mk 2014-06-17 19:38:25.337581252 +0200 +@@ -4,10 +4,6 @@ + + LOCAL_MODULE := libogg + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char +-ifeq ($(TARGET_ARCH),arm) +- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp +-endif +- + + LOCAL_SRC_FILES := \ + bitwise.c \ diff --git a/build/android/project.properties b/build/android/project.properties new file mode 100644 index 000000000..cc2a7c5cf --- /dev/null +++ b/build/android/project.properties @@ -0,0 +1 @@ +target=android-10 diff --git a/build/android/res/drawable-hdpi/irr_icon.png b/build/android/res/drawable-hdpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..0b6861a0d --- /dev/null +++ b/build/android/res/drawable-hdpi/irr_icon.png diff --git a/build/android/res/drawable-ldpi/irr_icon.png b/build/android/res/drawable-ldpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..b8c5d0177 --- /dev/null +++ b/build/android/res/drawable-ldpi/irr_icon.png diff --git a/build/android/res/drawable-mdpi/irr_icon.png b/build/android/res/drawable-mdpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..951a7f8c1 --- /dev/null +++ b/build/android/res/drawable-mdpi/irr_icon.png diff --git a/build/android/res/drawable-xhdpi/irr_icon.png b/build/android/res/drawable-xhdpi/irr_icon.png Binary files differnew file mode 100644 index 000000000..2ec528ef7 --- /dev/null +++ b/build/android/res/drawable-xhdpi/irr_icon.png diff --git a/build/android/res/layout/assetcopy.xml b/build/android/res/layout/assetcopy.xml new file mode 100644 index 000000000..ade4b0c98 --- /dev/null +++ b/build/android/res/layout/assetcopy.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > + + <ProgressBar + android:id="@+id/progressBar1" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" /> + + <TextView + android:id="@+id/textView1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="preparing media ..." + android:textAppearance="?android:attr/textAppearanceSmall" /> + +</LinearLayout> diff --git a/build/android/res/values/styles.xml b/build/android/res/values/styles.xml new file mode 100644 index 000000000..25b8df5a3 --- /dev/null +++ b/build/android/res/values/styles.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="Theme.Transparent" parent="android:Theme"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:windowContentOverlay">@null</item> + <item name="android:windowNoTitle">true</item> + <item name="android:windowIsFloating">true</item> + <item name="android:backgroundDimEnabled">false</item> + </style> +</resources>
\ No newline at end of file diff --git a/build/android/src/org/minetest/minetest/MinetestAssetCopy.java b/build/android/src/org/minetest/minetest/MinetestAssetCopy.java new file mode 100644 index 000000000..652a00831 --- /dev/null +++ b/build/android/src/org/minetest/minetest/MinetestAssetCopy.java @@ -0,0 +1,288 @@ +package org.minetest.minetest; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.Vector; + +import android.app.Activity; +import android.content.res.AssetFileDescriptor; + +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.Display; +import android.widget.ProgressBar; +import android.widget.TextView; + +public class MinetestAssetCopy extends Activity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.assetcopy); + + m_ProgressBar = (ProgressBar) findViewById(R.id.progressBar1); + m_Filename = (TextView) findViewById(R.id.textView1); + + Display display = getWindowManager().getDefaultDisplay(); + m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8); + m_ProgressBar.invalidate(); + + m_AssetCopy = new copyAssetTask(); + m_AssetCopy.execute(); + } + + ProgressBar m_ProgressBar; + TextView m_Filename; + + copyAssetTask m_AssetCopy; + + private class copyAssetTask extends AsyncTask<String, Integer, String>{ + + private void copyElement(String name, String path) { + String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath(); + String full_path; + if (path != "") { + full_path = path + "/" + name; + } + else { + full_path = name; + } + //is a folder read asset list + if (m_foldernames.contains(full_path)) { + m_Foldername = full_path; + publishProgress(0); + File current_folder = new File(baseDir + "/" + full_path); + if (!current_folder.exists()) { + if (!current_folder.mkdirs()) { + Log.w("MinetestAssetCopy","\t failed create folder: " + baseDir + "/" + full_path); + } + else { + Log.w("MinetestAssetCopy","\t created folder: " + baseDir + "/" + full_path); + } + } + try { + String[] current_assets = getAssets().list(full_path); + for(int i=0; i < current_assets.length; i++) { + copyElement(current_assets[i],full_path); + } + } catch (IOException e) { + Log.w("MinetestAssetCopy","\t failed to read contents of folder"); + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + //is a file just copy + else { + boolean refresh = true; + + File testme = new File(baseDir + "/" + full_path); + + long asset_filesize = -1; + long stored_filesize = -1; + + if (testme.exists()) { + try { + AssetFileDescriptor fd = getAssets().openFd(full_path); + asset_filesize = fd.getLength(); + fd.close(); + } catch (IOException e) { + refresh = true; + m_asset_size_unknown.add(full_path); + } + + stored_filesize = testme.length(); + + if (asset_filesize == stored_filesize) { + refresh = false; + } + + } + + if (refresh) { + m_tocopy.add(full_path); + } + } + } + + private long getFullSize(String filename) { + long size = 0; + try { + InputStream src = getAssets().open(filename); + byte[] buf = new byte[1024]; + + int len = 0; + while ((len = src.read(buf)) > 0) { + size += len; + } + } + catch (IOException e) { + e.printStackTrace(); + } + return size; + } + + @Override + protected String doInBackground(String... files) { + + m_foldernames = new Vector<String>(); + m_tocopy = new Vector<String>(); + m_asset_size_unknown = new Vector<String>(); + String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/"; + + File TempFolder = new File(baseDir + "Minetest/tmp/"); + + if (!TempFolder.exists()) { + TempFolder.mkdir(); + } + else { + File[] todel = TempFolder.listFiles(); + + for(int i=0; i < todel.length; i++) { + Log.w("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath()); + todel[i].delete(); + } + } + + // add a .nomedia file + try { + OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia"); + dst.close(); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Failed to create .nomedia file"); + e.printStackTrace(); + } + + try { + InputStream is = getAssets().open("index.txt"); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + + String line = reader.readLine(); + while(line != null){ + m_foldernames.add(line); + line = reader.readLine(); + } + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + copyElement("Minetest",""); + + m_copy_started = true; + m_ProgressBar.setMax(m_tocopy.size()); + + for (int i = 0; i < m_tocopy.size(); i++) { + try { + String filename = m_tocopy.get(i); + publishProgress(i); + + boolean asset_size_unknown = false; + long filesize = -1; + + if (m_asset_size_unknown.contains(filename)) { + File testme = new File(baseDir + "/" + filename); + + if(testme.exists()) { + filesize = testme.length(); + } + asset_size_unknown = true; + } + + InputStream src; + try { + src = getAssets().open(filename); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)"); + // TODO Auto-generated catch block + e.printStackTrace(); + continue; + } + + // Transfer bytes from in to out + byte[] buf = new byte[1*1024]; + int len = src.read(buf, 0, 1024); + + /* following handling is crazy but we need to deal with */ + /* compressed assets.Flash chips limited livetime sue to */ + /* write operations, we can't allow large files to destroy */ + /* users flash. */ + if (asset_size_unknown) { + if ( (len > 0) && (len < buf.length) && (len == filesize)) { + src.close(); + continue; + } + + if (len == buf.length) { + src.close(); + long size = getFullSize(filename); + if ( size == filesize) { + continue; + } + src = getAssets().open(filename); + len = src.read(buf, 0, 1024); + } + } + if (len > 0) { + int total_filesize = 0; + OutputStream dst; + try { + dst = new FileOutputStream(baseDir + "/" + filename); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Copying file: " + baseDir + + "/" + filename + " FAILED (couldn't open output file)"); + e.printStackTrace(); + src.close(); + continue; + } + dst.write(buf, 0, len); + total_filesize += len; + + while ((len = src.read(buf)) > 0) { + dst.write(buf, 0, len); + total_filesize += len; + } + + dst.close(); + Log.w("MinetestAssetCopy","Copied file: " + m_tocopy.get(i) + " (" + total_filesize + " bytes)"); + } + else if (len < 0) { + Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed, size < 0"); + } + src.close(); + } catch (IOException e) { + Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed"); + e.printStackTrace(); + } + } + + return ""; + } + + protected void onProgressUpdate(Integer... progress) { + if (m_copy_started) { + m_ProgressBar.setProgress(progress[0]); + m_Filename.setText(m_tocopy.get(progress[0])); + } + else { + m_Filename.setText("scanning " + m_Foldername + " ..."); + } + } + + protected void onPostExecute (String result) { + finish(); + } + boolean m_copy_started = false; + String m_Foldername = "media"; + Vector<String> m_foldernames; + Vector<String> m_tocopy; + Vector<String> m_asset_size_unknown; + } +} diff --git a/build/android/src/org/minetest/minetest/MinetestTextEntry.java b/build/android/src/org/minetest/minetest/MinetestTextEntry.java new file mode 100644 index 000000000..db175a483 --- /dev/null +++ b/build/android/src/org/minetest/minetest/MinetestTextEntry.java @@ -0,0 +1,91 @@ +package org.minetest.minetest; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.text.InputType; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnKeyListener; +import android.widget.EditText; + +public class MinetestTextEntry extends Activity { + public AlertDialog mTextInputDialog; + public EditText mTextInputWidget; + + private final int MultiLineTextInput = 1; + private final int SingleLineTextInput = 2; + private final int SingleLinePasswordInput = 3; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Bundle b = getIntent().getExtras(); + String acceptButton = b.getString("EnterButton"); + String hint = b.getString("hint"); + String current = b.getString("current"); + int editType = b.getInt("editType"); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + mTextInputWidget = new EditText(this); + mTextInputWidget.setHint(hint); + mTextInputWidget.setText(current); + mTextInputWidget.setMinWidth(300); + if (editType == SingleLinePasswordInput) { + mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT | + InputType.TYPE_TEXT_VARIATION_PASSWORD); + } + else { + mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT); + } + + + builder.setView(mTextInputWidget); + + if (editType == MultiLineTextInput) { + builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) + { pushResult(mTextInputWidget.getText().toString()); } + }); + } + + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + cancelDialog(); + } + }); + + mTextInputWidget.setOnKeyListener(new OnKeyListener() { + @Override + public boolean onKey(View view, int KeyCode, KeyEvent event) { + if ( KeyCode == KeyEvent.KEYCODE_ENTER){ + + pushResult(mTextInputWidget.getText().toString()); + return true; + } + return false; + } + }); + + mTextInputDialog = builder.create(); + mTextInputDialog.show(); + } + + public void pushResult(String text) { + Intent resultData = new Intent(); + resultData.putExtra("text", text); + setResult(Activity.RESULT_OK,resultData); + mTextInputDialog.dismiss(); + finish(); + } + + public void cancelDialog() { + setResult(Activity.RESULT_CANCELED); + mTextInputDialog.dismiss(); + finish(); + } +} diff --git a/build/android/src/org/minetest/minetest/MtNativeActivity.java b/build/android/src/org/minetest/minetest/MtNativeActivity.java new file mode 100644 index 000000000..ba7d62169 --- /dev/null +++ b/build/android/src/org/minetest/minetest/MtNativeActivity.java @@ -0,0 +1,93 @@ +package org.minetest.minetest; + +import android.app.NativeActivity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.WindowManager; + +public class MtNativeActivity extends NativeActivity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + m_MessagReturnCode = -1; + m_MessageReturnValue = ""; + + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + + public void copyAssets() { + Intent intent = new Intent(this, MinetestAssetCopy.class); + startActivity(intent); + } + + public void showDialog(String acceptButton, String hint, String current, + int editType) { + + Intent intent = new Intent(this, MinetestTextEntry.class); + Bundle params = new Bundle(); + params.putString("acceptButton", acceptButton); + params.putString("hint", hint); + params.putString("current", current); + params.putInt("editType", editType); + intent.putExtras(params); + startActivityForResult(intent, 101); + m_MessageReturnValue = ""; + m_MessagReturnCode = -1; + } + + public static native void putMessageBoxResult(String text); + + /* ugly code to workaround putMessageBoxResult not beeing found */ + public int getDialogState() { + return m_MessagReturnCode; + } + + public String getDialogValue() { + m_MessagReturnCode = -1; + return m_MessageReturnValue; + } + + public float getDensity() { + return getResources().getDisplayMetrics().density; + } + + public int getDisplayWidth() { + return getResources().getDisplayMetrics().widthPixels; + } + + public int getDisplayHeight() { + return getResources().getDisplayMetrics().heightPixels; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + if (requestCode == 101) { + if (resultCode == RESULT_OK) { + String text = data.getStringExtra("text"); + m_MessagReturnCode = 0; + m_MessageReturnValue = text; + } + else { + m_MessagReturnCode = 1; + } + } + } + + static { + System.loadLibrary("openal"); + System.loadLibrary("ogg"); + System.loadLibrary("vorbis"); + System.loadLibrary("ssl"); + System.loadLibrary("crypto"); + } + + private int m_MessagReturnCode; + private String m_MessageReturnValue; +} |