Moved to NDK r4 and SDK 2.2, updated readme, still catching the crash in audio output with Android 2.2 - added lot of debug spam
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
APP_PROJECT_PATH := $(call my-dir)/project
|
||||
APP_MODULES := application stlport sdl sdl_main sdl_mixer tremor sdl_image png jpeg sdl_ttf freetype
|
||||
7
alienblaster/build.sh
Executable file
7
alienblaster/build.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set here your own NDK path if needed
|
||||
export PATH=$PATH:~/src/endless_space/android-ndk-r4
|
||||
|
||||
cd project && ndk-build -j2 V=1 && ant debug && cd bin && adb install -r DemoActivity-debug.apk
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
package="de.schwardtnet.alienblaster"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application android:label="@string/app_name">
|
||||
<application android:label="@string/app_name"
|
||||
android:debuggable="true"
|
||||
>
|
||||
<activity android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
@@ -14,7 +16,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-sdk android:minSdkVersion="4" />
|
||||
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
|
||||
|
||||
@@ -8,6 +8,4 @@
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-4
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
target=android-8
|
||||
|
||||
@@ -74,13 +74,19 @@ int difficultyLevel;
|
||||
float actBackgroundPos;
|
||||
|
||||
Game::Game() {
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 1");
|
||||
videoserver = new Video();
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 2");
|
||||
screen = 0;
|
||||
screen = videoserver->init();
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 3");
|
||||
settings = new Settings();
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 4");
|
||||
intro = new Intro( screen );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 5");
|
||||
setDifficulty = new SetDifficulty( screen );
|
||||
menuArcadeMode = new MenuArcadeMode( screen );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 6");
|
||||
|
||||
pauseSprite = surfaceDB.loadSurface( FN_PAUSED );
|
||||
youLoseSprite = surfaceDB.loadSurface( FN_YOU_LOSE );
|
||||
@@ -92,6 +98,8 @@ Game::Game() {
|
||||
|
||||
bossAlarm = Mixer::mixer().loadSample( FN_SOUND_BOSS_ALARM, 60 );
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 7");
|
||||
|
||||
fontTime = new Font( FN_FONT_NUMBERS_TIME );
|
||||
fontSizeTime = fontTime->getCharWidth();
|
||||
|
||||
@@ -125,18 +133,27 @@ Game::Game() {
|
||||
sonic1 = new Sonic();
|
||||
sonic2 = new Sonic();
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 8");
|
||||
|
||||
background = new Background();
|
||||
loadLevel( FN_LEVEL_ONE_PLAYER );
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 9");
|
||||
|
||||
SDL_Surface *loadingSprite = surfaceDB.loadSurface( FN_LOADING );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 10");
|
||||
SDL_Rect dest;
|
||||
dest.x = (SCREEN_WIDTH - loadingSprite->w ) / 2;
|
||||
dest.y = (SCREEN_HEIGHT - loadingSprite->h ) / 2;
|
||||
dest.w = loadingSprite->w;
|
||||
dest.h = loadingSprite->h;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 11");
|
||||
SDL_BlitSurface( loadingSprite, 0, screen, &dest );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 12");
|
||||
SDL_Flip( screen );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 13");
|
||||
initAllSurfaces();
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 14");
|
||||
}
|
||||
|
||||
Game::~Game(){
|
||||
|
||||
@@ -31,15 +31,25 @@ using namespace std;
|
||||
#include "infoscreen.h"
|
||||
|
||||
Intro::Intro( SDL_Surface *scr ) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 1");
|
||||
screen = scr;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 2");
|
||||
introSprite = surfaceDB.loadSurface( FN_ALIENBLASTER_INTRO );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 3");
|
||||
activeChoiceSprite = surfaceDB.loadSurface( FN_INTRO_SHOW_CHOICE );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 4");
|
||||
font = new Font( FN_FONT_INTRO );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 5");
|
||||
fontHighlighted = new Font( FN_FONT_INTRO_HIGHLIGHTED );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 6");
|
||||
activeChoice = 0;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 7");
|
||||
choose = Mixer::mixer().loadSample( FN_SOUND_INTRO_CHOOSE, 100 );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 8");
|
||||
confirm = Mixer::mixer().loadSample( FN_SOUND_INTRO_CONFIRM, 100 );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 9");
|
||||
infoscreen = new Infoscreen( screen );
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 10");
|
||||
}
|
||||
|
||||
Intro::~Intro() {}
|
||||
|
||||
@@ -25,10 +25,15 @@
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 0");
|
||||
SDL_Init(0);
|
||||
srand(0);
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 1");
|
||||
Game game;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 2");
|
||||
game.run();
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 3");
|
||||
SDL_Quit();
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 4");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ using namespace std;
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <android/log.h>
|
||||
|
||||
Mixer * mixerInstance = NULL;
|
||||
|
||||
@@ -35,17 +36,22 @@ Mixer & Mixer::mixer()
|
||||
}
|
||||
|
||||
Mixer::Mixer() {
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio");
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||
printf("Couldn't initialize SDL audio subsystem: %s\n", SDL_GetError());
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "Couldn't initialize SDL audio subsystem: %s", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 2");
|
||||
mixChunks = MixChunks(0);
|
||||
musics = Musics(0);
|
||||
enabled = false;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 3");
|
||||
initMixer();
|
||||
lastUsedReservedChannel = 0;
|
||||
reservedChannels = 0;
|
||||
musicPlaying = MUSIC_NONE;
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio done");
|
||||
}
|
||||
|
||||
Mixer::~Mixer() {
|
||||
@@ -55,6 +61,7 @@ Mixer::~Mixer() {
|
||||
}
|
||||
|
||||
void Mixer::initMixer() {
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 4");
|
||||
enabled = (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 1, 1024) >= 0);
|
||||
if (enabled) {
|
||||
Mix_AllocateChannels(MIXER_NUMBER_CHANNELS);
|
||||
@@ -66,6 +73,7 @@ void Mixer::initMixer() {
|
||||
fn2mus.clear();
|
||||
playsOn.clear();
|
||||
}
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 5");
|
||||
}
|
||||
|
||||
void Mixer::freeMixer() {
|
||||
|
||||
@@ -40,14 +40,17 @@ SDL_Surface *Video::init(){
|
||||
// SDL initialisation
|
||||
// -----------------------------------------------------
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing video");
|
||||
fullscreen = false;
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
|
||||
printf("Couldn't initialize SDL video subsystem: %s\n", SDL_GetError());
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "Couldn't initialize SDL video subsystem: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, SDL_DOUBLEBUF /* | SDL_FULLSCREEN */ );
|
||||
if (!screen) {
|
||||
printf("Couldn't set %dx%d, %dbit video mode: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, SDL_GetError());
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "Couldn't set %dx%d, %dbit video mode: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, SDL_GetError());
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@@ -55,6 +58,7 @@ SDL_Surface *Video::init(){
|
||||
SDL_WM_SetIcon(SDL_LoadBMP( FN_ALIENBLASTER_ICON.c_str() ), NULL);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing video done");
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_error_c.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
/* Routine to get the thread-specific error variable */
|
||||
#if SDL_THREADS_DISABLED
|
||||
/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */
|
||||
@@ -111,6 +115,9 @@ SDL_SetError(const char *fmt, ...)
|
||||
#ifdef DEBUG_ERROR
|
||||
fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError());
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "SDL_SetError: %s", SDL_GetError());
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function has a bit more overhead than most error functions
|
||||
|
||||
@@ -100,8 +100,8 @@ static Uint8 *ANDROIDAUD_GetAudioBuf(_THIS)
|
||||
|
||||
static int ANDROIDAUD_OpenAudio(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio: enter");
|
||||
SDL_AudioSpec *audioFormat = &this->spec;
|
||||
jboolean isCopy = JNI_TRUE;
|
||||
int bytesPerSample;
|
||||
JNIEnv * jniEnv = NULL;
|
||||
|
||||
@@ -129,32 +129,26 @@ static int ANDROIDAUD_OpenAudio(_THIS, const char *devname, int iscapture)
|
||||
return (-1); // TODO: enable format conversion? Don't know how to do that in SDL
|
||||
}
|
||||
|
||||
audioBufferJNI = (*jniEnv)->CallObjectMethod( jniEnv, JavaAudioThread, JavaInitAudio,
|
||||
audioBufferSize = (*jniEnv)->CallIntMethod( jniEnv, JavaAudioThread, JavaInitAudio,
|
||||
(jint)audioFormat->freq, (jint)audioFormat->channels,
|
||||
(jint)(( bytesPerSample == 2 ) ? 1 : 0), (jint)audioFormat->size);
|
||||
|
||||
if( ! audioBufferJNI )
|
||||
if( audioBufferSize == 0 )
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio(): failed to get audio buffer from JNI");
|
||||
ANDROIDAUD_CloseAudio(this);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
audioBufferJNI = (*jniEnv)->NewGlobalRef(jniEnv, audioBufferJNI);
|
||||
audioBufferSize = (*jniEnv)->GetArrayLength(jniEnv, audioBufferJNI);
|
||||
audioBuffer = (unsigned char *) (*jniEnv)->GetByteArrayElements(jniEnv, audioBufferJNI, &isCopy);
|
||||
if( isCopy == JNI_TRUE )
|
||||
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "ANDROIDAUD_OpenAudio(): JNI returns a copy of byte array - no audio will be played");
|
||||
|
||||
/* We cannot call DetachCurrentThread() from main thread or we'll crash */
|
||||
/* (*jniVM)->DetachCurrentThread(jniVM); */
|
||||
|
||||
audioFormat->samples = audioBufferSize / bytesPerSample / audioFormat->channels;
|
||||
audioFormat->size = audioBufferSize;
|
||||
SDL_memset(audioBuffer, audioFormat->silence, audioFormat->size);
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_OpenAudio: exit, audioBufferSize %d", audioBufferSize);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@@ -190,12 +184,13 @@ static jmethodID JavaFillBuffer = NULL;
|
||||
|
||||
static void ANDROIDAUD_ThreadInit(_THIS)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_ThreadInit: enter");
|
||||
jclass JavaAudioThreadClass = NULL;
|
||||
jmethodID JavaInitThread = NULL;
|
||||
struct sched_param param;
|
||||
jmethodID JavaGetBuffer = NULL;
|
||||
jboolean isCopy = JNI_TRUE;
|
||||
|
||||
(*jniVM)->AttachCurrentThread(jniVM, &jniEnvPlaying, NULL);
|
||||
|
||||
|
||||
JavaAudioThreadClass = (*jniEnvPlaying)->GetObjectClass(jniEnvPlaying, JavaAudioThread);
|
||||
JavaFillBuffer = (*jniEnvPlaying)->GetMethodID(jniEnvPlaying, JavaAudioThreadClass, "fillBuffer", "()I");
|
||||
@@ -203,6 +198,22 @@ static void ANDROIDAUD_ThreadInit(_THIS)
|
||||
/* HACK: raise our own thread priority to max to get rid of "W/AudioFlinger: write blocked for 54 msecs" errors */
|
||||
JavaInitThread = (*jniEnvPlaying)->GetMethodID(jniEnvPlaying, JavaAudioThreadClass, "initAudioThread", "()I");
|
||||
(*jniEnvPlaying)->CallIntMethod( jniEnvPlaying, JavaAudioThread, JavaInitThread );
|
||||
|
||||
JavaGetBuffer = (*jniEnvPlaying)->GetMethodID(jniEnvPlaying, JavaAudioThreadClass, "getBuffer", "()[B");
|
||||
audioBufferJNI = (*jniEnvPlaying)->CallObjectMethod( jniEnvPlaying, JavaAudioThread, JavaGetBuffer );
|
||||
audioBufferJNI = (*jniEnvPlaying)->NewGlobalRef(jniEnvPlaying, audioBufferJNI);
|
||||
audioBuffer = (unsigned char *) (*jniEnvPlaying)->GetByteArrayElements(jniEnvPlaying, audioBufferJNI, &isCopy);
|
||||
if( !audioBuffer )
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "ANDROIDAUD_PlayAudio() JNI::GetByteArrayElements() failed! we will crash now");
|
||||
return;
|
||||
}
|
||||
if( isCopy == JNI_TRUE )
|
||||
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "ANDROIDAUD_OpenAudio(): JNI returns a copy of byte array - no audio will be played");
|
||||
|
||||
SDL_memset(audioBuffer, this->spec.silence, this->spec.size);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_ThreadInit: exit, audioBuffer %p", audioBuffer);
|
||||
};
|
||||
|
||||
static void ANDROIDAUD_ThreadDeinit(_THIS)
|
||||
@@ -212,18 +223,23 @@ static void ANDROIDAUD_ThreadDeinit(_THIS)
|
||||
|
||||
static void ANDROIDAUD_PlayAudio(_THIS)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio: enter, audiobuffer %p", audioBuffer);
|
||||
jboolean isCopy = JNI_TRUE;
|
||||
|
||||
(*jniEnvPlaying)->ReleaseByteArrayElements(jniEnvPlaying, audioBufferJNI, (jbyte *)audioBuffer, 0);
|
||||
audioBuffer = NULL;
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio: before JavaFillBuffer");
|
||||
(*jniEnvPlaying)->CallIntMethod( jniEnvPlaying, JavaAudioThread, JavaFillBuffer );
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio: after JavaFillBuffer");
|
||||
|
||||
audioBuffer = (unsigned char *) (*jniEnvPlaying)->GetByteArrayElements(jniEnvPlaying, audioBufferJNI, &isCopy);
|
||||
if( !audioBuffer )
|
||||
__android_log_print(ANDROID_LOG_ERROR, "libSDL", "ANDROIDAUD_PlayAudio() JNI::GetByteArrayElements() failed! we will crash now");
|
||||
|
||||
if( isCopy == JNI_TRUE )
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio() JNI returns a copy of byte array - that's slow");
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "ANDROIDAUD_PlayAudio: exit audioBuffer %p", audioBuffer);
|
||||
}
|
||||
|
||||
#ifndef SDL_JAVA_PACKAGE_PATH
|
||||
@@ -238,7 +254,7 @@ JNIEXPORT jint JNICALL JAVA_EXPORT_NAME(AudioThread_nativeAudioInitJavaCallbacks
|
||||
jclass JavaAudioThreadClass = NULL;
|
||||
JavaAudioThread = (*jniEnv)->NewGlobalRef(jniEnv, thiz);
|
||||
JavaAudioThreadClass = (*jniEnv)->GetObjectClass(jniEnv, JavaAudioThread);
|
||||
JavaInitAudio = (*jniEnv)->GetMethodID(jniEnv, JavaAudioThreadClass, "initAudio", "(IIII)[B");
|
||||
JavaInitAudio = (*jniEnv)->GetMethodID(jniEnv, JavaAudioThreadClass, "initAudio", "(IIII)I");
|
||||
JavaDeinitAudio = (*jniEnv)->GetMethodID(jniEnv, JavaAudioThreadClass, "deinitAudio", "()I");
|
||||
/*
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "nativeAudioInitJavaCallbacks(): JavaAudioThread %p JavaFillBuffer %p JavaInitAudio %p JavaDeinitAudio %p",
|
||||
|
||||
@@ -28,6 +28,11 @@ JAVA_EXPORT_NAME(DemoRenderer_nativeInit) ( JNIEnv* env, jobject thiz )
|
||||
int argc = 1;
|
||||
char * argv[] = { "sdl" };
|
||||
chdir(SDL_CURDIR_PATH);
|
||||
/*
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Waiting 30s for debugger");
|
||||
sleep(30); // Wait for debugger to attach
|
||||
__android_log_print(ANDROID_LOG_INFO, "libSDL", "Starting main()");
|
||||
*/
|
||||
main( argc, argv );
|
||||
};
|
||||
|
||||
|
||||
@@ -34,11 +34,18 @@ class AudioThread {
|
||||
|
||||
public int fillBuffer()
|
||||
{
|
||||
mAudio.write( mAudioBuffer, 0, mAudioBuffer.length );
|
||||
Log.i("libSDL", "JNI: fillBuffer() enter, mAudioBuffer len " + String.valueOf(mAudioBuffer.length));
|
||||
int ret = 0;
|
||||
try{
|
||||
ret = mAudio.write( mAudioBuffer, 0, mAudioBuffer.length );
|
||||
} catch( Throwable t ) {
|
||||
Log.i("libSDL", "JNI: fillBuffer() caught exception!");
|
||||
}
|
||||
Log.i("libSDL", "JNI: fillBuffer() exit, written " + String.valueOf(ret));
|
||||
return 1;
|
||||
}
|
||||
|
||||
public byte[] initAudio(int rate, int channels, int encoding, int bufSize)
|
||||
public int initAudio(int rate, int channels, int encoding, int bufSize)
|
||||
{
|
||||
if( mAudio == null )
|
||||
{
|
||||
@@ -60,7 +67,12 @@ class AudioThread {
|
||||
AudioTrack.MODE_STREAM );
|
||||
mAudio.play();
|
||||
}
|
||||
return mAudioBuffer;
|
||||
return mAudioBuffer.length;
|
||||
}
|
||||
|
||||
public byte[] getBuffer()
|
||||
{
|
||||
return mAudioBuffer;
|
||||
}
|
||||
|
||||
public int deinitAudio()
|
||||
|
||||
@@ -3,29 +3,25 @@ I did not change anything in Alien Blaster sources, except for SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT and BIT_DEPTH constants in global.h, to support 320x480x16bpp video mode,
|
||||
and also made audio initialize after main() has been called, not inside static initializers.
|
||||
|
||||
This should be compiled with Android 1.6 SDK and NDK - google for them and install them as described in their docs.
|
||||
You'll need to install Ant too
|
||||
Then symlink this dir to <android-ndk>/apps under the name "alienblaster":
|
||||
ln -s `pwd` <android-ndk>/apps/alienblaster
|
||||
Then go to <android-ndk> dir and execute:
|
||||
make APP=alienblaster V=1
|
||||
Hopefully it will compile a bunch of libs under project/libs/armeabi
|
||||
Then you'll have to compile Android .apk package with Java wrapper code for this lib:
|
||||
Go to "project" directory and type
|
||||
This should be compiled with Android 2.2 SDK and NDK r4 - google for them and install them as described in their docs
|
||||
(the application will run on Android 1.6 and above, 2.2 is the first version where you can debug it).
|
||||
You'll need to install Ant too.
|
||||
Go to "project" directory and launch command
|
||||
android update project -p .
|
||||
ant debug
|
||||
That will create file project/bin/DemoActivity-debug.apk - use "adb install" to test it
|
||||
Then go back, edit file build.sh if needed to add NDK dir to your PATH, then launch it.
|
||||
Hopefully it will compile a bunch of libs under project/libs/armeabi,
|
||||
create file project/bin/DemoActivity-debug.apk and install it on your device or emulator.
|
||||
Then you can test it by launching Alien Blaster icon from Android applications menu.
|
||||
It's designed for 640x480, and GUI elements are drawn out of place, but you can play the game.
|
||||
Note: The game enforces vertical screen orientation, but you may open your keyboard and use it for
|
||||
It's designed for 640x480, so if you have smaller screen it will be resized.
|
||||
Note: The game enforces horizontal screen orientation, you may open your keyboard and use it for
|
||||
additional keys - the phone will just keep current screen orientation.
|
||||
Fire key is Call key ( = left Ctrl for SDL ), Change weapon is Menu key ( = left Alt for SDL )
|
||||
Note that you may use Volume up/down and Camera keys as game inputs -
|
||||
you'll have to redefine them in game keyconfig menu.
|
||||
Other keys like Home, Search and End Call will force application quit, and because
|
||||
the app itself does not handle SDL_QUIT event correctly (asks for confirmation),
|
||||
it will stay in memory until you reboot device (actually it won't stay in memory - it will crash :P ).
|
||||
To exit correctly press Menu key - it's redirected to Escape.
|
||||
Keys Home, Search and End Call will force application quit, and because
|
||||
of a bug in my SDL implementation application will crash.
|
||||
Back key is mapped to Escape, and both Menu and cursor keys center / trackball click are mapped to Enter.
|
||||
Newer Android phones like HTC Evo have no keyboard at all, so there are just 3 usable keys -
|
||||
Menu, Volume Up and Volume Down. Because of that the accelerometer is configured to trigger cursor key events.
|
||||
|
||||
This port also supports GL ES + SDL combo - there is GLXGears demo app in project/jni/application/glxgears,
|
||||
remove all files from project/jni/application/src and put glxgears.c there to check if it works.
|
||||
@@ -33,32 +29,45 @@ Note that GL ES is NOT pure OpenGL - there are no glBegin() and glEnd() call and
|
||||
and generally it will take a lot of effort to port pure OpenGL application to GL ES.
|
||||
|
||||
When porting you own app, first of all ensure that your application supports
|
||||
one of 320x200, 320x240 or 480x320 display resolutions and 16 bits per pixel
|
||||
(480x320 is native resolution for G1, Supersonic has 800x480).
|
||||
Also there is 640x480 mode, but it's very slow on G1 to copy from memory surface (2 FPS max).
|
||||
SDL_ListModes()[0] will always return native screen resolution, other modes are there for compatibility.
|
||||
native RGB_565 pixel format and AUDIO_S8 or AUDIO_S16 audio format
|
||||
(yes, there is RGB_565 pixelformat even for OpenGL, not BGR_565 as all other OpenGL implementation have).
|
||||
HTC G1/Nexus One has native screen resolution 480x320, HTC Evo has 800x480, so design your app to support
|
||||
any screen resolution.
|
||||
SDL_ListModes()[0] will always return native screen resolution, you may use 640x480 or 800x600
|
||||
but it will be resized to fit the screen.
|
||||
|
||||
To compile your own app, put your app sources into project/jni/application dir (remove Alien Blaster first),
|
||||
and launch script ChangeAppSettings.sh - it will put the name of your app in several places in sources.
|
||||
The C++ files shall have .cpp extension to be compiled.
|
||||
|
||||
Then repeat steps:
|
||||
make APP=alienblaster V=1
|
||||
ant debug
|
||||
The C++ files shall have .cpp extension to be compiled, rename them if necessary.
|
||||
Then you should launch script ChangeAppSettings.sh - it will ask you few questions,
|
||||
and change several values across project files.
|
||||
Then you can launch build.sh.
|
||||
|
||||
Application data is not bundled with app itself - it should be downloaded from net on first run.
|
||||
Create .ZIP file with your application data, and put it somewhere on HTTP server - ChangeAppSettings.sh
|
||||
will ask you for the URL.
|
||||
If your app data is bigger than 5 megabytes it's better to store it on SD card,
|
||||
If your app data is bigger than 5 megabytes it's better to store it on SD card,
|
||||
internal flash on Android is very limited.
|
||||
|
||||
If you'll add new libs add them to project/jni/, copy Android.mk from existing lib, and
|
||||
add libname to Application.mk and project/jni/<yourapp>/Android.mk
|
||||
If you'll add new libs - add them to project/jni/, copy Android.mk from existing lib, and
|
||||
add libname to project/jni/<yourapp>/Android.mk
|
||||
|
||||
Audio formats currently supported are AUDIO_S8 and AUDIO_S16 (signed 8-bit and 16-bit PCM).
|
||||
To debug your application launch Android 2.2 emulator or connect Android 2.2 device,
|
||||
go to "project" directory and launch command
|
||||
ndk-gdb --verbose --start --force
|
||||
then when it fails enter command
|
||||
target remote:5039
|
||||
(then answer "y")
|
||||
Note that it's extremely buggy (I've succeeded to launch debug session twice from 20 tries),
|
||||
you may wish to add "sleep(30);" at the beginning of main() so your app won't crash before debugger attached.
|
||||
So it's best to debug with code like:
|
||||
__android_log_print(ANDROID_LOG_INFO, "My App", "We somehow reached execution point #224");
|
||||
|
||||
Known bugs:
|
||||
|
||||
0. Revert to widely-used SDL 1.2, backport changes that enable hardware acceleration from SDL 1.3
|
||||
Ideally ChangeAppSettings.sh should ask you what SDL version you want to use.
|
||||
|
||||
1. Application will crash on exit or when you're pressing "Home" button - the correct behavior for Android apps
|
||||
is to stay in memory and go to foreground when you're launching app again, that's not working yet because
|
||||
app will lose OpenGL context (there are rumors that it won't lose GL context in 2.1 SDK).
|
||||
|
||||
Reference in New Issue
Block a user