diff --git a/project/jni/application/commandergenius/commandergenius b/project/jni/application/commandergenius/commandergenius index 7d74f1993..1bcbadd1e 160000 --- a/project/jni/application/commandergenius/commandergenius +++ b/project/jni/application/commandergenius/commandergenius @@ -1 +1 @@ -Subproject commit 7d74f19934f2f3a2f9e3d0df90de82cb6d52f9ad +Subproject commit 1bcbadd1eadd735235288463239c348f5b58f845 diff --git a/project/jni/application/openarena/engine b/project/jni/application/openarena/engine index 30e98be35..07c011b6c 160000 --- a/project/jni/application/openarena/engine +++ b/project/jni/application/openarena/engine @@ -1 +1 @@ -Subproject commit 30e98be3582cca3009f371ca2f9a7334e24e1582 +Subproject commit 07c011b6ccb275fc2b69dbd6e7ee8dba6223e59a diff --git a/project/jni/application/openarena/vm b/project/jni/application/openarena/vm index 278f04520..4b83db91a 160000 --- a/project/jni/application/openarena/vm +++ b/project/jni/application/openarena/vm @@ -1 +1 @@ -Subproject commit 278f045202ff1bc0c1911b6c3d441909ba93ee87 +Subproject commit 4b83db91ab39b9cae27f087fe1a0a8ba9f30d43d diff --git a/project/jni/application/teeworlds/src b/project/jni/application/teeworlds/src index e5489c8c0..34b64249c 160000 --- a/project/jni/application/teeworlds/src +++ b/project/jni/application/teeworlds/src @@ -1 +1 @@ -Subproject commit e5489c8c089e57d88bbaa90df0176d5e5d4c6351 +Subproject commit 34b64249c46a90ce127f32b3ef41a565b8a70a61 diff --git a/project/jni/application/xserver/AndroidAppSettings.cfg b/project/jni/application/xserver/AndroidAppSettings.cfg index 17359b097..9c3c2c6fa 100644 --- a/project/jni/application/xserver/AndroidAppSettings.cfg +++ b/project/jni/application/xserver/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 files|:data.tar.gz:data-1.tgz^!!Data files|:busybox:busybox" +AppDataDownloadUrl="!!Data files|:data.tar.gz:data-1.tgz^!!Data files|:busybox:busybox^!!Data files|:DroidSansMono.ttf:DroidSansMono.ttf" # 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) @@ -124,7 +124,7 @@ NonBlockingSwapBuffers=n # SEARCH and CALL by default return same keycode as DPAD_CENTER - one of those keys is available on most devices # Use word NO_REMAP if you want to preserve native functionality for certain key (volume keys are 3-rd and 4-th) # Keys: TOUCHSCREEN (works only when AppUsesMouse=n), DPAD_CENTER/SEARCH, VOLUMEUP, VOLUMEDOWN, MENU, BACK, CAMERA -RedefinedKeys="LALT RETURN NO_REMAP NO_REMAP RETURN ESCAPE" +RedefinedKeys="LALT RETURN NO_REMAP NO_REMAP RETURN UNDO" # Number of virtual keyboard keys (currently 6 is maximum) AppTouchscreenKeyboardKeysAmount=0 @@ -184,7 +184,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="jpeg png freetype sdl-1.2" +CompiledLibraries="jpeg png freetype sdl_ttf" # Application uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n) CustomBuildScript=y diff --git a/project/jni/application/xserver/AndroidBuild.sh b/project/jni/application/xserver/AndroidBuild.sh index 284c4a145..72464a830 100755 --- a/project/jni/application/xserver/AndroidBuild.sh +++ b/project/jni/application/xserver/AndroidBuild.sh @@ -6,9 +6,7 @@ LOCAL_PATH=`cd $LOCAL_PATH && pwd` PACKAGE_NAME=`grep AppFullName AndroidAppSettings.cfg | sed 's/.*=//'` ../setEnvironment-armeabi-v7a.sh sh -c '\ -$CC $CFLAGS -c main.c -o main.o' || exit 1 - - +$CC $CFLAGS -c main.c gfx.c' || exit 1 [ -e xserver/android ] || git submodule update --init xserver || exit 1 cd xserver @@ -19,8 +17,9 @@ env TARGET_DIR=/data/data/$PACKAGE_NAME/files \ ./build.sh || exit 1 ../../../setEnvironment-armeabi-v7a.sh sh -c '\ -$CC $LDFLAGS -o ../../libapplication-armeabi-v7a.so -L. \ +$CC $CFLAGS $LDFLAGS -o ../../libapplication-armeabi-v7a.so -L. \ ../../main.o \ +../../gfx.o \ hw/kdrive/sdl/sdl.o \ dix/.libs/libmain.a \ dix/.libs/libdix.a \ @@ -44,7 +43,9 @@ xkb/.libs/libxkbstubs.a \ composite/.libs/libcomposite.a \ os/.libs/libos.a \ hw/kdrive/linux/.libs/liblinux.a \ --lpixman-1 -lXfont -lXau -lXdmcp -lfontenc -lfreetype -lts' \ +-lpixman-1 -lXfont -lXau -lXdmcp -lfontenc -lts -lfreetype' \ || exit 1 +#-lfreetype is inside -lsdl_ttf + exit 0 diff --git a/project/jni/application/xserver/AndroidData/DroidSansMono.ttf b/project/jni/application/xserver/AndroidData/DroidSansMono.ttf new file mode 100644 index 000000000..a00707194 Binary files /dev/null and b/project/jni/application/xserver/AndroidData/DroidSansMono.ttf differ diff --git a/project/jni/application/xserver/gfx.c b/project/jni/application/xserver/gfx.c new file mode 100644 index 000000000..5b8a64b74 --- /dev/null +++ b/project/jni/application/xserver/gfx.c @@ -0,0 +1,300 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gfx.h" + +static TTF_Font* sFont; +static int unpackProgressMb; +static int unpackProgressMbTotal = 1; +static int unpackFinished = 0; + +static void renderString(const char *c, int x, int y); +static void renderStringColor(const char *c, int x, int y, int r, int g, int b); + +static void * unpackFilesThread(void * unused); +static void showErrorMessage(const char *msg); + +void * unpackFilesThread(void * unused) +{ + char fname[PATH_MAX*2]; + strcpy( fname, getenv("SECURE_STORAGE_DIR") ); + strcat( fname, "/usr/bin/xkbcomp" ); + struct stat st; + if( stat( fname, &st ) == 0 ) + { + unpackFinished = 1; + return 1; + } + + strcpy( fname, getenv("SECURE_STORAGE_DIR") ); + strcat( fname, "/busybox" ); + FILE * ff = fopen("busybox", "rb"); + FILE * fo = fopen(fname, "wb"); + if( !ff || !fo ) + { + unpackFinished = 1; + return 0; + } + + for(;;) + { + char buf[2048]; + int cnt = fread( buf, 1, sizeof(buf), ff ); + if( cnt < 0 ) + { + unpackFinished = 1; + return 1; + } + fwrite( buf, 1, cnt, fo ); + if( cnt < sizeof(buf) ) + break; + } + + fclose(ff); + fclose(fo); + + if( chmod(fname, 0755) != 0 ) + { + unpackFinished = 1; + return 0; + } + + if( stat( "data.tar.gz", &st ) == 0 ) + unpackProgressMbTotal = st.st_size / 1024 / 1024; + else + unpackProgressMbTotal = 1; + + unpackProgressMb = 0; + + ff = fopen("data.tar.gz", "rb"); + strcat(fname, " tar xz -C "); + strcat(fname, getenv("SECURE_STORAGE_DIR")); + fo = popen(fname, "w"); + if( !ff || !fo ) + { + unpackFinished = 1; + return 0; + } + + int unpackProgressKb = 0; + for(;;) + { + char buf[1024 * 8]; + int cnt = fread( buf, 1, sizeof(buf), ff ); + if( cnt < 0 ) + { + unpackFinished = 1; + return 1; + } + fwrite( buf, 1, cnt, fo ); + if( cnt < sizeof(buf) ) + break; + unpackProgressKb += 8; + if( unpackProgressKb >= 1024 ) + { + unpackProgressKb = 0; + unpackProgressMb++; + } + } + + fclose(ff); + if( pclose(fo) != 0 ) + { + unpackFinished = 1; + return 0; + } + + remove("data.tar.gz"); + + unpackFinished = 1; + return 1; +} + +void XSDL_unpackFiles() +{ + pthread_t thread_id; + void * status; + pthread_create(&thread_id, NULL, &unpackFilesThread, NULL); + + while (!unpackFinished) + { + SDL_Delay(400); + SDL_FillRect(SDL_GetVideoSurface(), NULL, 0); + char s[128]; + sprintf(s, "Unpacking data: %d/%d Mb, %d%%", unpackProgressMb, unpackProgressMbTotal, unpackProgressMb * 100 / unpackProgressMbTotal); + renderString(s, VID_X/2, VID_Y/3); + renderString("You may put this app to background while it's unpacking", VID_X/2, VID_Y*2/3); + SDL_Flip(SDL_GetVideoSurface()); + } + + pthread_join(thread_id, &status); + if( status == 0 ) + { + showErrorMessage("Cannot unpack data files, please reinstall the app"); + exit(1); + } +} + +void XSDL_showConfigMenu(int * resolutionW, int * displayW, int * resolutionH, int * displayH) +{ + int x, y, i, ii; + SDL_Event event; + int res = -1, dpi = -1; + char native[32] = "0x0"; + float dpiScale = 1.0f; + + const char * resStr[] = { + native, "1920x1080", "1280x960", "1280x720", + "1024x768", "800x600", "800x480", "640x480" + }; + const int resVal[][2] = { + {*resolutionW, *resolutionH}, {1920,1080}, {1280,960}, {1280,720}, + {1024,768}, {800,600}, {800,480}, {640,480} + }; + + const char * fontsStr[] = { + "x2.5", "x2", "x1.7", "x1.5", + "x1.3", "x1", "x0.9", "x0.8", + "x0.7", "x0.6", "x0.5", "x0.4" + }; + const float fontsVal[] = { + 2.5f, 2.0f, 1.7f, 1.5f, + 1.3f, 1.0f, 0.9f, 0.8f, + 0.7f, 0.6f, 0.5f, 0.4f + }; + + sprintf(native, "%dx%d native", resVal[0][0], resVal[0][1]); + + while ( res < 0 ) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_UNDO) + return; + break; + case SDL_MOUSEBUTTONUP: + { + SDL_GetMouseState(&x, &y); + i = (y / (VID_Y/2)); + ii = (x / (VID_X/4)); + res = i * 4 + ii; + } + break; + } + } + SDL_FillRect(SDL_GetVideoSurface(), NULL, 0); + renderString("Select display resolution", VID_X/2, VID_Y/2); + for(i = 0; i < 2; i++) + for(ii = 0; ii < 4; ii++) + renderString(resStr[i*4+ii], VID_X/8 + (ii*VID_X/4), VID_Y/4 + (i*VID_Y/2)); + SDL_GetMouseState(&x, &y); + renderString("X", x, y); + SDL_Delay(200); + SDL_Flip(SDL_GetVideoSurface()); + } + dpiScale = (float)resVal[res][0] / (float)*resolutionW; + *resolutionW = resVal[res][0]; + *resolutionH = resVal[res][1]; + while ( dpi < 0 ) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_UNDO) + return; + break; + case SDL_MOUSEBUTTONUP: + { + SDL_GetMouseState(&x, &y); + i = (y / (VID_Y/3)); + ii = (x / (VID_X/4)); + dpi = i * 4 + ii; + } + break; + } + } + SDL_FillRect(SDL_GetVideoSurface(), NULL, 0); + renderString("Select font scale", VID_X/2, VID_Y/3); + for(i = 0; i < 3; i++) + for(ii = 0; ii < 4; ii++) + renderString(fontsStr[i*4+ii], VID_X/8 + (ii*VID_X/4), VID_Y/6 + (i*VID_Y/3)); + SDL_GetMouseState(&x, &y); + renderString("X", x, y); + SDL_Delay(200); + SDL_Flip(SDL_GetVideoSurface()); + } + *displayW = *displayW * (dpiScale / fontsVal[dpi]); + *displayH = *displayH * (dpiScale / fontsVal[dpi]); +} + +void showErrorMessage(const char *msg) +{ + SDL_Event event; + SDL_FillRect(SDL_GetVideoSurface(), NULL, 0); + renderString(msg, VID_X/2, VID_Y/2); + SDL_Flip(SDL_GetVideoSurface()); + while (1) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_UNDO) + return; + break; + } + } + } +} + +void XSDL_initSDL() +{ + SDL_Init(SDL_INIT_VIDEO); + SDL_SetVideoMode(VID_X, VID_Y, 24, SDL_SWSURFACE); + TTF_Init(); + sFont = TTF_OpenFont("DroidSansMono.ttf", 10); + if (!sFont) + { + __android_log_print(ANDROID_LOG_INFO, "XSDL", "Error: cannot open font file, please reinstall the app"); + exit(1); + } +} + +void XSDL_deinitSDL() +{ + TTF_CloseFont(sFont); + sFont = NULL; + TTF_Quit(); + // Do NOT call SDL_Quit(), it crashes! +} + +void renderStringColor(const char *c, int x, int y, int r, int g, int b) +{ + SDL_Color fColor = {r, g, b}; + SDL_Rect fontRect = {0, 0, 0, 0}; + SDL_Surface* fontSurface = TTF_RenderUTF8_Solid(sFont, c, fColor); + fontRect.w = fontSurface->w; + fontRect.h = fontSurface->h; + fontRect.x = x - fontRect.w / 2; + fontRect.y = y - fontRect.h / 2; + SDL_BlitSurface(fontSurface, NULL, SDL_GetVideoSurface(), &fontRect); + SDL_FreeSurface(fontSurface); +} + +void renderString(const char *c, int x, int y) +{ + renderStringColor(c, x, y, 255, 255, 255); +} + diff --git a/project/jni/application/xserver/gfx.h b/project/jni/application/xserver/gfx.h new file mode 100644 index 000000000..1fefefdb1 --- /dev/null +++ b/project/jni/application/xserver/gfx.h @@ -0,0 +1,11 @@ +#ifndef _XSDL_GFX_H_ +#define _XSDL_GFX_H_ + +enum { VID_X = 480, VID_Y = 320 }; + +void XSDL_initSDL(); +void XSDL_deinitSDL(); +void XSDL_unpackFiles(); +void XSDL_showConfigMenu(int * resolutionW, int * displayW, int * resolutionH, int * displayH); + +#endif diff --git a/project/jni/application/xserver/main.c b/project/jni/application/xserver/main.c index eb88f1962..fd8db92b5 100644 --- a/project/jni/application/xserver/main.c +++ b/project/jni/application/xserver/main.c @@ -1,12 +1,12 @@ #include #include -#include -#include +#include #include #include +#include "gfx.h" + extern int android_main( int argc, char *argv[], char *envp[] ); -static int unpack_files(); int main( int argc, char* argv[] ) { @@ -25,81 +25,29 @@ int main( int argc, char* argv[] ) }; char * envp[] = { NULL }; - sprintf( screenres, "%s/%sx%s/%sx%d", - getenv("DISPLAY_RESOLUTION_WIDTH"), - getenv("DISPLAY_WIDTH_MM"), - getenv("DISPLAY_RESOLUTION_HEIGHT"), - getenv("DISPLAY_HEIGHT_MM"), - 24 ); + int resolutionW = atoi(getenv("DISPLAY_RESOLUTION_WIDTH")); + int resolutionH = atoi(getenv("DISPLAY_RESOLUTION_HEIGHT")); + int displayW = atoi(getenv("DISPLAY_WIDTH_MM")); + int displayH = atoi(getenv("DISPLAY_HEIGHT_MM")); + + __android_log_print(ANDROID_LOG_INFO, "XSDL", "Actual video resolution %d/%dx%d/%d", resolutionW, displayW, resolutionH, displayH); + + XSDL_initSDL(); + + XSDL_unpackFiles(); + + XSDL_showConfigMenu(&resolutionW, &displayW, &resolutionH, &displayH); + + XSDL_deinitSDL(); + + sprintf( screenres, "%d/%dx%d/%dx%d", resolutionW, displayW, resolutionH, displayH, 24 ); if( argc >= 2 ) cmd = argv[2]; sprintf( clientcmd, "%s/usr/bin/xhost + ; %s", getenv("SECURE_STORAGE_DIR"), cmd ); - if( !unpack_files() ) - { - __android_log_print(ANDROID_LOG_INFO, "XSDL", "Error while unpacking files, try to reinstall the app"); - return 1; - } - + __android_log_print(ANDROID_LOG_INFO, "XSDL", "XSDL video resolution %s", screenres); + return android_main( 8, args, envp ); } - -int unpack_files() -{ - char fname[PATH_MAX*2]; - strcpy( fname, getenv("SECURE_STORAGE_DIR") ); - strcat( fname, "/usr/bin/xkbcomp" ); - struct stat st; - if( stat( fname, &st ) == 0 ) - return 1; - - strcpy( fname, getenv("SECURE_STORAGE_DIR") ); - strcat( fname, "/busybox" ); - FILE * ff = fopen("busybox", "rb"); - FILE * fo = fopen(fname, "wb"); - if( !ff || !fo ) - return 0; - - for(;;) - { - char buf[2048]; - int cnt = fread( buf, 1, sizeof(buf), ff ); - if( cnt < 0 ) - return 1; - fwrite( buf, 1, cnt, fo ); - if( cnt < sizeof(buf) ) - break; - } - - fclose(ff); - fclose(fo); - - if( chmod(fname, 0755) != 0 ) - return 0; - - ff = fopen("data.tar.gz", "rb"); - strcat(fname, " tar xz -C "); - strcat(fname, getenv("SECURE_STORAGE_DIR")); - fo = popen(fname, "w"); - if( !ff || !fo ) - return 0; - - for(;;) - { - char buf[2048]; - int cnt = fread( buf, 1, sizeof(buf), ff ); - if( cnt < 0 ) - return 1; - fwrite( buf, 1, cnt, fo ); - if( cnt < sizeof(buf) ) - break; - } - - fclose(ff); - if( pclose(fo) != 0 ) - return 0; - - return 1; -} diff --git a/project/jni/application/xserver/readme.txt b/project/jni/application/xserver/readme.txt index 298123b66..9d0534a94 100644 --- a/project/jni/application/xserver/readme.txt +++ b/project/jni/application/xserver/readme.txt @@ -1,7 +1,7 @@ You will need to install some packages to your Debian/Ubuntu first: -sudo apt-get install bison libpixman-1-dev +sudo apt-get install bison libpixman-1-dev \ libxfont-dev libxkbfile-dev libpciaccess-dev \ xutils-dev xcb-proto python-xcbgen xsltproc \ x11proto-bigreqs-dev x11proto-composite-dev \ diff --git a/project/jni/application/xserver/xserver b/project/jni/application/xserver/xserver index d1da3d5e3..f1a52cb49 160000 --- a/project/jni/application/xserver/xserver +++ b/project/jni/application/xserver/xserver @@ -1 +1 @@ -Subproject commit d1da3d5e31a7fe9beb380114616c6a4e3de277a8 +Subproject commit f1a52cb49bd4b869d6ce94f65156bdfb95b042a8