[Scummvm-cvs-logs] scummvm master -> a017cb3d00293c2f4c916c375fff172a6d962e33

dhewg dhewg at wiibrew.org
Thu Feb 24 23:23:37 CET 2011


This automated email contains information about 13 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
257913676d ANDROID: Split code into multiple files
4af28f96ab ANDROID: Remove unused jmethod Object.wait()
c4706733d4 ANDROID: Move the global back reference to jni.cpp
f80d993860 ANDROID: Wrap JNI code in a class
53b5808d4f ANDROID: Move rest of everything JNI
0e9b4f3c50 ANDROID: We are not a text editor
50a682e7e1 GUI: Make the ThemeParser less dumb
867fa2696d ANDROID: Let's not do that on the stack
d8acbc0311 ANDROID: Deuglify overlay gfx
36135443b9 ANDROID: Disable zoning for now
a636d41ca8 ANDROID: Check thread origin when debugging GL
c8551b80dd GUI: Properly clear the screen buffer
a017cb3d00 GUI: Fix two-step rendering


Commit: 257913676d5a21c6192a6146e662c21f299c9b09
    https://github.com/scummvm/scummvm/commit/257913676d5a21c6192a6146e662c21f299c9b09
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:31-08:00

Commit Message:
ANDROID: Split code into multiple files

And get rid of unnecessary JNI calls to get a pointer to g_system

Changed paths:
  A backends/platform/android/gfx.cpp
  A backends/platform/android/jni.cpp
  A backends/platform/android/texture.cpp
  A backends/platform/android/texture.h
  R backends/platform/android/video.cpp
  R backends/platform/android/video.h
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/module.mk



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index c49745f..a0a5347 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -25,22 +25,10 @@
 
 #if defined(__ANDROID__)
 
-#include "backends/base-backend.h"
-#include "base/main.h"
-#include "graphics/surface.h"
-
-#include "backends/platform/android/android.h"
-#include "backends/platform/android/video.h"
-
-#include <jni.h>
-
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
 #include <sys/time.h>
 #include <time.h>
+#include <unistd.h>
 
-#include "common/archive.h"
 #include "common/util.h"
 #include "common/rect.h"
 #include "common/queue.h"
@@ -48,13 +36,11 @@
 #include "common/events.h"
 #include "common/config-manager.h"
 
-#include "backends/fs/posix/posix-fs-factory.h"
 #include "backends/keymapper/keymapper.h"
 #include "backends/saves/default/default-saves.h"
 #include "backends/timer/default/default-timer.h"
-#include "backends/plugins/posix/posix-provider.h"
-#include "audio/mixer_intern.h"
 
+#include "backends/platform/android/android.h"
 #include "backends/platform/android/asset-archive.h"
 
 const char *android_log_tag = "ScummVM";
@@ -106,226 +92,13 @@ void checkGlError(const char *expr, const char *file, int line) {
 }
 #endif
 
-static JavaVM *cached_jvm;
-static jfieldID FID_Event_type;
-static jfieldID FID_Event_synthetic;
-static jfieldID FID_Event_kbd_keycode;
-static jfieldID FID_Event_kbd_ascii;
-static jfieldID FID_Event_kbd_flags;
-static jfieldID FID_Event_mouse_x;
-static jfieldID FID_Event_mouse_y;
-static jfieldID FID_Event_mouse_relative;
-static jfieldID FID_ScummVM_nativeScummVM;
-static jmethodID MID_Object_wait;
-
-JNIEnv *JNU_GetEnv() {
-	JNIEnv *env = 0;
-
-	jint res = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
-
-	if (res != JNI_OK) {
-		LOGE("GetEnv() failed: %d", res);
-		abort();
-	}
-
-	return env;
-}
-
-static void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
-	jclass cls = env->FindClass(name);
-
-	// if cls is 0, an exception has already been thrown
-	if (cls != 0)
-		env->ThrowNew(cls, msg);
-
-	env->DeleteLocalRef(cls);
-}
-
 // floating point. use sparingly
 template <class T>
 static inline T scalef(T in, float numerator, float denominator) {
 	return static_cast<float>(in) * numerator / denominator;
 }
 
-static inline GLfixed xdiv(int numerator, int denominator) {
-	assert(numerator < (1 << 16));
-	return (numerator << 16) / denominator;
-}
-
-#ifdef DYNAMIC_MODULES
-class AndroidPluginProvider : public POSIXPluginProvider {
-protected:
-	virtual void addCustomDirectories(Common::FSList &dirs) const;
-};
-#endif
-
-class OSystem_Android : public BaseBackend, public PaletteManager {
-private:
-	// back pointer to (java) peer instance
-	jobject _back_ptr;
-
-	jmethodID MID_displayMessageOnOSD;
-	jmethodID MID_setWindowCaption;
-	jmethodID MID_initBackend;
-	jmethodID MID_audioSampleRate;
-	jmethodID MID_showVirtualKeyboard;
-	jmethodID MID_getSysArchives;
-	jmethodID MID_getPluginDirectories;
-	jmethodID MID_setupScummVMSurface;
-	jmethodID MID_destroyScummVMSurface;
-	jmethodID MID_swapBuffers;
-
-	int _screen_changeid;
-	int _egl_surface_width;
-	int _egl_surface_height;
-
-	bool _force_redraw;
-
-	// Game layer
-	GLESPaletteTexture *_game_texture;
-	int _shake_offset;
-	Common::Rect _focus_rect;
-
-	// Overlay layer
-	GLES4444Texture *_overlay_texture;
-	bool _show_overlay;
-
-	// Mouse layer
-	GLESPaletteATexture *_mouse_texture;
-	Common::Point _mouse_hotspot;
-	int _mouse_targetscale;
-	bool _show_mouse;
-	bool _use_mouse_palette;
-
-	Common::Queue<Common::Event> _event_queue;
-	MutexRef _event_queue_lock;
-
-	bool _timer_thread_exit;
-	pthread_t _timer_thread;
-	static void *timerThreadFunc(void *arg);
-
-	bool _enable_zoning;
-	bool _virtkeybd_on;
-
-	Common::SaveFileManager *_savefile;
-	Audio::MixerImpl *_mixer;
-	Common::TimerManager *_timer;
-	FilesystemFactory *_fsFactory;
-	Common::Archive *_asset_archive;
-	timeval _startTime;
-
-	void setupScummVMSurface();
-	void destroyScummVMSurface();
-	void setupKeymapper();
-	void _setCursorPalette(const byte *colors, uint start, uint num);
-
-public:
-	OSystem_Android(jobject am);
-	virtual ~OSystem_Android();
-	bool initJavaHooks(JNIEnv *env, jobject self);
-
-	static OSystem_Android *fromJavaObject(JNIEnv *env, jobject obj);
-	virtual void initBackend();
-	void addPluginDirectories(Common::FSList &dirs) const;
-	void enableZoning(bool enable) { _enable_zoning = enable; }
-	void setSurfaceSize(int width, int height) {
-		_egl_surface_width = width;
-		_egl_surface_height = height;
-	}
-
-	virtual bool hasFeature(Feature f);
-	virtual void setFeatureState(Feature f, bool enable);
-	virtual bool getFeatureState(Feature f);
-	virtual const GraphicsMode *getSupportedGraphicsModes() const;
-	virtual int getDefaultGraphicsMode() const;
-	bool setGraphicsMode(const char *name);
-	virtual bool setGraphicsMode(int mode);
-	virtual int getGraphicsMode() const;
-	virtual void initSize(uint width, uint height,
-							const Graphics::PixelFormat *format);
-
-	virtual int getScreenChangeID() const {
-		return _screen_changeid;
-	}
-
-	virtual int16 getHeight();
-	virtual int16 getWidth();
-
-	virtual PaletteManager *getPaletteManager() {
-		return this;
-	}
-
-protected:
-	// PaletteManager API
-	virtual void setPalette(const byte *colors, uint start, uint num);
-	virtual void grabPalette(byte *colors, uint start, uint num);
-
-public:
-	virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
-	virtual void updateScreen();
-	virtual Graphics::Surface *lockScreen();
-	virtual void unlockScreen();
-	virtual void setShakePos(int shakeOffset);
-	virtual void fillScreen(uint32 col);
-	virtual void setFocusRectangle(const Common::Rect& rect);
-	virtual void clearFocusRectangle();
-
-	virtual void showOverlay();
-	virtual void hideOverlay();
-	virtual void clearOverlay();
-	virtual void grabOverlay(OverlayColor *buf, int pitch);
-	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
-	virtual int16 getOverlayHeight();
-	virtual int16 getOverlayWidth();
-
-	// RGBA 4444
-	virtual Graphics::PixelFormat getOverlayFormat() const {
-		Graphics::PixelFormat format;
-
-		format.bytesPerPixel = 2;
-		format.rLoss = 8 - 4;
-		format.gLoss = 8 - 4;
-		format.bLoss = 8 - 4;
-		format.aLoss = 8 - 4;
-		format.rShift = 3 * 4;
-		format.gShift = 2 * 4;
-		format.bShift = 1 * 4;
-		format.aShift = 0 * 4;
-
-		return format;
-	}
-
-	virtual bool showMouse(bool visible);
-
-	virtual void warpMouse(int x, int y);
-	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
-	virtual void setCursorPalette(const byte *colors, uint start, uint num);
-	virtual void disableCursorPalette(bool disable);
-
-	virtual bool pollEvent(Common::Event &event);
-	void pushEvent(const Common::Event& event);
-	virtual uint32 getMillis();
-	virtual void delayMillis(uint msecs);
-
-	virtual MutexRef createMutex(void);
-	virtual void lockMutex(MutexRef mutex);
-	virtual void unlockMutex(MutexRef mutex);
-	virtual void deleteMutex(MutexRef mutex);
-
-	virtual void quit();
-
-	virtual void setWindowCaption(const char *caption);
-	virtual void displayMessageOnOSD(const char *msg);
-	virtual void showVirtualKeyboard(bool enable);
-
-	virtual Common::SaveFileManager *getSavefileManager();
-	virtual Audio::Mixer *getMixer();
-	virtual void getTimeAndDate(TimeDate &t) const;
-	virtual Common::TimerManager *getTimerManager();
-	virtual FilesystemFactory *getFilesystemFactory();
-	virtual void logMessage(LogMessageType::Type type, const char *message);
-	virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
-};
+OSystem_Android *g_sys = 0;
 
 OSystem_Android::OSystem_Android(jobject am) :
 	_back_ptr(0),
@@ -357,6 +130,7 @@ OSystem_Android::~OSystem_Android() {
 	destroyScummVMSurface();
 
 	JNIEnv *env = JNU_GetEnv();
+	// see below
 	//env->DeleteWeakGlobalRef(_back_ptr);
 	env->DeleteGlobalRef(_back_ptr);
 
@@ -369,14 +143,9 @@ OSystem_Android::~OSystem_Android() {
 	deleteMutex(_event_queue_lock);
 }
 
-OSystem_Android *OSystem_Android::fromJavaObject(JNIEnv *env, jobject obj) {
-	jlong peer = env->GetLongField(obj, FID_ScummVM_nativeScummVM);
-	return (OSystem_Android *)peer;
-}
-
 bool OSystem_Android::initJavaHooks(JNIEnv *env, jobject self) {
 	// weak global ref to allow class to be unloaded
-	// ... except dalvik doesn't implement NewWeakGlobalRef (yet)
+	// ... except dalvik implements NewWeakGlobalRef only on froyo
 	//_back_ptr = env->NewWeakGlobalRef(self);
 	_back_ptr = env->NewGlobalRef(self);
 
@@ -404,91 +173,11 @@ bool OSystem_Android::initJavaHooks(JNIEnv *env, jobject self) {
 	return true;
 }
 
-static void ScummVM_create(JNIEnv *env, jobject self, jobject am) {
-	OSystem_Android *cpp_obj = new OSystem_Android(am);
-
-	// Exception already thrown by initJavaHooks?
-	if (!cpp_obj->initJavaHooks(env, self))
-		return;
-
-	env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)cpp_obj);
-
-#ifdef DYNAMIC_MODULES
-	PluginManager::instance().addPluginProvider(new AndroidPluginProvider());
-#endif
-}
-
-static void ScummVM_nativeDestroy(JNIEnv *env, jobject self) {
-	OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-	delete cpp_obj;
-}
-
-static void ScummVM_audioMixCallback(JNIEnv *env, jobject self,
-										jbyteArray jbuf) {
-	OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-	jsize len = env->GetArrayLength(jbuf);
-	jbyte *buf = env->GetByteArrayElements(jbuf, 0);
-
-	if (buf == 0) {
-		warning("Unable to get Java audio byte array. Skipping");
-		return;
-	}
-
-	Audio::MixerImpl *mixer =
-		static_cast<Audio::MixerImpl *>(cpp_obj->getMixer());
-	assert(mixer);
-	mixer->mixCallback(reinterpret_cast<byte *>(buf), len);
-
-	env->ReleaseByteArrayElements(jbuf, buf, 0);
-}
-
-static void ScummVM_setConfManInt(JNIEnv *env, jclass cls,
-									jstring key_obj, jint value) {
-	ENTER("%p, %d", key_obj, (int)value);
-
-	const char *key = env->GetStringUTFChars(key_obj, 0);
-
-	if (key == 0)
-		return;
-
-	ConfMan.setInt(key, value);
-
-	env->ReleaseStringUTFChars(key_obj, key);
-}
-
-static void ScummVM_setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
-										jstring value_obj) {
-	ENTER("%p, %p", key_obj, value_obj);
-
-	const char *key = env->GetStringUTFChars(key_obj, 0);
-
-	if (key == 0)
-		return;
-
-	const char *value = env->GetStringUTFChars(value_obj, 0);
-
-	if (value == 0) {
-		env->ReleaseStringUTFChars(key_obj, key);
-		return;
-	}
-
-	ConfMan.set(key, value);
-
-	env->ReleaseStringUTFChars(value_obj, value);
-	env->ReleaseStringUTFChars(key_obj, key);
-}
-
 void *OSystem_Android::timerThreadFunc(void *arg) {
 	OSystem_Android *system = (OSystem_Android *)arg;
 	DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
 
-	JNIEnv *env = 0;
-	jint res = cached_jvm->AttachCurrentThread(&env, 0);
-
-	if (res != JNI_OK) {
-		LOGE("AttachCurrentThread() failed: %d", res);
-		abort();
-	}
+	JNU_AttachThread();
 
 	struct timespec tv;
 	tv.tv_sec = 0;
@@ -499,12 +188,7 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 		nanosleep(&tv, 0);
 	}
 
-	res = cached_jvm->DetachCurrentThread();
-
-	if (res != JNI_OK) {
-		LOGE("DetachCurrentThread() failed: %d", res);
-		abort();
-	}
+	JNU_DetachThread();
 
 	return 0;
 }
@@ -627,430 +311,6 @@ bool OSystem_Android::getFeatureState(Feature f) {
 	}
 }
 
-const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
-	static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
-		{ "default", "Default", 1 },
-		{ 0, 0, 0 },
-	};
-
-	return s_supportedGraphicsModes;
-}
-
-
-int OSystem_Android::getDefaultGraphicsMode() const {
-	return 1;
-}
-
-bool OSystem_Android::setGraphicsMode(const char *mode) {
-	ENTER("%s", mode);
-	return true;
-}
-
-bool OSystem_Android::setGraphicsMode(int mode) {
-	ENTER("%d", mode);
-	return true;
-}
-
-int OSystem_Android::getGraphicsMode() const {
-	return 1;
-}
-
-void OSystem_Android::setupScummVMSurface() {
-	ENTER();
-
-	JNIEnv *env = JNU_GetEnv();
-	env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
-
-	if (env->ExceptionCheck())
-		return;
-
-	// EGL set up with a new surface.  Initialise OpenGLES context.
-	GLESTexture::initGLExtensions();
-
-	// Turn off anything that looks like 3D ;)
-	GLCALL(glDisable(GL_CULL_FACE));
-	GLCALL(glDisable(GL_DEPTH_TEST));
-	GLCALL(glDisable(GL_LIGHTING));
-	GLCALL(glDisable(GL_FOG));
-	GLCALL(glDisable(GL_DITHER));
-
-	GLCALL(glShadeModel(GL_FLAT));
-	GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
-
-	GLCALL(glEnable(GL_BLEND));
-	GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
-
-	GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
-	GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
-
-	GLCALL(glEnable(GL_TEXTURE_2D));
-
-	if (!_game_texture)
-		_game_texture = new GLESPaletteTexture();
-	else
-		_game_texture->reinitGL();
-
-	if (!_overlay_texture)
-		_overlay_texture = new GLES4444Texture();
-	else
-		_overlay_texture->reinitGL();
-
-	if (!_mouse_texture)
-		_mouse_texture = new GLESPaletteATexture();
-	else
-		_mouse_texture->reinitGL();
-
-	GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
-
-	GLCALL(glMatrixMode(GL_PROJECTION));
-	GLCALL(glLoadIdentity());
-	GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1));
-	GLCALL(glMatrixMode(GL_MODELVIEW));
-	GLCALL(glLoadIdentity());
-
-	clearFocusRectangle();
-}
-
-void OSystem_Android::destroyScummVMSurface() {
-	JNIEnv *env = JNU_GetEnv();
-	env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
-	// Can't use OpenGLES functions after this
-}
-
-void OSystem_Android::initSize(uint width, uint height,
-								const Graphics::PixelFormat *format) {
-	ENTER("%d, %d, %p", width, height, format);
-
-	_game_texture->allocBuffer(width, height);
-
-	// Cap at 320x200 or the ScummVM themes abort :/
-	GLuint overlay_width = MIN(_egl_surface_width, 320);
-	GLuint overlay_height = MIN(_egl_surface_height, 200);
-	_overlay_texture->allocBuffer(overlay_width, overlay_height);
-
-	// Don't know mouse size yet - it gets reallocated in
-	// setMouseCursor.  We need the palette allocated before
-	// setMouseCursor however, so just take a guess at the desired
-	// size (it's small).
-	_mouse_texture->allocBuffer(20, 20);
-}
-
-int16 OSystem_Android::getHeight() {
-	return _game_texture->height();
-}
-
-int16 OSystem_Android::getWidth() {
-	return _game_texture->width();
-}
-
-void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
-	ENTER("%p, %u, %u", colors, start, num);
-
-	if (!_use_mouse_palette)
-		_setCursorPalette(colors, start, num);
-
-	memcpy(_game_texture->palette() + start * 3, colors, num * 3);
-}
-
-void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
-	ENTER("%p, %u, %u", colors, start, num);
-	memcpy(colors, _game_texture->palette_const() + start * 3, num * 3);
-}
-
-void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
-										int x, int y, int w, int h) {
-	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
-
-	_game_texture->updateBuffer(x, y, w, h, buf, pitch);
-}
-
-void OSystem_Android::updateScreen() {
-	//ENTER();
-
-	if (!_force_redraw &&
-			!_game_texture->dirty() &&
-			!_overlay_texture->dirty() &&
-			!_mouse_texture->dirty())
-		return;
-
-	_force_redraw = false;
-
-	GLCALL(glPushMatrix());
-
-	if (_shake_offset != 0 ||
-			(!_focus_rect.isEmpty() &&
-			!Common::Rect(_game_texture->width(),
-							_game_texture->height()).contains(_focus_rect))) {
-		// These are the only cases where _game_texture doesn't
-		// cover the entire screen.
-		GLCALL(glClearColorx(0, 0, 0, 1 << 16));
-		GLCALL(glClear(GL_COLOR_BUFFER_BIT));
-
-		// Move everything up by _shake_offset (game) pixels
-		GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
-	}
-
-	if (_focus_rect.isEmpty()) {
-		_game_texture->drawTexture(0, 0,
-									_egl_surface_width, _egl_surface_height);
-	} else {
-		GLCALL(glPushMatrix());
-		GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
-						xdiv(_egl_surface_height, _focus_rect.height()),
-						1 << 16));
-		GLCALL(glTranslatex(-_focus_rect.left << 16,
-							-_focus_rect.top << 16, 0));
-		GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width),
-						xdiv(_game_texture->height(), _egl_surface_height),
-						1 << 16));
-
-		_game_texture->drawTexture(0, 0,
-									_egl_surface_width, _egl_surface_height);
-		GLCALL(glPopMatrix());
-	}
-
-	int cs = _mouse_targetscale;
-
-	if (_show_overlay) {
-		// ugly, but the modern theme sets a wacko factor, only god knows why
-		cs = 1;
-
-		GLCALL(_overlay_texture->drawTexture(0, 0,
-												_egl_surface_width,
-												_egl_surface_height));
-	}
-
-	if (_show_mouse) {
-		GLCALL(glPushMatrix());
-
-		// Scale up ScummVM -> OpenGL (pixel) coordinates
-		int texwidth, texheight;
-
-		if (_show_overlay) {
-			texwidth = getOverlayWidth();
-			texheight = getOverlayHeight();
-		} else {
-			texwidth = getWidth();
-			texheight = getHeight();
-		}
-
-		GLCALL(glScalex(xdiv(_egl_surface_width, texwidth),
-						xdiv(_egl_surface_height, texheight),
-						1 << 16));
-
-		GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
-							(-_mouse_hotspot.y * cs) << 16,
-							0));
-
-		// Note the extra half texel to position the mouse in
-		// the middle of the x,y square:
-		const Common::Point& mouse = getEventManager()->getMousePos();
-		GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
-							(mouse.y << 16) | 1 << 15, 0));
-
-		GLCALL(glScalex(cs << 16, cs << 16, 1 << 16));
-
-		_mouse_texture->drawTexture();
-
-		GLCALL(glPopMatrix());
-	}
-
-	GLCALL(glPopMatrix());
-
-	JNIEnv *env = JNU_GetEnv();
-	if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
-		// Context lost -> need to reinit GL
-		destroyScummVMSurface();
-		setupScummVMSurface();
-	}
-}
-
-Graphics::Surface *OSystem_Android::lockScreen() {
-	ENTER();
-
-	Graphics::Surface *surface = _game_texture->surface();
-	assert(surface->pixels);
-
-	return surface;
-}
-
-void OSystem_Android::unlockScreen() {
-	ENTER();
-
-	assert(_game_texture->dirty());
-}
-
-void OSystem_Android::setShakePos(int shake_offset) {
-	ENTER("%d", shake_offset);
-
-	if (_shake_offset != shake_offset) {
-		_shake_offset = shake_offset;
-		_force_redraw = true;
-	}
-}
-
-void OSystem_Android::fillScreen(uint32 col) {
-	ENTER("%u", col);
-
-	assert(col < 256);
-	_game_texture->fillBuffer(col);
-}
-
-void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
-	ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom);
-
-	if (_enable_zoning) {
-		_focus_rect = rect;
-		_force_redraw = true;
-	}
-}
-
-void OSystem_Android::clearFocusRectangle() {
-	ENTER();
-
-	if (_enable_zoning) {
-		_focus_rect = Common::Rect();
-		_force_redraw = true;
-	}
-}
-
-void OSystem_Android::showOverlay() {
-	ENTER();
-
-	_show_overlay = true;
-	_force_redraw = true;
-}
-
-void OSystem_Android::hideOverlay() {
-	ENTER();
-
-	_show_overlay = false;
-	_force_redraw = true;
-}
-
-void OSystem_Android::clearOverlay() {
-	ENTER();
-
-	_overlay_texture->fillBuffer(0);
-
-	// Shouldn't need this, but works around a 'blank screen' bug on Nexus1
-	updateScreen();
-}
-
-void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
-	ENTER("%p, %d", buf, pitch);
-
-	// We support overlay alpha blending, so the pixel data here
-	// shouldn't actually be used.	Let's fill it with zeros, I'm sure
-	// it will be fine...
-	const Graphics::Surface *surface = _overlay_texture->surface_const();
-	assert(surface->bytesPerPixel == sizeof(buf[0]));
-
-	int h = surface->h;
-
-	do {
-		memset(buf, 0, surface->w * sizeof(buf[0]));
-
-		// This 'pitch' is pixels not bytes
-		buf += pitch;
-	} while (--h);
-}
-
-void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
-										int x, int y, int w, int h) {
-	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
-
-	const Graphics::Surface *surface = _overlay_texture->surface_const();
-	assert(surface->bytesPerPixel == sizeof(buf[0]));
-
-	// This 'pitch' is pixels not bytes
-	_overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
-
-	// Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
-	updateScreen();
-}
-
-int16 OSystem_Android::getOverlayHeight() {
-	return _overlay_texture->height();
-}
-
-int16 OSystem_Android::getOverlayWidth() {
-	return _overlay_texture->width();
-}
-
-bool OSystem_Android::showMouse(bool visible) {
-	ENTER("%d", visible);
-
-	_show_mouse = visible;
-
-	return true;
-}
-
-void OSystem_Android::warpMouse(int x, int y) {
-	ENTER("%d, %d", x, y);
-
-	// We use only the eventmanager's idea of the current mouse
-	// position, so there is nothing extra to do here.
-}
-
-void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
-										int hotspotX, int hotspotY,
-										uint32 keycolor, int cursorTargetScale,
-										const Graphics::PixelFormat *format) {
-	ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
-			keycolor, cursorTargetScale, format);
-
-	assert(keycolor < 256);
-
-	_mouse_texture->allocBuffer(w, h);
-
-	// Update palette alpha based on keycolor
-	byte *palette = _mouse_texture->palette();
-	int i = 256;
-
-	do {
-		palette[3] = 0xff;
-		palette += 4;
-	} while (--i);
-
-	palette = _mouse_texture->palette();
-	palette[keycolor * 4 + 3] = 0x00;
-
-	_mouse_texture->updateBuffer(0, 0, w, h, buf, w);
-
-	_mouse_hotspot = Common::Point(hotspotX, hotspotY);
-	_mouse_targetscale = cursorTargetScale;
-}
-
-void OSystem_Android::_setCursorPalette(const byte *colors,
-										uint start, uint num) {
-	byte *palette = _mouse_texture->palette() + start * 4;
-
-	do {
-		for (int i = 0; i < 3; ++i)
-			palette[i] = colors[i];
-
-		// Leave alpha untouched to preserve keycolor
-
-		palette += 4;
-		colors += 3;
-	} while (--num);
-}
-
-void OSystem_Android::setCursorPalette(const byte *colors,
-										uint start, uint num) {
-	ENTER("%p, %u, %u", colors, start, num);
-
-	_setCursorPalette(colors, start, num);
-	_use_mouse_palette = true;
-}
-
-void OSystem_Android::disableCursorPalette(bool disable) {
-	ENTER("%d", disable);
-
-	_use_mouse_palette = !disable;
-}
-
 void OSystem_Android::setupKeymapper() {
 #ifdef ENABLE_KEYMAPPER
 	using namespace Common;
@@ -1168,52 +428,6 @@ void OSystem_Android::pushEvent(const Common::Event& event) {
 	unlockMutex(_event_queue_lock);
 }
 
-static void ScummVM_pushEvent(JNIEnv *env, jobject self, jobject java_event) {
-	OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-
-	Common::Event event;
-	event.type = (Common::EventType)env->GetIntField(java_event,
-														FID_Event_type);
-
-	event.synthetic =
-		env->GetBooleanField(java_event, FID_Event_synthetic);
-
-	switch (event.type) {
-	case Common::EVENT_KEYDOWN:
-	case Common::EVENT_KEYUP:
-		event.kbd.keycode = (Common::KeyCode)env->GetIntField(
-			java_event, FID_Event_kbd_keycode);
-		event.kbd.ascii = static_cast<int>(env->GetIntField(
-			java_event, FID_Event_kbd_ascii));
-		event.kbd.flags = static_cast<int>(env->GetIntField(
-			java_event, FID_Event_kbd_flags));
-		break;
-	case Common::EVENT_MOUSEMOVE:
-	case Common::EVENT_LBUTTONDOWN:
-	case Common::EVENT_LBUTTONUP:
-	case Common::EVENT_RBUTTONDOWN:
-	case Common::EVENT_RBUTTONUP:
-	case Common::EVENT_WHEELUP:
-	case Common::EVENT_WHEELDOWN:
-	case Common::EVENT_MBUTTONDOWN:
-	case Common::EVENT_MBUTTONUP:
-		event.mouse.x =
-			env->GetIntField(java_event, FID_Event_mouse_x);
-		event.mouse.y =
-			env->GetIntField(java_event, FID_Event_mouse_y);
-		// This is a terrible hack.	 We stash "relativeness"
-		// in the kbd.flags field until pollEvent() can work
-		// it out.
-		event.kbd.flags = env->GetBooleanField(
-			java_event, FID_Event_mouse_relative) ? 1 : 0;
-		break;
-	default:
-		break;
-	}
-
-	cpp_obj->pushEvent(event);
-}
-
 uint32 OSystem_Android::getMillis() {
 	timeval curTime;
 
@@ -1401,177 +615,11 @@ void OSystem_Android::logMessage(LogMessageType::Type type, const char *message)
 	}
 }
 
-static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) {
-	OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-
-	const int MAX_NARGS = 32;
-	int res = -1;
-
-	int argc = env->GetArrayLength(args);
-	if (argc > MAX_NARGS) {
-		JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
-						"too many arguments");
-		return 0;
-	}
-
-	char *argv[MAX_NARGS];
-
-	// note use in cleanup loop below
-	int nargs;
-
-	for (nargs = 0; nargs < argc; ++nargs) {
-		jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
-
-		if (arg == 0) {
-			argv[nargs] = 0;
-		} else {
-			const char *cstr = env->GetStringUTFChars(arg, 0);
-
-			argv[nargs] = const_cast<char *>(cstr);
-
-			// exception already thrown?
-			if (cstr == 0)
-				goto cleanup;
-		}
-
-		env->DeleteLocalRef(arg);
-	}
-
-	g_system = cpp_obj;
-	assert(g_system);
-
-	LOGI("Entering scummvm_main with %d args", argc);
-
-	res = scummvm_main(argc, argv);
-
-	LOGI("Exiting scummvm_main");
-
-	g_system->quit();
-
-cleanup:
-	nargs--;
-
-	for (int i = 0; i < nargs; ++i) {
-		if (argv[i] == 0)
-			continue;
-
-		jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
-
-		// Exception already thrown?
-		if (arg == 0)
-			return res;
-
-		env->ReleaseStringUTFChars(arg, argv[i]);
-		env->DeleteLocalRef(arg);
-	}
-
-	return res;
-}
-
 #ifdef DYNAMIC_MODULES
 void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
-	OSystem_Android *g_system_android = (OSystem_Android *)g_system;
-	g_system_android->addPluginDirectories(dirs);
+	g_sys->addPluginDirectories(dirs);
 }
 #endif
 
-static void ScummVM_enableZoning(JNIEnv *env, jobject self, jboolean enable) {
-	OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-	cpp_obj->enableZoning(enable);
-}
-
-static void ScummVM_setSurfaceSize(JNIEnv *env, jobject self,
-									jint width, jint height) {
-	OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-	cpp_obj->setSurfaceSize(width, height);
-}
-
-const static JNINativeMethod gMethods[] = {
-	{ "create", "(Landroid/content/res/AssetManager;)V",
-		(void *)ScummVM_create },
-	{ "nativeDestroy", "()V",
-		(void *)ScummVM_nativeDestroy },
-	{ "scummVMMain", "([Ljava/lang/String;)I",
-	 	(void *)ScummVM_scummVMMain },
-	{ "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
-		(void *)ScummVM_pushEvent },
-	{ "audioMixCallback", "([B)V",
-		(void *)ScummVM_audioMixCallback },
-	{ "setConfMan", "(Ljava/lang/String;I)V",
-		(void *)ScummVM_setConfManInt },
-	{ "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
-		(void *)ScummVM_setConfManString },
-	{ "enableZoning", "(Z)V",
-		(void *)ScummVM_enableZoning },
-	{ "setSurfaceSize", "(II)V",
-		(void *)ScummVM_setSurfaceSize },
-};
-
-JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *jvm, void *reserved) {
-	cached_jvm = jvm;
-
-	JNIEnv *env;
-
-	if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2))
-		return JNI_ERR;
-
-	jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
-	if (cls == 0)
-		return JNI_ERR;
-
-	if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0)
-		return JNI_ERR;
-
-	FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
-	if (FID_ScummVM_nativeScummVM == 0)
-		return JNI_ERR;
-
-	jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
-	if (event == 0)
-		return JNI_ERR;
-
-	FID_Event_type = env->GetFieldID(event, "type", "I");
-	if (FID_Event_type == 0)
-		return JNI_ERR;
-
-	FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
-	if (FID_Event_synthetic == 0)
-		return JNI_ERR;
-
-	FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
-	if (FID_Event_kbd_keycode == 0)
-		return JNI_ERR;
-
-	FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
-	if (FID_Event_kbd_ascii == 0)
-		return JNI_ERR;
-
-	FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
-	if (FID_Event_kbd_flags == 0)
-		return JNI_ERR;
-
-	FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
-	if (FID_Event_mouse_x == 0)
-		return JNI_ERR;
-
-	FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
-	if (FID_Event_mouse_y == 0)
-		return JNI_ERR;
-
-	FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
-	if (FID_Event_mouse_relative == 0)
-		return JNI_ERR;
-
-	cls = env->FindClass("java/lang/Object");
-	if (cls == 0)
-		return JNI_ERR;
-
-	MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
-	if (MID_Object_wait == 0)
-		return JNI_ERR;
-
-	return JNI_VERSION_1_2;
-}
-
 #endif
+
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 855fb04..b31c0fd 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -23,8 +23,24 @@
  *
  */
 
+#ifndef _ANDROID_H_
+#define _ANDROID_H_
+
 #if defined(__ANDROID__)
 
+#include "common/fs.h"
+#include "common/archive.h"
+#include "audio/mixer_intern.h"
+#include "graphics/surface.h"
+#include "backends/base-backend.h"
+#include "backends/plugins/posix/posix-provider.h"
+#include "backends/fs/posix/posix-fs-factory.h"
+
+#include "backends/platform/android/texture.h"
+
+#include <pthread.h>
+
+#include <jni.h>
 #include <android/log.h>
 
 #include <GLES/gl.h>
@@ -62,9 +78,187 @@ extern void checkGlError(const char *expr, const char *file, int line);
 #define GLCALL(x) do { (x); } while (false)
 #endif
 
-// Fix JNIEXPORT declaration to actually do something useful
-#undef JNIEXPORT
-#define JNIEXPORT __attribute__ ((visibility("default")))
+extern JNIEnv *JNU_GetEnv();
+extern void JNU_AttachThread();
+extern void JNU_DetachThread();
+
+class OSystem_Android;
+extern OSystem_Android *g_sys;
+
+#ifdef DYNAMIC_MODULES
+class AndroidPluginProvider : public POSIXPluginProvider {
+protected:
+	virtual void addCustomDirectories(Common::FSList &dirs) const;
+};
+#endif
+
+class OSystem_Android : public BaseBackend, public PaletteManager {
+private:
+	// back pointer to (java) peer instance
+	jobject _back_ptr;
+
+	jmethodID MID_displayMessageOnOSD;
+	jmethodID MID_setWindowCaption;
+	jmethodID MID_initBackend;
+	jmethodID MID_audioSampleRate;
+	jmethodID MID_showVirtualKeyboard;
+	jmethodID MID_getSysArchives;
+	jmethodID MID_getPluginDirectories;
+	jmethodID MID_setupScummVMSurface;
+	jmethodID MID_destroyScummVMSurface;
+	jmethodID MID_swapBuffers;
+
+	int _screen_changeid;
+	int _egl_surface_width;
+	int _egl_surface_height;
+
+	bool _force_redraw;
+
+	// Game layer
+	GLESPaletteTexture *_game_texture;
+	int _shake_offset;
+	Common::Rect _focus_rect;
+
+	// Overlay layer
+	GLES4444Texture *_overlay_texture;
+	bool _show_overlay;
+
+	// Mouse layer
+	GLESPaletteATexture *_mouse_texture;
+	Common::Point _mouse_hotspot;
+	int _mouse_targetscale;
+	bool _show_mouse;
+	bool _use_mouse_palette;
+
+	Common::Queue<Common::Event> _event_queue;
+	MutexRef _event_queue_lock;
+
+	bool _timer_thread_exit;
+	pthread_t _timer_thread;
+	static void *timerThreadFunc(void *arg);
+
+	bool _enable_zoning;
+	bool _virtkeybd_on;
+
+	Common::SaveFileManager *_savefile;
+	Audio::MixerImpl *_mixer;
+	Common::TimerManager *_timer;
+	FilesystemFactory *_fsFactory;
+	Common::Archive *_asset_archive;
+	timeval _startTime;
+
+	void setupScummVMSurface();
+	void destroyScummVMSurface();
+	void setupKeymapper();
+	void _setCursorPalette(const byte *colors, uint start, uint num);
+
+public:
+	OSystem_Android(jobject am);
+	virtual ~OSystem_Android();
+	bool initJavaHooks(JNIEnv *env, jobject self);
 
+	virtual void initBackend();
+	void addPluginDirectories(Common::FSList &dirs) const;
+	void enableZoning(bool enable) { _enable_zoning = enable; }
+	void setSurfaceSize(int width, int height) {
+		_egl_surface_width = width;
+		_egl_surface_height = height;
+	}
+
+	virtual bool hasFeature(Feature f);
+	virtual void setFeatureState(Feature f, bool enable);
+	virtual bool getFeatureState(Feature f);
+	virtual const GraphicsMode *getSupportedGraphicsModes() const;
+	virtual int getDefaultGraphicsMode() const;
+	bool setGraphicsMode(const char *name);
+	virtual bool setGraphicsMode(int mode);
+	virtual int getGraphicsMode() const;
+	virtual void initSize(uint width, uint height,
+							const Graphics::PixelFormat *format);
+
+	virtual int getScreenChangeID() const {
+		return _screen_changeid;
+	}
+
+	virtual int16 getHeight();
+	virtual int16 getWidth();
+
+	virtual PaletteManager *getPaletteManager() {
+		return this;
+	}
+
+protected:
+	// PaletteManager API
+	virtual void setPalette(const byte *colors, uint start, uint num);
+	virtual void grabPalette(byte *colors, uint start, uint num);
+
+public:
+	virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
+	virtual void updateScreen();
+	virtual Graphics::Surface *lockScreen();
+	virtual void unlockScreen();
+	virtual void setShakePos(int shakeOffset);
+	virtual void fillScreen(uint32 col);
+	virtual void setFocusRectangle(const Common::Rect& rect);
+	virtual void clearFocusRectangle();
+
+	virtual void showOverlay();
+	virtual void hideOverlay();
+	virtual void clearOverlay();
+	virtual void grabOverlay(OverlayColor *buf, int pitch);
+	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
+	virtual int16 getOverlayHeight();
+	virtual int16 getOverlayWidth();
+
+	// RGBA 4444
+	virtual Graphics::PixelFormat getOverlayFormat() const {
+		Graphics::PixelFormat format;
+
+		format.bytesPerPixel = 2;
+		format.rLoss = 8 - 4;
+		format.gLoss = 8 - 4;
+		format.bLoss = 8 - 4;
+		format.aLoss = 8 - 4;
+		format.rShift = 3 * 4;
+		format.gShift = 2 * 4;
+		format.bShift = 1 * 4;
+		format.aShift = 0 * 4;
+
+		return format;
+	}
+
+	virtual bool showMouse(bool visible);
+
+	virtual void warpMouse(int x, int y);
+	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
+	virtual void setCursorPalette(const byte *colors, uint start, uint num);
+	virtual void disableCursorPalette(bool disable);
+
+	virtual bool pollEvent(Common::Event &event);
+	void pushEvent(const Common::Event& event);
+	virtual uint32 getMillis();
+	virtual void delayMillis(uint msecs);
+
+	virtual MutexRef createMutex(void);
+	virtual void lockMutex(MutexRef mutex);
+	virtual void unlockMutex(MutexRef mutex);
+	virtual void deleteMutex(MutexRef mutex);
+
+	virtual void quit();
+
+	virtual void setWindowCaption(const char *caption);
+	virtual void displayMessageOnOSD(const char *msg);
+	virtual void showVirtualKeyboard(bool enable);
+
+	virtual Common::SaveFileManager *getSavefileManager();
+	virtual Audio::Mixer *getMixer();
+	virtual void getTimeAndDate(TimeDate &t) const;
+	virtual Common::TimerManager *getTimerManager();
+	virtual FilesystemFactory *getFilesystemFactory();
+	virtual void logMessage(LogMessageType::Type type, const char *message);
+	virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+};
+
+#endif
 #endif
 
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
new file mode 100644
index 0000000..eb5a66c
--- /dev/null
+++ b/backends/platform/android/gfx.cpp
@@ -0,0 +1,459 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "backends/platform/android/android.h"
+
+static inline GLfixed xdiv(int numerator, int denominator) {
+	assert(numerator < (1 << 16));
+	return (numerator << 16) / denominator;
+}
+
+const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
+	static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
+		{ "default", "Default", 1 },
+		{ 0, 0, 0 },
+	};
+
+	return s_supportedGraphicsModes;
+}
+
+int OSystem_Android::getDefaultGraphicsMode() const {
+	return 1;
+}
+
+bool OSystem_Android::setGraphicsMode(const char *mode) {
+	ENTER("%s", mode);
+	return true;
+}
+
+bool OSystem_Android::setGraphicsMode(int mode) {
+	ENTER("%d", mode);
+	return true;
+}
+
+int OSystem_Android::getGraphicsMode() const {
+	return 1;
+}
+
+void OSystem_Android::setupScummVMSurface() {
+	ENTER();
+
+	JNIEnv *env = JNU_GetEnv();
+	env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
+
+	if (env->ExceptionCheck())
+		return;
+
+	// EGL set up with a new surface.  Initialise OpenGLES context.
+	GLESTexture::initGLExtensions();
+
+	// Turn off anything that looks like 3D ;)
+	GLCALL(glDisable(GL_CULL_FACE));
+	GLCALL(glDisable(GL_DEPTH_TEST));
+	GLCALL(glDisable(GL_LIGHTING));
+	GLCALL(glDisable(GL_FOG));
+	GLCALL(glDisable(GL_DITHER));
+
+	GLCALL(glShadeModel(GL_FLAT));
+	GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
+
+	GLCALL(glEnable(GL_BLEND));
+	GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+
+	GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
+	GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
+
+	GLCALL(glEnable(GL_TEXTURE_2D));
+
+	if (!_game_texture)
+		_game_texture = new GLESPaletteTexture();
+	else
+		_game_texture->reinitGL();
+
+	if (!_overlay_texture)
+		_overlay_texture = new GLES4444Texture();
+	else
+		_overlay_texture->reinitGL();
+
+	if (!_mouse_texture)
+		_mouse_texture = new GLESPaletteATexture();
+	else
+		_mouse_texture->reinitGL();
+
+	GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
+
+	GLCALL(glMatrixMode(GL_PROJECTION));
+	GLCALL(glLoadIdentity());
+	GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1));
+	GLCALL(glMatrixMode(GL_MODELVIEW));
+	GLCALL(glLoadIdentity());
+
+	clearFocusRectangle();
+}
+
+void OSystem_Android::destroyScummVMSurface() {
+	JNIEnv *env = JNU_GetEnv();
+	env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
+	// Can't use OpenGLES functions after this
+}
+
+void OSystem_Android::initSize(uint width, uint height,
+								const Graphics::PixelFormat *format) {
+	ENTER("%d, %d, %p", width, height, format);
+
+	_game_texture->allocBuffer(width, height);
+
+	// Cap at 320x200 or the ScummVM themes abort :/
+	GLuint overlay_width = MIN(_egl_surface_width, 320);
+	GLuint overlay_height = MIN(_egl_surface_height, 200);
+	_overlay_texture->allocBuffer(overlay_width, overlay_height);
+
+	// Don't know mouse size yet - it gets reallocated in
+	// setMouseCursor.  We need the palette allocated before
+	// setMouseCursor however, so just take a guess at the desired
+	// size (it's small).
+	_mouse_texture->allocBuffer(20, 20);
+}
+
+int16 OSystem_Android::getHeight() {
+	return _game_texture->height();
+}
+
+int16 OSystem_Android::getWidth() {
+	return _game_texture->width();
+}
+
+void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
+	ENTER("%p, %u, %u", colors, start, num);
+
+	if (!_use_mouse_palette)
+		_setCursorPalette(colors, start, num);
+
+	memcpy(_game_texture->palette() + start * 3, colors, num * 3);
+}
+
+void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
+	ENTER("%p, %u, %u", colors, start, num);
+	memcpy(colors, _game_texture->palette_const() + start * 3, num * 3);
+}
+
+void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
+										int x, int y, int w, int h) {
+	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
+
+	_game_texture->updateBuffer(x, y, w, h, buf, pitch);
+}
+
+void OSystem_Android::updateScreen() {
+	//ENTER();
+
+	if (!_force_redraw &&
+			!_game_texture->dirty() &&
+			!_overlay_texture->dirty() &&
+			!_mouse_texture->dirty())
+		return;
+
+	_force_redraw = false;
+
+	GLCALL(glPushMatrix());
+
+	if (_shake_offset != 0 ||
+			(!_focus_rect.isEmpty() &&
+			!Common::Rect(_game_texture->width(),
+							_game_texture->height()).contains(_focus_rect))) {
+		// These are the only cases where _game_texture doesn't
+		// cover the entire screen.
+		GLCALL(glClearColorx(0, 0, 0, 1 << 16));
+		GLCALL(glClear(GL_COLOR_BUFFER_BIT));
+
+		// Move everything up by _shake_offset (game) pixels
+		GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
+	}
+
+	if (_focus_rect.isEmpty()) {
+		_game_texture->drawTexture(0, 0,
+									_egl_surface_width, _egl_surface_height);
+	} else {
+		GLCALL(glPushMatrix());
+		GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
+						xdiv(_egl_surface_height, _focus_rect.height()),
+						1 << 16));
+		GLCALL(glTranslatex(-_focus_rect.left << 16,
+							-_focus_rect.top << 16, 0));
+		GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width),
+						xdiv(_game_texture->height(), _egl_surface_height),
+						1 << 16));
+
+		_game_texture->drawTexture(0, 0,
+									_egl_surface_width, _egl_surface_height);
+		GLCALL(glPopMatrix());
+	}
+
+	int cs = _mouse_targetscale;
+
+	if (_show_overlay) {
+		// ugly, but the modern theme sets a wacko factor, only god knows why
+		cs = 1;
+
+		GLCALL(_overlay_texture->drawTexture(0, 0,
+												_egl_surface_width,
+												_egl_surface_height));
+	}
+
+	if (_show_mouse) {
+		GLCALL(glPushMatrix());
+
+		// Scale up ScummVM -> OpenGL (pixel) coordinates
+		int texwidth, texheight;
+
+		if (_show_overlay) {
+			texwidth = getOverlayWidth();
+			texheight = getOverlayHeight();
+		} else {
+			texwidth = getWidth();
+			texheight = getHeight();
+		}
+
+		GLCALL(glScalex(xdiv(_egl_surface_width, texwidth),
+						xdiv(_egl_surface_height, texheight),
+						1 << 16));
+
+		GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
+							(-_mouse_hotspot.y * cs) << 16,
+							0));
+
+		// Note the extra half texel to position the mouse in
+		// the middle of the x,y square:
+		const Common::Point& mouse = getEventManager()->getMousePos();
+		GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
+							(mouse.y << 16) | 1 << 15, 0));
+
+		GLCALL(glScalex(cs << 16, cs << 16, 1 << 16));
+
+		_mouse_texture->drawTexture();
+
+		GLCALL(glPopMatrix());
+	}
+
+	GLCALL(glPopMatrix());
+
+	JNIEnv *env = JNU_GetEnv();
+	if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
+		// Context lost -> need to reinit GL
+		destroyScummVMSurface();
+		setupScummVMSurface();
+	}
+}
+
+Graphics::Surface *OSystem_Android::lockScreen() {
+	ENTER();
+
+	Graphics::Surface *surface = _game_texture->surface();
+	assert(surface->pixels);
+
+	return surface;
+}
+
+void OSystem_Android::unlockScreen() {
+	ENTER();
+
+	assert(_game_texture->dirty());
+}
+
+void OSystem_Android::setShakePos(int shake_offset) {
+	ENTER("%d", shake_offset);
+
+	if (_shake_offset != shake_offset) {
+		_shake_offset = shake_offset;
+		_force_redraw = true;
+	}
+}
+
+void OSystem_Android::fillScreen(uint32 col) {
+	ENTER("%u", col);
+
+	assert(col < 256);
+	_game_texture->fillBuffer(col);
+}
+
+void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
+	ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom);
+
+	if (_enable_zoning) {
+		_focus_rect = rect;
+		_force_redraw = true;
+	}
+}
+
+void OSystem_Android::clearFocusRectangle() {
+	ENTER();
+
+	if (_enable_zoning) {
+		_focus_rect = Common::Rect();
+		_force_redraw = true;
+	}
+}
+
+void OSystem_Android::showOverlay() {
+	ENTER();
+
+	_show_overlay = true;
+	_force_redraw = true;
+}
+
+void OSystem_Android::hideOverlay() {
+	ENTER();
+
+	_show_overlay = false;
+	_force_redraw = true;
+}
+
+void OSystem_Android::clearOverlay() {
+	ENTER();
+
+	_overlay_texture->fillBuffer(0);
+
+	// Shouldn't need this, but works around a 'blank screen' bug on Nexus1
+	updateScreen();
+}
+
+void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
+	ENTER("%p, %d", buf, pitch);
+
+	// We support overlay alpha blending, so the pixel data here
+	// shouldn't actually be used.	Let's fill it with zeros, I'm sure
+	// it will be fine...
+	const Graphics::Surface *surface = _overlay_texture->surface_const();
+	assert(surface->bytesPerPixel == sizeof(buf[0]));
+
+	int h = surface->h;
+
+	do {
+		memset(buf, 0, surface->w * sizeof(buf[0]));
+
+		// This 'pitch' is pixels not bytes
+		buf += pitch;
+	} while (--h);
+}
+
+void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
+										int x, int y, int w, int h) {
+	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
+
+	const Graphics::Surface *surface = _overlay_texture->surface_const();
+	assert(surface->bytesPerPixel == sizeof(buf[0]));
+
+	// This 'pitch' is pixels not bytes
+	_overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
+
+	// Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
+	updateScreen();
+}
+
+int16 OSystem_Android::getOverlayHeight() {
+	return _overlay_texture->height();
+}
+
+int16 OSystem_Android::getOverlayWidth() {
+	return _overlay_texture->width();
+}
+
+bool OSystem_Android::showMouse(bool visible) {
+	ENTER("%d", visible);
+
+	_show_mouse = visible;
+
+	return true;
+}
+
+void OSystem_Android::warpMouse(int x, int y) {
+	ENTER("%d, %d", x, y);
+
+	// We use only the eventmanager's idea of the current mouse
+	// position, so there is nothing extra to do here.
+}
+
+void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
+										int hotspotX, int hotspotY,
+										uint32 keycolor, int cursorTargetScale,
+										const Graphics::PixelFormat *format) {
+	ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
+			keycolor, cursorTargetScale, format);
+
+	assert(keycolor < 256);
+
+	_mouse_texture->allocBuffer(w, h);
+
+	// Update palette alpha based on keycolor
+	byte *palette = _mouse_texture->palette();
+	int i = 256;
+
+	do {
+		palette[3] = 0xff;
+		palette += 4;
+	} while (--i);
+
+	palette = _mouse_texture->palette();
+	palette[keycolor * 4 + 3] = 0x00;
+
+	_mouse_texture->updateBuffer(0, 0, w, h, buf, w);
+
+	_mouse_hotspot = Common::Point(hotspotX, hotspotY);
+	_mouse_targetscale = cursorTargetScale;
+}
+
+void OSystem_Android::_setCursorPalette(const byte *colors,
+										uint start, uint num) {
+	byte *palette = _mouse_texture->palette() + start * 4;
+
+	do {
+		for (int i = 0; i < 3; ++i)
+			palette[i] = colors[i];
+
+		// Leave alpha untouched to preserve keycolor
+
+		palette += 4;
+		colors += 3;
+	} while (--num);
+}
+
+void OSystem_Android::setCursorPalette(const byte *colors,
+										uint start, uint num) {
+	ENTER("%p, %u, %u", colors, start, num);
+
+	_setCursorPalette(colors, start, num);
+	_use_mouse_palette = true;
+}
+
+void OSystem_Android::disableCursorPalette(bool disable) {
+	ENTER("%d", disable);
+
+	_use_mouse_palette = !disable;
+}
+
+#endif
+
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
new file mode 100644
index 0000000..0f13661
--- /dev/null
+++ b/backends/platform/android/jni.cpp
@@ -0,0 +1,387 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "base/main.h"
+#include "common/config-manager.h"
+
+#include "backends/platform/android/android.h"
+
+// Fix JNIEXPORT declaration to actually do something useful
+#undef JNIEXPORT
+#define JNIEXPORT __attribute__ ((visibility("default")))
+
+static JavaVM *cached_jvm;
+static jfieldID FID_Event_type;
+static jfieldID FID_Event_synthetic;
+static jfieldID FID_Event_kbd_keycode;
+static jfieldID FID_Event_kbd_ascii;
+static jfieldID FID_Event_kbd_flags;
+static jfieldID FID_Event_mouse_x;
+static jfieldID FID_Event_mouse_y;
+static jfieldID FID_Event_mouse_relative;
+static jfieldID FID_ScummVM_nativeScummVM;
+static jmethodID MID_Object_wait;
+
+JNIEnv *JNU_GetEnv() {
+	JNIEnv *env = 0;
+
+	jint res = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
+
+	if (res != JNI_OK) {
+		LOGE("GetEnv() failed: %d", res);
+		abort();
+	}
+
+	return env;
+}
+
+void JNU_AttachThread() {
+	JNIEnv *env = 0;
+	jint res = cached_jvm->AttachCurrentThread(&env, 0);
+
+	if (res != JNI_OK) {
+		LOGE("AttachCurrentThread() failed: %d", res);
+		abort();
+	}
+}
+
+void JNU_DetachThread() {
+	jint res = cached_jvm->DetachCurrentThread();
+
+	if (res != JNI_OK) {
+		LOGE("DetachCurrentThread() failed: %d", res);
+		abort();
+	}
+}
+
+static void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
+	jclass cls = env->FindClass(name);
+
+	// if cls is 0, an exception has already been thrown
+	if (cls != 0)
+		env->ThrowNew(cls, msg);
+
+	env->DeleteLocalRef(cls);
+}
+
+static void ScummVM_create(JNIEnv *env, jobject self, jobject am) {
+	assert(!g_system);
+
+	g_sys = new OSystem_Android(am);
+	assert(g_sys);
+
+	// Exception already thrown by initJavaHooks?
+	if (!g_sys->initJavaHooks(env, self))
+		return;
+
+	env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)g_sys);
+
+	g_system = g_sys;
+}
+
+static void ScummVM_nativeDestroy(JNIEnv *env, jobject self) {
+	assert(g_sys);
+
+	OSystem_Android *tmp = g_sys;
+	g_system = 0;
+	g_sys = 0;
+	delete tmp;
+}
+
+static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) {
+	assert(g_sys);
+
+	const int MAX_NARGS = 32;
+	int res = -1;
+
+	int argc = env->GetArrayLength(args);
+	if (argc > MAX_NARGS) {
+		JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
+						"too many arguments");
+		return 0;
+	}
+
+	char *argv[MAX_NARGS];
+
+	// note use in cleanup loop below
+	int nargs;
+
+	for (nargs = 0; nargs < argc; ++nargs) {
+		jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
+
+		if (arg == 0) {
+			argv[nargs] = 0;
+		} else {
+			const char *cstr = env->GetStringUTFChars(arg, 0);
+
+			argv[nargs] = const_cast<char *>(cstr);
+
+			// exception already thrown?
+			if (cstr == 0)
+				goto cleanup;
+		}
+
+		env->DeleteLocalRef(arg);
+	}
+
+#ifdef DYNAMIC_MODULES
+	PluginManager::instance().addPluginProvider(new AndroidPluginProvider());
+#endif
+
+	LOGI("Entering scummvm_main with %d args", argc);
+
+	res = scummvm_main(argc, argv);
+
+	LOGI("Exiting scummvm_main");
+
+	g_sys->quit();
+
+cleanup:
+	nargs--;
+
+	for (int i = 0; i < nargs; ++i) {
+		if (argv[i] == 0)
+			continue;
+
+		jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
+
+		// Exception already thrown?
+		if (arg == 0)
+			return res;
+
+		env->ReleaseStringUTFChars(arg, argv[i]);
+		env->DeleteLocalRef(arg);
+	}
+
+	return res;
+}
+
+static void ScummVM_pushEvent(JNIEnv *env, jobject self, jobject java_event) {
+	assert(g_sys);
+
+	Common::Event event;
+	event.type = (Common::EventType)env->GetIntField(java_event,
+														FID_Event_type);
+
+	event.synthetic =
+		env->GetBooleanField(java_event, FID_Event_synthetic);
+
+	switch (event.type) {
+	case Common::EVENT_KEYDOWN:
+	case Common::EVENT_KEYUP:
+		event.kbd.keycode = (Common::KeyCode)env->GetIntField(
+			java_event, FID_Event_kbd_keycode);
+		event.kbd.ascii = static_cast<int>(env->GetIntField(
+			java_event, FID_Event_kbd_ascii));
+		event.kbd.flags = static_cast<int>(env->GetIntField(
+			java_event, FID_Event_kbd_flags));
+		break;
+	case Common::EVENT_MOUSEMOVE:
+	case Common::EVENT_LBUTTONDOWN:
+	case Common::EVENT_LBUTTONUP:
+	case Common::EVENT_RBUTTONDOWN:
+	case Common::EVENT_RBUTTONUP:
+	case Common::EVENT_WHEELUP:
+	case Common::EVENT_WHEELDOWN:
+	case Common::EVENT_MBUTTONDOWN:
+	case Common::EVENT_MBUTTONUP:
+		event.mouse.x =
+			env->GetIntField(java_event, FID_Event_mouse_x);
+		event.mouse.y =
+			env->GetIntField(java_event, FID_Event_mouse_y);
+		// This is a terrible hack.	 We stash "relativeness"
+		// in the kbd.flags field until pollEvent() can work
+		// it out.
+		event.kbd.flags = env->GetBooleanField(
+			java_event, FID_Event_mouse_relative) ? 1 : 0;
+		break;
+	default:
+		break;
+	}
+
+	g_sys->pushEvent(event);
+}
+
+static void ScummVM_audioMixCallback(JNIEnv *env, jobject self,
+										jbyteArray jbuf) {
+	assert(g_sys);
+
+	jsize len = env->GetArrayLength(jbuf);
+	jbyte *buf = env->GetByteArrayElements(jbuf, 0);
+
+	if (buf == 0) {
+		warning("Unable to get Java audio byte array. Skipping");
+		return;
+	}
+
+	Audio::MixerImpl *mixer =
+		static_cast<Audio::MixerImpl *>(g_sys->getMixer());
+	assert(mixer);
+	mixer->mixCallback(reinterpret_cast<byte *>(buf), len);
+
+	env->ReleaseByteArrayElements(jbuf, buf, 0);
+}
+
+static void ScummVM_setConfManInt(JNIEnv *env, jclass cls,
+									jstring key_obj, jint value) {
+	ENTER("%p, %d", key_obj, (int)value);
+
+	const char *key = env->GetStringUTFChars(key_obj, 0);
+
+	if (key == 0)
+		return;
+
+	ConfMan.setInt(key, value);
+
+	env->ReleaseStringUTFChars(key_obj, key);
+}
+
+static void ScummVM_setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
+										jstring value_obj) {
+	ENTER("%p, %p", key_obj, value_obj);
+
+	const char *key = env->GetStringUTFChars(key_obj, 0);
+
+	if (key == 0)
+		return;
+
+	const char *value = env->GetStringUTFChars(value_obj, 0);
+
+	if (value == 0) {
+		env->ReleaseStringUTFChars(key_obj, key);
+		return;
+	}
+
+	ConfMan.set(key, value);
+
+	env->ReleaseStringUTFChars(value_obj, value);
+	env->ReleaseStringUTFChars(key_obj, key);
+}
+
+static void ScummVM_enableZoning(JNIEnv *env, jobject self, jboolean enable) {
+	assert(g_sys);
+
+	g_sys->enableZoning(enable);
+}
+
+static void ScummVM_setSurfaceSize(JNIEnv *env, jobject self,
+									jint width, jint height) {
+	assert(g_sys);
+
+	g_sys->setSurfaceSize(width, height);
+}
+
+const static JNINativeMethod gMethods[] = {
+	{ "create", "(Landroid/content/res/AssetManager;)V",
+		(void *)ScummVM_create },
+	{ "nativeDestroy", "()V",
+		(void *)ScummVM_nativeDestroy },
+	{ "scummVMMain", "([Ljava/lang/String;)I",
+	 	(void *)ScummVM_scummVMMain },
+	{ "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
+		(void *)ScummVM_pushEvent },
+	{ "audioMixCallback", "([B)V",
+		(void *)ScummVM_audioMixCallback },
+	{ "setConfMan", "(Ljava/lang/String;I)V",
+		(void *)ScummVM_setConfManInt },
+	{ "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
+		(void *)ScummVM_setConfManString },
+	{ "enableZoning", "(Z)V",
+		(void *)ScummVM_enableZoning },
+	{ "setSurfaceSize", "(II)V",
+		(void *)ScummVM_setSurfaceSize },
+};
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *jvm, void *reserved) {
+	cached_jvm = jvm;
+
+	JNIEnv *env;
+
+	if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2))
+		return JNI_ERR;
+
+	jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
+	if (cls == 0)
+		return JNI_ERR;
+
+	if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0)
+		return JNI_ERR;
+
+	FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
+	if (FID_ScummVM_nativeScummVM == 0)
+		return JNI_ERR;
+
+	jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
+	if (event == 0)
+		return JNI_ERR;
+
+	FID_Event_type = env->GetFieldID(event, "type", "I");
+	if (FID_Event_type == 0)
+		return JNI_ERR;
+
+	FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
+	if (FID_Event_synthetic == 0)
+		return JNI_ERR;
+
+	FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
+	if (FID_Event_kbd_keycode == 0)
+		return JNI_ERR;
+
+	FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
+	if (FID_Event_kbd_ascii == 0)
+		return JNI_ERR;
+
+	FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
+	if (FID_Event_kbd_flags == 0)
+		return JNI_ERR;
+
+	FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
+	if (FID_Event_mouse_x == 0)
+		return JNI_ERR;
+
+	FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
+	if (FID_Event_mouse_y == 0)
+		return JNI_ERR;
+
+	FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
+	if (FID_Event_mouse_relative == 0)
+		return JNI_ERR;
+
+	cls = env->FindClass("java/lang/Object");
+	if (cls == 0)
+		return JNI_ERR;
+
+	MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
+	if (MID_Object_wait == 0)
+		return JNI_ERR;
+
+	return JNI_VERSION_1_2;
+}
+
+#endif
+
diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk
index 8b120b2..3bcfa7a 100644
--- a/backends/platform/android/module.mk
+++ b/backends/platform/android/module.mk
@@ -1,9 +1,11 @@
 MODULE := backends/platform/android
 
 MODULE_OBJS := \
-	android.o \
+	jni.o \
+	texture.o \
 	asset-archive.o \
-	video.o
+	android.o \
+	gfx.o
 
 # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
 MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
new file mode 100644
index 0000000..b638976
--- /dev/null
+++ b/backends/platform/android/texture.cpp
@@ -0,0 +1,342 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "base/main.h"
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+#include "common/util.h"
+#include "common/tokenizer.h"
+
+#include "backends/platform/android/texture.h"
+#include "backends/platform/android/android.h"
+
+// Unfortunately, Android devices are too varied to make broad assumptions :/
+#define TEXSUBIMAGE_IS_EXPENSIVE 0
+
+// Supported GL extensions
+static bool npot_supported = false;
+#ifdef GL_OES_draw_texture
+static bool draw_tex_supported = false;
+#endif
+
+static inline GLfixed xdiv(int numerator, int denominator) {
+	assert(numerator < (1 << 16));
+	return (numerator << 16) / denominator;
+}
+
+template <class T>
+static T nextHigher2(T k) {
+	if (k == 0)
+		return 1;
+	--k;
+
+	for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1)
+		k = k | k >> i;
+
+	return k + 1;
+}
+
+void GLESTexture::initGLExtensions() {
+	const char *ext_string =
+		reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
+
+	LOGI("Extensions: %s", ext_string);
+
+	Common::StringTokenizer tokenizer(ext_string, " ");
+	while (!tokenizer.empty()) {
+		Common::String token = tokenizer.nextToken();
+
+		if (token == "GL_ARB_texture_non_power_of_two")
+			npot_supported = true;
+
+#ifdef GL_OES_draw_texture
+		if (token == "GL_OES_draw_texture")
+			draw_tex_supported = true;
+#endif
+	}
+}
+
+GLESTexture::GLESTexture() :
+	_texture_width(0),
+	_texture_height(0),
+	_all_dirty(true)
+{
+	GLCALL(glGenTextures(1, &_texture_name));
+
+	// This all gets reset later in allocBuffer:
+	_surface.w = 0;
+	_surface.h = 0;
+	_surface.pitch = _texture_width;
+	_surface.pixels = 0;
+	_surface.bytesPerPixel = 0;
+}
+
+GLESTexture::~GLESTexture() {
+	debug("Destroying texture %u", _texture_name);
+	GLCALL(glDeleteTextures(1, &_texture_name));
+}
+
+void GLESTexture::reinitGL() {
+	GLCALL(glDeleteTextures(1, &_texture_name));
+	GLCALL(glGenTextures(1, &_texture_name));
+
+	// bypass allocBuffer() shortcut to reinit the texture properly
+	_texture_width = 0;
+	_texture_height = 0;
+
+	allocBuffer(_surface.w, _surface.h);
+	setDirty();
+}
+
+void GLESTexture::allocBuffer(GLuint w, GLuint h) {
+	int bpp = bytesPerPixel();
+	_surface.w = w;
+	_surface.h = h;
+	_surface.bytesPerPixel = bpp;
+
+	// Already allocated a sufficiently large buffer?
+	if (w <= _texture_width && h <= _texture_height)
+		return;
+
+	if (npot_supported) {
+		_texture_width = _surface.w;
+		_texture_height = _surface.h;
+	} else {
+		_texture_width = nextHigher2(_surface.w);
+		_texture_height = nextHigher2(_surface.h);
+	}
+
+	_surface.pitch = _texture_width * bpp;
+
+	// Allocate room for the texture now, but pixel data gets uploaded
+	// later (perhaps with multiple TexSubImage2D operations).
+	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+	GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+	GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, glFormat(),
+						_texture_width, _texture_height,
+						0, glFormat(), glType(), 0));
+}
+
+void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
+								const void *buf, int pitch) {
+	ENTER("%u, %u, %u, %u, %p, %d", x, y, w, h, buf, pitch);
+
+	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+	GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+
+	setDirtyRect(Common::Rect(x, y, x+w, y+h));
+
+	if (static_cast<int>(w) * bytesPerPixel() == pitch) {
+		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
+								glFormat(), glType(), buf));
+	} else {
+		// GLES removed the ability to specify pitch, so we
+		// have to do this ourselves.
+		if (h == 0)
+			return;
+
+#if TEXSUBIMAGE_IS_EXPENSIVE
+		byte tmpbuf[w * h * bytesPerPixel()];
+		const byte *src = static_cast<const byte *>(buf);
+		byte *dst = tmpbuf;
+		GLuint count = h;
+
+		do {
+			memcpy(dst, src, w * bytesPerPixel());
+			dst += w * bytesPerPixel();
+			src += pitch;
+		} while (--count);
+
+		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
+								glFormat(), glType(), tmpbuf));
+#else
+		// This version avoids the intermediate copy at the expense of
+		// repeat glTexSubImage2D calls.  On some devices this is worse.
+		const byte *src = static_cast<const byte *>(buf);
+		do {
+			GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
+									w, 1, glFormat(), glType(), src));
+			++y;
+			src += pitch;
+		} while (--h);
+#endif
+	}
+}
+
+void GLESTexture::fillBuffer(byte x) {
+	int rowbytes = _surface.w * bytesPerPixel();
+	byte tmpbuf[_surface.h * rowbytes];
+	memset(tmpbuf, x, _surface.h * rowbytes);
+	updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes);
+}
+
+void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+#ifdef GL_OES_draw_texture
+	// Great extension, but only works under specific conditions.
+	// Still a work-in-progress - disabled for now.
+	if (false && draw_tex_supported && paletteSize() == 0) {
+		//GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
+		const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h };
+
+		GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop));
+
+		// Android GLES bug?
+		GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
+
+		GLCALL(glDrawTexiOES(x, y, 0, w, h));
+	} else
+#endif
+	{
+		const GLfixed tex_width = xdiv(_surface.w, _texture_width);
+		const GLfixed tex_height = xdiv(_surface.h, _texture_height);
+		const GLfixed texcoords[] = {
+			0, 0,
+			tex_width, 0,
+			0, tex_height,
+			tex_width, tex_height,
+		};
+
+		GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords));
+
+		const GLshort vertices[] = {
+			x, y,
+			x + w, y,
+			x, y + h,
+			x + w, y + h,
+		};
+
+		GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
+
+		assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
+		GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2));
+	}
+
+	_all_dirty = false;
+	_dirty_rect = Common::Rect();
+}
+
+GLESPaletteTexture::GLESPaletteTexture() :
+	GLESTexture(),
+	_texture(0)
+{
+}
+
+GLESPaletteTexture::~GLESPaletteTexture() {
+	delete[] _texture;
+}
+
+void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
+	int bpp = bytesPerPixel();
+	_surface.w = w;
+	_surface.h = h;
+	_surface.bytesPerPixel = bpp;
+
+	// Already allocated a sufficiently large buffer?
+	if (w <= _texture_width && h <= _texture_height)
+		return;
+
+	if (npot_supported) {
+		_texture_width = _surface.w;
+		_texture_height = _surface.h;
+	} else {
+		_texture_width = nextHigher2(_surface.w);
+		_texture_height = nextHigher2(_surface.h);
+	}
+	_surface.pitch = _texture_width * bpp;
+
+	// Texture gets uploaded later (from drawTexture())
+
+	byte *new_buffer = new byte[paletteSize() +
+		_texture_width * _texture_height * bytesPerPixel()];
+	if (_texture) {
+		// preserve palette
+		memcpy(new_buffer, _texture, paletteSize());
+		delete[] _texture;
+	}
+
+	_texture = new_buffer;
+	_surface.pixels = _texture + paletteSize();
+}
+
+void GLESPaletteTexture::fillBuffer(byte x) {
+	assert(_surface.pixels);
+	memset(_surface.pixels, x, _surface.pitch * _surface.h);
+	setDirty();
+}
+
+void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y,
+										GLuint w, GLuint h,
+										const void *buf, int pitch) {
+	_all_dirty = true;
+
+	const byte * src = static_cast<const byte *>(buf);
+	byte *dst = static_cast<byte *>(_surface.getBasePtr(x, y));
+
+	do {
+		memcpy(dst, src, w * bytesPerPixel());
+		dst += _surface.pitch;
+		src += pitch;
+	} while (--h);
+}
+
+void GLESPaletteTexture::uploadTexture() const {
+	const size_t texture_size =
+		paletteSize() + _texture_width * _texture_height * bytesPerPixel();
+
+	GLCALL(glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(),
+									_texture_width, _texture_height,
+									0, texture_size, _texture));
+}
+
+void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+	if (_all_dirty) {
+		GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+								GL_NEAREST));
+		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+								GL_NEAREST));
+		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+								GL_CLAMP_TO_EDGE));
+		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+								GL_CLAMP_TO_EDGE));
+		uploadTexture();
+		_all_dirty = false;
+	}
+
+	GLESTexture::drawTexture(x, y, w, h);
+}
+
+#endif
+
diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h
new file mode 100644
index 0000000..050eafa
--- /dev/null
+++ b/backends/platform/android/texture.h
@@ -0,0 +1,214 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef _ANDROID_TEXTURE_H_
+#define _ANDROID_TEXTURE_H_
+
+#if defined(__ANDROID__)
+
+#include <GLES/gl.h>
+
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+
+class GLESTexture {
+public:
+	static void initGLExtensions();
+
+	GLESTexture();
+	virtual ~GLESTexture();
+
+	virtual void reinitGL();
+	virtual void allocBuffer(GLuint width, GLuint height);
+
+	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+								const void *buf, int pitch);
+	virtual void fillBuffer(byte x);
+
+	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+	inline GLuint width() const {
+		return _surface.w;
+	}
+
+	inline GLuint height() const {
+		return _surface.h;
+	}
+
+	inline GLuint texture_name() const {
+		return _texture_name;
+	}
+
+	inline const Graphics::Surface *surface_const() const {
+		return &_surface;
+	}
+
+	inline Graphics::Surface *surface() {
+		setDirty();
+		return &_surface;
+	}
+
+	inline bool dirty() const {
+		return _all_dirty || !_dirty_rect.isEmpty();
+	}
+
+	inline void drawTexture() {
+		drawTexture(0, 0, _surface.w, _surface.h);
+	}
+
+protected:
+	virtual byte bytesPerPixel() const = 0;
+	virtual GLenum glFormat() const = 0;
+	virtual GLenum glType() const = 0;
+
+	virtual size_t paletteSize() const {
+		return 0;
+	}
+
+	inline void setDirty() {
+		_all_dirty = true;
+		_dirty_rect = Common::Rect();
+	}
+
+	inline void setDirtyRect(const Common::Rect& r) {
+		if (!_all_dirty) {
+			if (_dirty_rect.isEmpty())
+				_dirty_rect = r;
+			else
+				_dirty_rect.extend(r);
+		}
+	}
+
+	GLuint _texture_name;
+	Graphics::Surface _surface;
+	GLuint _texture_width;
+	GLuint _texture_height;
+	bool _all_dirty;
+
+	// Covers dirty area
+	Common::Rect _dirty_rect;
+};
+
+// RGBA4444 texture
+class GLES4444Texture : public GLESTexture {
+protected:
+	virtual byte bytesPerPixel() const {
+		return 2;
+	}
+
+	virtual GLenum glFormat() const {
+		return GL_RGBA;
+	}
+
+	virtual GLenum glType() const {
+		return GL_UNSIGNED_SHORT_4_4_4_4;
+	}
+};
+
+// RGB565 texture
+class GLES565Texture : public GLESTexture {
+protected:
+	virtual byte bytesPerPixel() const {
+		return 2;
+	}
+
+	virtual GLenum glFormat() const {
+		return GL_RGB;
+	}
+
+	virtual GLenum glType() const {
+		return GL_UNSIGNED_SHORT_5_6_5;
+	}
+};
+
+// RGB888 256-entry paletted texture
+class GLESPaletteTexture : public GLESTexture {
+public:
+	GLESPaletteTexture();
+	virtual ~GLESPaletteTexture();
+
+	virtual void allocBuffer(GLuint width, GLuint height);
+	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+								const void *buf, int pitch);
+	virtual void fillBuffer(byte x);
+
+	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+	inline void drawTexture() {
+		drawTexture(0, 0, _surface.w, _surface.h);
+	}
+
+	inline const byte *palette_const() const {
+		return _texture;
+	};
+
+	inline byte *palette() {
+		setDirty();
+		return _texture;
+	};
+
+protected:
+	virtual byte bytesPerPixel() const {
+		return 1;
+	}
+
+	virtual GLenum glFormat() const {
+		return GL_RGB;
+	}
+
+	virtual GLenum glType() const {
+		return GL_PALETTE8_RGB8_OES;
+	}
+
+	virtual size_t paletteSize() const {
+		return 256 * 3;
+	}
+
+	void uploadTexture() const;
+
+	byte *_texture;
+};
+
+// RGBA8888 256-entry paletted texture
+class GLESPaletteATexture : public GLESPaletteTexture {
+protected:
+	virtual GLenum glFormat() const {
+		return GL_RGBA;
+	}
+
+	virtual GLenum glType() const {
+		return GL_PALETTE8_RGBA8_OES;
+	}
+
+	virtual size_t paletteSize() const {
+		return 256 * 4;
+	}
+};
+
+#endif
+#endif
+
diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp
deleted file mode 100644
index f8427c2..0000000
--- a/backends/platform/android/video.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#if defined(__ANDROID__)
-
-#include "base/main.h"
-#include "graphics/surface.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-#include "common/util.h"
-#include "common/tokenizer.h"
-
-#include "backends/platform/android/android.h"
-#include "backends/platform/android/video.h"
-
-// Unfortunately, Android devices are too varied to make broad assumptions :/
-#define TEXSUBIMAGE_IS_EXPENSIVE 0
-
-// Supported GL extensions
-static bool npot_supported = false;
-#ifdef GL_OES_draw_texture
-static bool draw_tex_supported = false;
-#endif
-
-static inline GLfixed xdiv(int numerator, int denominator) {
-	assert(numerator < (1 << 16));
-	return (numerator << 16) / denominator;
-}
-
-template <class T>
-static T nextHigher2(T k) {
-	if (k == 0)
-		return 1;
-	--k;
-
-	for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1)
-		k = k | k >> i;
-
-	return k + 1;
-}
-
-void GLESTexture::initGLExtensions() {
-	const char *ext_string =
-		reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
-
-	LOGI("Extensions: %s", ext_string);
-
-	Common::StringTokenizer tokenizer(ext_string, " ");
-	while (!tokenizer.empty()) {
-		Common::String token = tokenizer.nextToken();
-
-		if (token == "GL_ARB_texture_non_power_of_two")
-			npot_supported = true;
-
-#ifdef GL_OES_draw_texture
-		if (token == "GL_OES_draw_texture")
-			draw_tex_supported = true;
-#endif
-	}
-}
-
-GLESTexture::GLESTexture() :
-	_texture_width(0),
-	_texture_height(0),
-	_all_dirty(true)
-{
-	GLCALL(glGenTextures(1, &_texture_name));
-
-	// This all gets reset later in allocBuffer:
-	_surface.w = 0;
-	_surface.h = 0;
-	_surface.pitch = _texture_width;
-	_surface.pixels = 0;
-	_surface.bytesPerPixel = 0;
-}
-
-GLESTexture::~GLESTexture() {
-	debug("Destroying texture %u", _texture_name);
-	GLCALL(glDeleteTextures(1, &_texture_name));
-}
-
-void GLESTexture::reinitGL() {
-	GLCALL(glDeleteTextures(1, &_texture_name));
-	GLCALL(glGenTextures(1, &_texture_name));
-
-	// bypass allocBuffer() shortcut to reinit the texture properly
-	_texture_width = 0;
-	_texture_height = 0;
-
-	allocBuffer(_surface.w, _surface.h);
-	setDirty();
-}
-
-void GLESTexture::allocBuffer(GLuint w, GLuint h) {
-	int bpp = bytesPerPixel();
-	_surface.w = w;
-	_surface.h = h;
-	_surface.bytesPerPixel = bpp;
-
-	// Already allocated a sufficiently large buffer?
-	if (w <= _texture_width && h <= _texture_height)
-		return;
-
-	if (npot_supported) {
-		_texture_width = _surface.w;
-		_texture_height = _surface.h;
-	} else {
-		_texture_width = nextHigher2(_surface.w);
-		_texture_height = nextHigher2(_surface.h);
-	}
-
-	_surface.pitch = _texture_width * bpp;
-
-	// Allocate room for the texture now, but pixel data gets uploaded
-	// later (perhaps with multiple TexSubImage2D operations).
-	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-	GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-	GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, glFormat(),
-						_texture_width, _texture_height,
-						0, glFormat(), glType(), 0));
-}
-
-void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
-								const void *buf, int pitch) {
-	ENTER("%u, %u, %u, %u, %p, %d", x, y, w, h, buf, pitch);
-
-	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-	GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
-
-	setDirtyRect(Common::Rect(x, y, x+w, y+h));
-
-	if (static_cast<int>(w) * bytesPerPixel() == pitch) {
-		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
-								glFormat(), glType(), buf));
-	} else {
-		// GLES removed the ability to specify pitch, so we
-		// have to do this ourselves.
-		if (h == 0)
-			return;
-
-#if TEXSUBIMAGE_IS_EXPENSIVE
-		byte tmpbuf[w * h * bytesPerPixel()];
-		const byte *src = static_cast<const byte *>(buf);
-		byte *dst = tmpbuf;
-		GLuint count = h;
-
-		do {
-			memcpy(dst, src, w * bytesPerPixel());
-			dst += w * bytesPerPixel();
-			src += pitch;
-		} while (--count);
-
-		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
-								glFormat(), glType(), tmpbuf));
-#else
-		// This version avoids the intermediate copy at the expense of
-		// repeat glTexSubImage2D calls.  On some devices this is worse.
-		const byte *src = static_cast<const byte *>(buf);
-		do {
-			GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
-									w, 1, glFormat(), glType(), src));
-			++y;
-			src += pitch;
-		} while (--h);
-#endif
-	}
-}
-
-void GLESTexture::fillBuffer(byte x) {
-	int rowbytes = _surface.w * bytesPerPixel();
-	byte tmpbuf[_surface.h * rowbytes];
-	memset(tmpbuf, x, _surface.h * rowbytes);
-	updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes);
-}
-
-void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
-	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-
-#ifdef GL_OES_draw_texture
-	// Great extension, but only works under specific conditions.
-	// Still a work-in-progress - disabled for now.
-	if (false && draw_tex_supported && paletteSize() == 0) {
-		//GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
-		const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h };
-
-		GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop));
-
-		// Android GLES bug?
-		GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
-
-		GLCALL(glDrawTexiOES(x, y, 0, w, h));
-	} else
-#endif
-	{
-		const GLfixed tex_width = xdiv(_surface.w, _texture_width);
-		const GLfixed tex_height = xdiv(_surface.h, _texture_height);
-		const GLfixed texcoords[] = {
-			0, 0,
-			tex_width, 0,
-			0, tex_height,
-			tex_width, tex_height,
-		};
-
-		GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords));
-
-		const GLshort vertices[] = {
-			x, y,
-			x + w, y,
-			x, y + h,
-			x + w, y + h,
-		};
-
-		GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
-
-		assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
-		GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2));
-	}
-
-	_all_dirty = false;
-	_dirty_rect = Common::Rect();
-}
-
-GLESPaletteTexture::GLESPaletteTexture() :
-	GLESTexture(),
-	_texture(0)
-{
-}
-
-GLESPaletteTexture::~GLESPaletteTexture() {
-	delete[] _texture;
-}
-
-void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
-	int bpp = bytesPerPixel();
-	_surface.w = w;
-	_surface.h = h;
-	_surface.bytesPerPixel = bpp;
-
-	// Already allocated a sufficiently large buffer?
-	if (w <= _texture_width && h <= _texture_height)
-		return;
-
-	if (npot_supported) {
-		_texture_width = _surface.w;
-		_texture_height = _surface.h;
-	} else {
-		_texture_width = nextHigher2(_surface.w);
-		_texture_height = nextHigher2(_surface.h);
-	}
-	_surface.pitch = _texture_width * bpp;
-
-	// Texture gets uploaded later (from drawTexture())
-
-	byte *new_buffer = new byte[paletteSize() +
-		_texture_width * _texture_height * bytesPerPixel()];
-	if (_texture) {
-		// preserve palette
-		memcpy(new_buffer, _texture, paletteSize());
-		delete[] _texture;
-	}
-
-	_texture = new_buffer;
-	_surface.pixels = _texture + paletteSize();
-}
-
-void GLESPaletteTexture::fillBuffer(byte x) {
-	assert(_surface.pixels);
-	memset(_surface.pixels, x, _surface.pitch * _surface.h);
-	setDirty();
-}
-
-void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y,
-										GLuint w, GLuint h,
-										const void *buf, int pitch) {
-	_all_dirty = true;
-
-	const byte * src = static_cast<const byte *>(buf);
-	byte *dst = static_cast<byte *>(_surface.getBasePtr(x, y));
-
-	do {
-		memcpy(dst, src, w * bytesPerPixel());
-		dst += _surface.pitch;
-		src += pitch;
-	} while (--h);
-}
-
-void GLESPaletteTexture::uploadTexture() const {
-	const size_t texture_size =
-		paletteSize() + _texture_width * _texture_height * bytesPerPixel();
-
-	GLCALL(glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(),
-									_texture_width, _texture_height,
-									0, texture_size, _texture));
-}
-
-void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
-	if (_all_dirty) {
-		GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
-								GL_NEAREST));
-		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
-								GL_NEAREST));
-		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
-								GL_CLAMP_TO_EDGE));
-		GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
-								GL_CLAMP_TO_EDGE));
-		uploadTexture();
-		_all_dirty = false;
-	}
-
-	GLESTexture::drawTexture(x, y, w, h);
-}
-
-#endif
-
diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h
deleted file mode 100644
index da42ea8..0000000
--- a/backends/platform/android/video.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#if defined(__ANDROID__)
-
-#include <GLES/gl.h>
-
-#include "graphics/surface.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-
-class GLESTexture {
-public:
-	static void initGLExtensions();
-
-	GLESTexture();
-	virtual ~GLESTexture();
-
-	virtual void reinitGL();
-	virtual void allocBuffer(GLuint width, GLuint height);
-
-	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
-								const void *buf, int pitch);
-	virtual void fillBuffer(byte x);
-
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
-	inline GLuint width() const {
-		return _surface.w;
-	}
-
-	inline GLuint height() const {
-		return _surface.h;
-	}
-
-	inline GLuint texture_name() const {
-		return _texture_name;
-	}
-
-	inline const Graphics::Surface *surface_const() const {
-		return &_surface;
-	}
-
-	inline Graphics::Surface *surface() {
-		setDirty();
-		return &_surface;
-	}
-
-	inline bool dirty() const {
-		return _all_dirty || !_dirty_rect.isEmpty();
-	}
-
-	inline void drawTexture() {
-		drawTexture(0, 0, _surface.w, _surface.h);
-	}
-
-protected:
-	virtual byte bytesPerPixel() const = 0;
-	virtual GLenum glFormat() const = 0;
-	virtual GLenum glType() const = 0;
-
-	virtual size_t paletteSize() const {
-		return 0;
-	}
-
-	inline void setDirty() {
-		_all_dirty = true;
-		_dirty_rect = Common::Rect();
-	}
-
-	inline void setDirtyRect(const Common::Rect& r) {
-		if (!_all_dirty) {
-			if (_dirty_rect.isEmpty())
-				_dirty_rect = r;
-			else
-				_dirty_rect.extend(r);
-		}
-	}
-
-	GLuint _texture_name;
-	Graphics::Surface _surface;
-	GLuint _texture_width;
-	GLuint _texture_height;
-	bool _all_dirty;
-
-	// Covers dirty area
-	Common::Rect _dirty_rect;
-};
-
-// RGBA4444 texture
-class GLES4444Texture : public GLESTexture {
-protected:
-	virtual byte bytesPerPixel() const {
-		return 2;
-	}
-
-	virtual GLenum glFormat() const {
-		return GL_RGBA;
-	}
-
-	virtual GLenum glType() const {
-		return GL_UNSIGNED_SHORT_4_4_4_4;
-	}
-};
-
-// RGB565 texture
-class GLES565Texture : public GLESTexture {
-protected:
-	virtual byte bytesPerPixel() const {
-		return 2;
-	}
-
-	virtual GLenum glFormat() const {
-		return GL_RGB;
-	}
-
-	virtual GLenum glType() const {
-		return GL_UNSIGNED_SHORT_5_6_5;
-	}
-};
-
-// RGB888 256-entry paletted texture
-class GLESPaletteTexture : public GLESTexture {
-public:
-	GLESPaletteTexture();
-	virtual ~GLESPaletteTexture();
-
-	virtual void allocBuffer(GLuint width, GLuint height);
-	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
-								const void *buf, int pitch);
-	virtual void fillBuffer(byte x);
-
-	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
-	inline void drawTexture() {
-		drawTexture(0, 0, _surface.w, _surface.h);
-	}
-
-	inline const byte *palette_const() const {
-		return _texture;
-	};
-
-	inline byte *palette() {
-		setDirty();
-		return _texture;
-	};
-
-protected:
-	virtual byte bytesPerPixel() const {
-		return 1;
-	}
-
-	virtual GLenum glFormat() const {
-		return GL_RGB;
-	}
-
-	virtual GLenum glType() const {
-		return GL_PALETTE8_RGB8_OES;
-	}
-
-	virtual size_t paletteSize() const {
-		return 256 * 3;
-	}
-
-	void uploadTexture() const;
-
-	byte *_texture;
-};
-
-// RGBA8888 256-entry paletted texture
-class GLESPaletteATexture : public GLESPaletteTexture {
-protected:
-	virtual GLenum glFormat() const {
-		return GL_RGBA;
-	}
-
-	virtual GLenum glType() const {
-		return GL_PALETTE8_RGBA8_OES;
-	}
-
-	virtual size_t paletteSize() const {
-		return 256 * 4;
-	}
-};
-
-#endif


Commit: 4af28f96ab4075cb5e512d4050ac085df73a029a
    https://github.com/scummvm/scummvm/commit/4af28f96ab4075cb5e512d4050ac085df73a029a
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:31-08:00

Commit Message:
ANDROID: Remove unused jmethod Object.wait()

Changed paths:
    backends/platform/android/jni.cpp



diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 0f13661..e5d0f71 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -44,7 +44,6 @@ static jfieldID FID_Event_mouse_x;
 static jfieldID FID_Event_mouse_y;
 static jfieldID FID_Event_mouse_relative;
 static jfieldID FID_ScummVM_nativeScummVM;
-static jmethodID MID_Object_wait;
 
 JNIEnv *JNU_GetEnv() {
 	JNIEnv *env = 0;
@@ -372,14 +371,6 @@ JNI_OnLoad(JavaVM *jvm, void *reserved) {
 	if (FID_Event_mouse_relative == 0)
 		return JNI_ERR;
 
-	cls = env->FindClass("java/lang/Object");
-	if (cls == 0)
-		return JNI_ERR;
-
-	MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
-	if (MID_Object_wait == 0)
-		return JNI_ERR;
-
 	return JNI_VERSION_1_2;
 }
 


Commit: c4706733d45de09803b7cd40c3536a4e04b4f767
    https://github.com/scummvm/scummvm/commit/c4706733d45de09803b7cd40c3536a4e04b4f767
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:32-08:00

Commit Message:
ANDROID: Move the global back reference to jni.cpp

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/gfx.cpp
    backends/platform/android/jni.cpp



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index a0a5347..f2c9a74 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -101,7 +101,6 @@ static inline T scalef(T in, float numerator, float denominator) {
 OSystem_Android *g_sys = 0;
 
 OSystem_Android::OSystem_Android(jobject am) :
-	_back_ptr(0),
 	_screen_changeid(0),
 	_force_redraw(false),
 	_game_texture(0),
@@ -129,11 +128,6 @@ OSystem_Android::~OSystem_Android() {
 
 	destroyScummVMSurface();
 
-	JNIEnv *env = JNU_GetEnv();
-	// see below
-	//env->DeleteWeakGlobalRef(_back_ptr);
-	env->DeleteGlobalRef(_back_ptr);
-
 	delete _savefile;
 	delete _mixer;
 	delete _timer;
@@ -143,13 +137,8 @@ OSystem_Android::~OSystem_Android() {
 	deleteMutex(_event_queue_lock);
 }
 
-bool OSystem_Android::initJavaHooks(JNIEnv *env, jobject self) {
-	// weak global ref to allow class to be unloaded
-	// ... except dalvik implements NewWeakGlobalRef only on froyo
-	//_back_ptr = env->NewWeakGlobalRef(self);
-	_back_ptr = env->NewGlobalRef(self);
-
-	jclass cls = env->GetObjectClass(_back_ptr);
+bool OSystem_Android::initJavaHooks(JNIEnv *env) {
+	jclass cls = env->GetObjectClass(back_ptr);
 
 #define FIND_METHOD(name, signature) do {						\
 		MID_ ## name = env->GetMethodID(cls, #name, signature); \
@@ -213,7 +202,7 @@ void OSystem_Android::initBackend() {
 
 	gettimeofday(&_startTime, 0);
 
-	jint sample_rate = env->CallIntMethod(_back_ptr, MID_audioSampleRate);
+	jint sample_rate = env->CallIntMethod(back_ptr, MID_audioSampleRate);
 	if (env->ExceptionCheck()) {
 		warning("Error finding audio sample rate - assuming 11025HZ");
 
@@ -226,7 +215,7 @@ void OSystem_Android::initBackend() {
 	_mixer = new Audio::MixerImpl(this, sample_rate);
 	_mixer->setReady(true);
 
-	env->CallVoidMethod(_back_ptr, MID_initBackend);
+	env->CallVoidMethod(back_ptr, MID_initBackend);
 
 	if (env->ExceptionCheck()) {
 		error("Error in Java initBackend");
@@ -249,7 +238,7 @@ void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
 	JNIEnv *env = JNU_GetEnv();
 
 	jobjectArray array =
-		(jobjectArray)env->CallObjectMethod(_back_ptr, MID_getPluginDirectories);
+		(jobjectArray)env->CallObjectMethod(back_ptr, MID_getPluginDirectories);
 	if (env->ExceptionCheck()) {
 		warning("Error finding plugin directories");
 
@@ -490,7 +479,7 @@ void OSystem_Android::setWindowCaption(const char *caption) {
 
 	JNIEnv *env = JNU_GetEnv();
 	jstring java_caption = env->NewStringUTF(caption);
-	env->CallVoidMethod(_back_ptr, MID_setWindowCaption, java_caption);
+	env->CallVoidMethod(back_ptr, MID_setWindowCaption, java_caption);
 
 	if (env->ExceptionCheck()) {
 		warning("Failed to set window caption");
@@ -508,7 +497,7 @@ void OSystem_Android::displayMessageOnOSD(const char *msg) {
 	JNIEnv *env = JNU_GetEnv();
 	jstring java_msg = env->NewStringUTF(msg);
 
-	env->CallVoidMethod(_back_ptr, MID_displayMessageOnOSD, java_msg);
+	env->CallVoidMethod(back_ptr, MID_displayMessageOnOSD, java_msg);
 
 	if (env->ExceptionCheck()) {
 		warning("Failed to display OSD message");
@@ -525,7 +514,7 @@ void OSystem_Android::showVirtualKeyboard(bool enable) {
 
 	JNIEnv *env = JNU_GetEnv();
 
-	env->CallVoidMethod(_back_ptr, MID_showVirtualKeyboard, enable);
+	env->CallVoidMethod(back_ptr, MID_showVirtualKeyboard, enable);
 
 	if (env->ExceptionCheck()) {
 		error("Error trying to show virtual keyboard");
@@ -574,7 +563,7 @@ void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
 	JNIEnv *env = JNU_GetEnv();
 
 	jobjectArray array =
-		(jobjectArray)env->CallObjectMethod(_back_ptr, MID_getSysArchives);
+		(jobjectArray)env->CallObjectMethod(back_ptr, MID_getSysArchives);
 
 	if (env->ExceptionCheck()) {
 		warning("Error finding system archive path");
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index b31c0fd..da487c5 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -78,6 +78,9 @@ extern void checkGlError(const char *expr, const char *file, int line);
 #define GLCALL(x) do { (x); } while (false)
 #endif
 
+// back pointer to (java) peer instance
+extern jobject back_ptr;
+
 extern JNIEnv *JNU_GetEnv();
 extern void JNU_AttachThread();
 extern void JNU_DetachThread();
@@ -94,9 +97,6 @@ protected:
 
 class OSystem_Android : public BaseBackend, public PaletteManager {
 private:
-	// back pointer to (java) peer instance
-	jobject _back_ptr;
-
 	jmethodID MID_displayMessageOnOSD;
 	jmethodID MID_setWindowCaption;
 	jmethodID MID_initBackend;
@@ -155,7 +155,7 @@ private:
 public:
 	OSystem_Android(jobject am);
 	virtual ~OSystem_Android();
-	bool initJavaHooks(JNIEnv *env, jobject self);
+	bool initJavaHooks(JNIEnv *env);
 
 	virtual void initBackend();
 	void addPluginDirectories(Common::FSList &dirs) const;
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index eb5a66c..2b73038 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -63,7 +63,7 @@ void OSystem_Android::setupScummVMSurface() {
 	ENTER();
 
 	JNIEnv *env = JNU_GetEnv();
-	env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
+	env->CallVoidMethod(back_ptr, MID_setupScummVMSurface);
 
 	if (env->ExceptionCheck())
 		return;
@@ -117,7 +117,7 @@ void OSystem_Android::setupScummVMSurface() {
 
 void OSystem_Android::destroyScummVMSurface() {
 	JNIEnv *env = JNU_GetEnv();
-	env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
+	env->CallVoidMethod(back_ptr, MID_destroyScummVMSurface);
 	// Can't use OpenGLES functions after this
 }
 
@@ -262,7 +262,7 @@ void OSystem_Android::updateScreen() {
 	GLCALL(glPopMatrix());
 
 	JNIEnv *env = JNU_GetEnv();
-	if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
+	if (!env->CallBooleanMethod(back_ptr, MID_swapBuffers)) {
 		// Context lost -> need to reinit GL
 		destroyScummVMSurface();
 		setupScummVMSurface();
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index e5d0f71..b81587b 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -34,7 +34,10 @@
 #undef JNIEXPORT
 #define JNIEXPORT __attribute__ ((visibility("default")))
 
+jobject back_ptr;
+
 static JavaVM *cached_jvm;
+
 static jfieldID FID_Event_type;
 static jfieldID FID_Event_synthetic;
 static jfieldID FID_Event_kbd_keycode;
@@ -93,8 +96,13 @@ static void ScummVM_create(JNIEnv *env, jobject self, jobject am) {
 	g_sys = new OSystem_Android(am);
 	assert(g_sys);
 
+	// weak global ref to allow class to be unloaded
+	// ... except dalvik implements NewWeakGlobalRef only on froyo
+	//back_ptr = env->NewWeakGlobalRef(self);
+	back_ptr = env->NewGlobalRef(self);
+
 	// Exception already thrown by initJavaHooks?
-	if (!g_sys->initJavaHooks(env, self))
+	if (!g_sys->initJavaHooks(env))
 		return;
 
 	env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)g_sys);
@@ -109,6 +117,10 @@ static void ScummVM_nativeDestroy(JNIEnv *env, jobject self) {
 	g_system = 0;
 	g_sys = 0;
 	delete tmp;
+
+	// see above
+	//JNU_GetEnv()->DeleteWeakGlobalRef(back_ptr);
+	JNU_GetEnv()->DeleteGlobalRef(back_ptr);
 }
 
 static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) {


Commit: f80d993860257a8e74936bc74eb99bda2fbfcaa4
    https://github.com/scummvm/scummvm/commit/f80d993860257a8e74936bc74eb99bda2fbfcaa4
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:32-08:00

Commit Message:
ANDROID: Wrap JNI code in a class

Changed paths:
  A backends/platform/android/jni.h
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/asset-archive.cpp
    backends/platform/android/gfx.cpp
    backends/platform/android/jni.cpp



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index f2c9a74..9437bf5 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -98,8 +98,6 @@ static inline T scalef(T in, float numerator, float denominator) {
 	return static_cast<float>(in) * numerator / denominator;
 }
 
-OSystem_Android *g_sys = 0;
-
 OSystem_Android::OSystem_Android(jobject am) :
 	_screen_changeid(0),
 	_force_redraw(false),
@@ -166,7 +164,7 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 	OSystem_Android *system = (OSystem_Android *)arg;
 	DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
 
-	JNU_AttachThread();
+	JNI::attachThread();
 
 	struct timespec tv;
 	tv.tv_sec = 0;
@@ -177,7 +175,7 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 		nanosleep(&tv, 0);
 	}
 
-	JNU_DetachThread();
+	JNI::detachThread();
 
 	return 0;
 }
@@ -185,7 +183,7 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 void OSystem_Android::initBackend() {
 	ENTER();
 
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 
 	ConfMan.setInt("autosave_period", 0);
 	ConfMan.setInt("FM_medium_quality", true);
@@ -235,10 +233,10 @@ void OSystem_Android::initBackend() {
 void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
 	ENTER();
 
-	JNIEnv *env = JNU_GetEnv();
-
+	JNIEnv *env = JNI::getEnv();
 	jobjectArray array =
 		(jobjectArray)env->CallObjectMethod(back_ptr, MID_getPluginDirectories);
+
 	if (env->ExceptionCheck()) {
 		warning("Error finding plugin directories");
 
@@ -477,7 +475,7 @@ void OSystem_Android::quit() {
 void OSystem_Android::setWindowCaption(const char *caption) {
 	ENTER("%s", caption);
 
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	jstring java_caption = env->NewStringUTF(caption);
 	env->CallVoidMethod(back_ptr, MID_setWindowCaption, java_caption);
 
@@ -494,9 +492,8 @@ void OSystem_Android::setWindowCaption(const char *caption) {
 void OSystem_Android::displayMessageOnOSD(const char *msg) {
 	ENTER("%s", msg);
 
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	jstring java_msg = env->NewStringUTF(msg);
-
 	env->CallVoidMethod(back_ptr, MID_displayMessageOnOSD, java_msg);
 
 	if (env->ExceptionCheck()) {
@@ -512,8 +509,7 @@ void OSystem_Android::displayMessageOnOSD(const char *msg) {
 void OSystem_Android::showVirtualKeyboard(bool enable) {
 	ENTER("%d", enable);
 
-	JNIEnv *env = JNU_GetEnv();
-
+	JNIEnv *env = JNI::getEnv();
 	env->CallVoidMethod(back_ptr, MID_showVirtualKeyboard, enable);
 
 	if (env->ExceptionCheck()) {
@@ -560,8 +556,7 @@ void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
 												int priority) {
 	s.add("ASSET", _asset_archive, priority, false);
 
-	JNIEnv *env = JNU_GetEnv();
-
+	JNIEnv *env = JNI::getEnv();
 	jobjectArray array =
 		(jobjectArray)env->CallObjectMethod(back_ptr, MID_getSysArchives);
 
@@ -606,7 +601,7 @@ void OSystem_Android::logMessage(LogMessageType::Type type, const char *message)
 
 #ifdef DYNAMIC_MODULES
 void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
-	g_sys->addPluginDirectories(dirs);
+	((OSystem_Android *)g_system)->addPluginDirectories(dirs);
 }
 #endif
 
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index da487c5..0ccf57e 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -36,6 +36,7 @@
 #include "backends/plugins/posix/posix-provider.h"
 #include "backends/fs/posix/posix-fs-factory.h"
 
+#include "backends/platform/android/jni.h"
 #include "backends/platform/android/texture.h"
 
 #include <pthread.h>
@@ -81,13 +82,6 @@ extern void checkGlError(const char *expr, const char *file, int line);
 // back pointer to (java) peer instance
 extern jobject back_ptr;
 
-extern JNIEnv *JNU_GetEnv();
-extern void JNU_AttachThread();
-extern void JNU_DetachThread();
-
-class OSystem_Android;
-extern OSystem_Android *g_sys;
-
 #ifdef DYNAMIC_MODULES
 class AndroidPluginProvider : public POSIXPluginProvider {
 protected:
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index 71ce25a..eb25308 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -36,10 +36,9 @@
 #include "common/archive.h"
 #include "common/debug.h"
 
+#include "backends/platform/android/jni.h"
 #include "backends/platform/android/asset-archive.h"
 
-extern JNIEnv *JNU_GetEnv();
-
 // Must match android.content.res.AssetManager.ACCESS_*
 const jint ACCESS_UNKNOWN = 0;
 const jint ACCESS_RANDOM = 1;
@@ -124,7 +123,7 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) :
 }
 
 JavaInputStream::~JavaInputStream() {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	close(env);
 
 	env->DeleteGlobalRef(_buf);
@@ -139,7 +138,7 @@ void JavaInputStream::close(JNIEnv *env) {
 }
 
 uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 
 	if (_buflen < jint(dataSize)) {
 		_buflen = dataSize;
@@ -171,7 +170,7 @@ uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
 }
 
 bool JavaInputStream::seek(int32 offset, int whence) {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	uint32 newpos;
 
 	switch (whence) {
@@ -318,7 +317,7 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
 }
 
 AssetFdReadStream::~AssetFdReadStream() {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	env->CallVoidMethod(_assetfd, MID_close);
 
 	if (env->ExceptionCheck())
@@ -369,7 +368,7 @@ bool AssetFdReadStream::seek(int32 offset, int whence) {
 }
 
 AndroidAssetArchive::AndroidAssetArchive(jobject am) {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	_am = env->NewGlobalRef(am);
 
 	jclass cls = env->GetObjectClass(_am);
@@ -387,12 +386,12 @@ AndroidAssetArchive::AndroidAssetArchive(jobject am) {
 }
 
 AndroidAssetArchive::~AndroidAssetArchive() {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	env->DeleteGlobalRef(_am);
 }
 
 bool AndroidAssetArchive::hasFile(const Common::String &name) {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	jstring path = env->NewStringUTF(name.c_str());
 	jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN);
 	if (env->ExceptionCheck()) {
@@ -412,7 +411,7 @@ bool AndroidAssetArchive::hasFile(const Common::String &name) {
 }
 
 int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	Common::List<Common::String> dirlist;
 	dirlist.push_back("");
 
@@ -469,7 +468,7 @@ Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &na
 }
 
 Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	jstring jpath = env->NewStringUTF(path.c_str());
 
 	// Try openFd() first ...
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 2b73038..2370958 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -62,7 +62,7 @@ int OSystem_Android::getGraphicsMode() const {
 void OSystem_Android::setupScummVMSurface() {
 	ENTER();
 
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	env->CallVoidMethod(back_ptr, MID_setupScummVMSurface);
 
 	if (env->ExceptionCheck())
@@ -116,7 +116,7 @@ void OSystem_Android::setupScummVMSurface() {
 }
 
 void OSystem_Android::destroyScummVMSurface() {
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	env->CallVoidMethod(back_ptr, MID_destroyScummVMSurface);
 	// Can't use OpenGLES functions after this
 }
@@ -261,7 +261,7 @@ void OSystem_Android::updateScreen() {
 
 	GLCALL(glPopMatrix());
 
-	JNIEnv *env = JNU_GetEnv();
+	JNIEnv *env = JNI::getEnv();
 	if (!env->CallBooleanMethod(back_ptr, MID_swapBuffers)) {
 		// Context lost -> need to reinit GL
 		destroyScummVMSurface();
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index b81587b..4fa08ef 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -30,28 +30,116 @@
 
 #include "backends/platform/android/android.h"
 
-// Fix JNIEXPORT declaration to actually do something useful
-#undef JNIEXPORT
-#define JNIEXPORT __attribute__ ((visibility("default")))
-
 jobject back_ptr;
 
-static JavaVM *cached_jvm;
+__attribute__ ((visibility("default")))
+jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
+	return JNI::onLoad(vm);
+}
+
+JavaVM *JNI::_vm = 0;
+jobject JNI::_jobj = 0;
+OSystem_Android *JNI::_system = 0;
+
+jfieldID JNI::_FID_Event_type = 0;
+jfieldID JNI::_FID_Event_synthetic = 0;
+jfieldID JNI::_FID_Event_kbd_keycode = 0;
+jfieldID JNI::_FID_Event_kbd_ascii = 0;
+jfieldID JNI::_FID_Event_kbd_flags = 0;
+jfieldID JNI::_FID_Event_mouse_x = 0;
+jfieldID JNI::_FID_Event_mouse_y = 0;
+jfieldID JNI::_FID_Event_mouse_relative = 0;
+jfieldID JNI::_FID_ScummVM_nativeScummVM = 0;
+
+const JNINativeMethod JNI::_natives[] = {
+	{ "create", "(Landroid/content/res/AssetManager;)V",
+		(void *)JNI::create },
+	{ "nativeDestroy", "()V",
+		(void *)JNI::destroy },
+	{ "scummVMMain", "([Ljava/lang/String;)I",
+	 	(void *)JNI::main },
+	{ "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
+		(void *)JNI::pushEvent },
+	{ "audioMixCallback", "([B)V",
+		(void *)JNI::audioMixCallback },
+	{ "setConfMan", "(Ljava/lang/String;I)V",
+		(void *)JNI::setConfManInt },
+	{ "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
+		(void *)JNI::setConfManString },
+	{ "enableZoning", "(Z)V",
+		(void *)JNI::enableZoning },
+	{ "setSurfaceSize", "(II)V",
+		(void *)JNI::setSurfaceSize },
+};
+
+JNI::JNI() {
+}
+
+JNI::~JNI() {
+}
+
+jint JNI::onLoad(JavaVM *vm) {
+	_vm = vm;
+
+	JNIEnv *env;
+
+	if (_vm->GetEnv((void **)&env, JNI_VERSION_1_2))
+		return JNI_ERR;
+
+	jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
+	if (cls == 0)
+		return JNI_ERR;
+
+	if (env->RegisterNatives(cls, _natives, ARRAYSIZE(_natives)) < 0)
+		return JNI_ERR;
+
+	_FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
+	if (_FID_ScummVM_nativeScummVM == 0)
+		return JNI_ERR;
+
+	jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
+	if (event == 0)
+		return JNI_ERR;
+
+	_FID_Event_type = env->GetFieldID(event, "type", "I");
+	if (_FID_Event_type == 0)
+		return JNI_ERR;
+
+	_FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
+	if (_FID_Event_synthetic == 0)
+		return JNI_ERR;
+
+	_FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
+	if (_FID_Event_kbd_keycode == 0)
+		return JNI_ERR;
+
+	_FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
+	if (_FID_Event_kbd_ascii == 0)
+		return JNI_ERR;
+
+	_FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
+	if (_FID_Event_kbd_flags == 0)
+		return JNI_ERR;
+
+	_FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
+	if (_FID_Event_mouse_x == 0)
+		return JNI_ERR;
+
+	_FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
+	if (_FID_Event_mouse_y == 0)
+		return JNI_ERR;
+
+	_FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
+	if (_FID_Event_mouse_relative == 0)
+		return JNI_ERR;
 
-static jfieldID FID_Event_type;
-static jfieldID FID_Event_synthetic;
-static jfieldID FID_Event_kbd_keycode;
-static jfieldID FID_Event_kbd_ascii;
-static jfieldID FID_Event_kbd_flags;
-static jfieldID FID_Event_mouse_x;
-static jfieldID FID_Event_mouse_y;
-static jfieldID FID_Event_mouse_relative;
-static jfieldID FID_ScummVM_nativeScummVM;
+	return JNI_VERSION_1_2;
+}
 
-JNIEnv *JNU_GetEnv() {
+JNIEnv *JNI::getEnv() {
 	JNIEnv *env = 0;
 
-	jint res = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
+	jint res = _vm->GetEnv((void **)&env, JNI_VERSION_1_2);
 
 	if (res != JNI_OK) {
 		LOGE("GetEnv() failed: %d", res);
@@ -61,9 +149,10 @@ JNIEnv *JNU_GetEnv() {
 	return env;
 }
 
-void JNU_AttachThread() {
+void JNI::attachThread() {
 	JNIEnv *env = 0;
-	jint res = cached_jvm->AttachCurrentThread(&env, 0);
+
+	jint res = _vm->AttachCurrentThread(&env, 0);
 
 	if (res != JNI_OK) {
 		LOGE("AttachCurrentThread() failed: %d", res);
@@ -71,8 +160,8 @@ void JNU_AttachThread() {
 	}
 }
 
-void JNU_DetachThread() {
-	jint res = cached_jvm->DetachCurrentThread();
+void JNI::detachThread() {
+	jint res = _vm->DetachCurrentThread();
 
 	if (res != JNI_OK) {
 		LOGE("DetachCurrentThread() failed: %d", res);
@@ -80,7 +169,7 @@ void JNU_DetachThread() {
 	}
 }
 
-static void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
+void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
 	jclass cls = env->FindClass(name);
 
 	// if cls is 0, an exception has already been thrown
@@ -90,49 +179,50 @@ static void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
 	env->DeleteLocalRef(cls);
 }
 
-static void ScummVM_create(JNIEnv *env, jobject self, jobject am) {
-	assert(!g_system);
+void JNI::create(JNIEnv *env, jobject self, jobject am) {
+	assert(!_system);
 
-	g_sys = new OSystem_Android(am);
-	assert(g_sys);
+	_system = new OSystem_Android(am);
+	assert(_system);
 
 	// weak global ref to allow class to be unloaded
 	// ... except dalvik implements NewWeakGlobalRef only on froyo
-	//back_ptr = env->NewWeakGlobalRef(self);
-	back_ptr = env->NewGlobalRef(self);
+	//_jobj = env->NewWeakGlobalRef(self);
+	_jobj = env->NewGlobalRef(self);
+	back_ptr = _jobj;
 
 	// Exception already thrown by initJavaHooks?
-	if (!g_sys->initJavaHooks(env))
+	if (!_system->initJavaHooks(env))
 		return;
 
-	env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)g_sys);
+	env->SetLongField(self, _FID_ScummVM_nativeScummVM, (jlong)_system);
 
-	g_system = g_sys;
+	g_system = _system;
 }
 
-static void ScummVM_nativeDestroy(JNIEnv *env, jobject self) {
-	assert(g_sys);
+void JNI::destroy(JNIEnv *env, jobject self) {
+	assert(_system);
 
-	OSystem_Android *tmp = g_sys;
+	OSystem_Android *tmp = _system;
 	g_system = 0;
-	g_sys = 0;
+	_system = 0;
 	delete tmp;
 
 	// see above
-	//JNU_GetEnv()->DeleteWeakGlobalRef(back_ptr);
-	JNU_GetEnv()->DeleteGlobalRef(back_ptr);
+	//JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
+	JNI::getEnv()->DeleteGlobalRef(_jobj);
 }
 
-static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) {
-	assert(g_sys);
+jint JNI::main(JNIEnv *env, jobject self, jobjectArray args) {
+	assert(_system);
 
 	const int MAX_NARGS = 32;
 	int res = -1;
 
 	int argc = env->GetArrayLength(args);
 	if (argc > MAX_NARGS) {
-		JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
-						"too many arguments");
+		throwByName(env, "java/lang/IllegalArgumentException",
+					"too many arguments");
 		return 0;
 	}
 
@@ -169,7 +259,7 @@ static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) {
 
 	LOGI("Exiting scummvm_main");
 
-	g_sys->quit();
+	_system->quit();
 
 cleanup:
 	nargs--;
@@ -191,25 +281,25 @@ cleanup:
 	return res;
 }
 
-static void ScummVM_pushEvent(JNIEnv *env, jobject self, jobject java_event) {
-	assert(g_sys);
+void JNI::pushEvent(JNIEnv *env, jobject self, jobject java_event) {
+	assert(_system);
 
 	Common::Event event;
 	event.type = (Common::EventType)env->GetIntField(java_event,
-														FID_Event_type);
+														_FID_Event_type);
 
 	event.synthetic =
-		env->GetBooleanField(java_event, FID_Event_synthetic);
+		env->GetBooleanField(java_event, _FID_Event_synthetic);
 
 	switch (event.type) {
 	case Common::EVENT_KEYDOWN:
 	case Common::EVENT_KEYUP:
 		event.kbd.keycode = (Common::KeyCode)env->GetIntField(
-			java_event, FID_Event_kbd_keycode);
+			java_event, _FID_Event_kbd_keycode);
 		event.kbd.ascii = static_cast<int>(env->GetIntField(
-			java_event, FID_Event_kbd_ascii));
+			java_event, _FID_Event_kbd_ascii));
 		event.kbd.flags = static_cast<int>(env->GetIntField(
-			java_event, FID_Event_kbd_flags));
+			java_event, _FID_Event_kbd_flags));
 		break;
 	case Common::EVENT_MOUSEMOVE:
 	case Common::EVENT_LBUTTONDOWN:
@@ -221,25 +311,24 @@ static void ScummVM_pushEvent(JNIEnv *env, jobject self, jobject java_event) {
 	case Common::EVENT_MBUTTONDOWN:
 	case Common::EVENT_MBUTTONUP:
 		event.mouse.x =
-			env->GetIntField(java_event, FID_Event_mouse_x);
+			env->GetIntField(java_event, _FID_Event_mouse_x);
 		event.mouse.y =
-			env->GetIntField(java_event, FID_Event_mouse_y);
+			env->GetIntField(java_event, _FID_Event_mouse_y);
 		// This is a terrible hack.	 We stash "relativeness"
 		// in the kbd.flags field until pollEvent() can work
 		// it out.
 		event.kbd.flags = env->GetBooleanField(
-			java_event, FID_Event_mouse_relative) ? 1 : 0;
+			java_event, _FID_Event_mouse_relative) ? 1 : 0;
 		break;
 	default:
 		break;
 	}
 
-	g_sys->pushEvent(event);
+	_system->pushEvent(event);
 }
 
-static void ScummVM_audioMixCallback(JNIEnv *env, jobject self,
-										jbyteArray jbuf) {
-	assert(g_sys);
+void JNI::audioMixCallback(JNIEnv *env, jobject self, jbyteArray jbuf) {
+	assert(_system);
 
 	jsize len = env->GetArrayLength(jbuf);
 	jbyte *buf = env->GetByteArrayElements(jbuf, 0);
@@ -250,15 +339,14 @@ static void ScummVM_audioMixCallback(JNIEnv *env, jobject self,
 	}
 
 	Audio::MixerImpl *mixer =
-		static_cast<Audio::MixerImpl *>(g_sys->getMixer());
+		static_cast<Audio::MixerImpl *>(_system->getMixer());
 	assert(mixer);
 	mixer->mixCallback(reinterpret_cast<byte *>(buf), len);
 
 	env->ReleaseByteArrayElements(jbuf, buf, 0);
 }
 
-static void ScummVM_setConfManInt(JNIEnv *env, jclass cls,
-									jstring key_obj, jint value) {
+void JNI::setConfManInt(JNIEnv *env, jclass cls, jstring key_obj, jint value) {
 	ENTER("%p, %d", key_obj, (int)value);
 
 	const char *key = env->GetStringUTFChars(key_obj, 0);
@@ -271,8 +359,8 @@ static void ScummVM_setConfManInt(JNIEnv *env, jclass cls,
 	env->ReleaseStringUTFChars(key_obj, key);
 }
 
-static void ScummVM_setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
-										jstring value_obj) {
+void JNI::setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
+							jstring value_obj) {
 	ENTER("%p, %p", key_obj, value_obj);
 
 	const char *key = env->GetStringUTFChars(key_obj, 0);
@@ -293,97 +381,16 @@ static void ScummVM_setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
 	env->ReleaseStringUTFChars(key_obj, key);
 }
 
-static void ScummVM_enableZoning(JNIEnv *env, jobject self, jboolean enable) {
-	assert(g_sys);
+void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
+	assert(_system);
 
-	g_sys->enableZoning(enable);
+	_system->enableZoning(enable);
 }
 
-static void ScummVM_setSurfaceSize(JNIEnv *env, jobject self,
-									jint width, jint height) {
-	assert(g_sys);
-
-	g_sys->setSurfaceSize(width, height);
-}
-
-const static JNINativeMethod gMethods[] = {
-	{ "create", "(Landroid/content/res/AssetManager;)V",
-		(void *)ScummVM_create },
-	{ "nativeDestroy", "()V",
-		(void *)ScummVM_nativeDestroy },
-	{ "scummVMMain", "([Ljava/lang/String;)I",
-	 	(void *)ScummVM_scummVMMain },
-	{ "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V",
-		(void *)ScummVM_pushEvent },
-	{ "audioMixCallback", "([B)V",
-		(void *)ScummVM_audioMixCallback },
-	{ "setConfMan", "(Ljava/lang/String;I)V",
-		(void *)ScummVM_setConfManInt },
-	{ "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V",
-		(void *)ScummVM_setConfManString },
-	{ "enableZoning", "(Z)V",
-		(void *)ScummVM_enableZoning },
-	{ "setSurfaceSize", "(II)V",
-		(void *)ScummVM_setSurfaceSize },
-};
-
-JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *jvm, void *reserved) {
-	cached_jvm = jvm;
-
-	JNIEnv *env;
-
-	if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2))
-		return JNI_ERR;
-
-	jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM");
-	if (cls == 0)
-		return JNI_ERR;
-
-	if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0)
-		return JNI_ERR;
-
-	FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
-	if (FID_ScummVM_nativeScummVM == 0)
-		return JNI_ERR;
+void JNI::setSurfaceSize(JNIEnv *env, jobject self, jint width, jint height) {
+	assert(_system);
 
-	jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
-	if (event == 0)
-		return JNI_ERR;
-
-	FID_Event_type = env->GetFieldID(event, "type", "I");
-	if (FID_Event_type == 0)
-		return JNI_ERR;
-
-	FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
-	if (FID_Event_synthetic == 0)
-		return JNI_ERR;
-
-	FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
-	if (FID_Event_kbd_keycode == 0)
-		return JNI_ERR;
-
-	FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
-	if (FID_Event_kbd_ascii == 0)
-		return JNI_ERR;
-
-	FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
-	if (FID_Event_kbd_flags == 0)
-		return JNI_ERR;
-
-	FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
-	if (FID_Event_mouse_x == 0)
-		return JNI_ERR;
-
-	FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
-	if (FID_Event_mouse_y == 0)
-		return JNI_ERR;
-
-	FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
-	if (FID_Event_mouse_relative == 0)
-		return JNI_ERR;
-
-	return JNI_VERSION_1_2;
+	_system->setSurfaceSize(width, height);
 }
 
 #endif
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
new file mode 100644
index 0000000..39276b9
--- /dev/null
+++ b/backends/platform/android/jni.h
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef _ANDROID_JNI_H_
+#define _ANDROID_JNI_H_
+
+#if defined(__ANDROID__)
+
+#include <jni.h>
+
+extern jobject back_ptr;
+
+class OSystem_Android;
+
+class JNI {
+public:
+	static jint onLoad(JavaVM *vm);
+
+	static JNIEnv *getEnv();
+
+	static void attachThread();
+	static void detachThread();
+
+private:
+	JNI();
+	virtual ~JNI();
+
+private:
+	static JavaVM *_vm;
+	// back pointer to (java) peer instance
+	static jobject _jobj;
+	static OSystem_Android *_system;
+
+	static jfieldID _FID_Event_type;
+	static jfieldID _FID_Event_synthetic;
+	static jfieldID _FID_Event_kbd_keycode;
+	static jfieldID _FID_Event_kbd_ascii;
+	static jfieldID _FID_Event_kbd_flags;
+	static jfieldID _FID_Event_mouse_x;
+	static jfieldID _FID_Event_mouse_y;
+	static jfieldID _FID_Event_mouse_relative;
+	static jfieldID _FID_ScummVM_nativeScummVM;
+
+	static const JNINativeMethod _natives[];
+
+	static void throwByName(JNIEnv *env, const char *name, const char *msg);
+
+	// natives for the dark side
+	static void create(JNIEnv *env, jobject self, jobject am);
+	static void destroy(JNIEnv *env, jobject self);
+	static jint main(JNIEnv *env, jobject self, jobjectArray args);
+	static void pushEvent(JNIEnv *env, jobject self, jobject java_event);
+	static void audioMixCallback(JNIEnv *env, jobject self, jbyteArray jbuf);
+	static void setConfManInt(JNIEnv *env, jclass cls, jstring key_obj,
+								jint value);
+	static void setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
+							   		jstring value_obj);
+	static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
+	static void setSurfaceSize(JNIEnv *env, jobject self, jint width,
+								jint height);
+};
+
+#endif
+#endif
+


Commit: 53b5808d4f16a44779ef5fd8a5c8ca5e262e0379
    https://github.com/scummvm/scummvm/commit/53b5808d4f16a44779ef5fd8a5c8ca5e262e0379
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:32-08:00

Commit Message:
ANDROID: Move rest of everything JNI

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/asset-archive.h
    backends/platform/android/gfx.cpp
    backends/platform/android/jni.cpp
    backends/platform/android/jni.h



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 9437bf5..3639987 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -40,8 +40,8 @@
 #include "backends/saves/default/default-saves.h"
 #include "backends/timer/default/default-timer.h"
 
+#include "backends/platform/android/jni.h"
 #include "backends/platform/android/android.h"
-#include "backends/platform/android/asset-archive.h"
 
 const char *android_log_tag = "ScummVM";
 
@@ -98,7 +98,7 @@ static inline T scalef(T in, float numerator, float denominator) {
 	return static_cast<float>(in) * numerator / denominator;
 }
 
-OSystem_Android::OSystem_Android(jobject am) :
+OSystem_Android::OSystem_Android() :
 	_screen_changeid(0),
 	_force_redraw(false),
 	_game_texture(0),
@@ -112,7 +112,6 @@ OSystem_Android::OSystem_Android(jobject am) :
 	_mixer(0),
 	_timer(0),
 	_fsFactory(new POSIXFilesystemFactory()),
-	_asset_archive(new AndroidAssetArchive(am)),
 	_shake_offset(0),
 	_event_queue_lock(createMutex()) {
 }
@@ -124,42 +123,16 @@ OSystem_Android::~OSystem_Android() {
 	delete _overlay_texture;
 	delete _mouse_texture;
 
-	destroyScummVMSurface();
+	JNI::destroySurface();
 
 	delete _savefile;
 	delete _mixer;
 	delete _timer;
 	delete _fsFactory;
-	delete _asset_archive;
 
 	deleteMutex(_event_queue_lock);
 }
 
-bool OSystem_Android::initJavaHooks(JNIEnv *env) {
-	jclass cls = env->GetObjectClass(back_ptr);
-
-#define FIND_METHOD(name, signature) do {						\
-		MID_ ## name = env->GetMethodID(cls, #name, signature); \
-		if (MID_ ## name == 0)									\
-			return false;										\
-	} while (0)
-
-	FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
-	FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
-	FIND_METHOD(initBackend, "()V");
-	FIND_METHOD(audioSampleRate, "()I");
-	FIND_METHOD(showVirtualKeyboard, "(Z)V");
-	FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
-	FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
-	FIND_METHOD(setupScummVMSurface, "()V");
-	FIND_METHOD(destroyScummVMSurface, "()V");
-	FIND_METHOD(swapBuffers, "()Z");
-
-#undef FIND_METHOD
-
-	return true;
-}
-
 void *OSystem_Android::timerThreadFunc(void *arg) {
 	OSystem_Android *system = (OSystem_Android *)arg;
 	DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
@@ -183,8 +156,6 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 void OSystem_Android::initBackend() {
 	ENTER();
 
-	JNIEnv *env = JNI::getEnv();
-
 	ConfMan.setInt("autosave_period", 0);
 	ConfMan.setInt("FM_medium_quality", true);
 
@@ -200,74 +171,23 @@ void OSystem_Android::initBackend() {
 
 	gettimeofday(&_startTime, 0);
 
-	jint sample_rate = env->CallIntMethod(back_ptr, MID_audioSampleRate);
-	if (env->ExceptionCheck()) {
-		warning("Error finding audio sample rate - assuming 11025HZ");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-
-		sample_rate = 11025;
-	}
-
-	_mixer = new Audio::MixerImpl(this, sample_rate);
+	_mixer = new Audio::MixerImpl(this, JNI::getAudioSampleRate());
 	_mixer->setReady(true);
 
-	env->CallVoidMethod(back_ptr, MID_initBackend);
-
-	if (env->ExceptionCheck()) {
-		error("Error in Java initBackend");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-	}
+	JNI::initBackend();
 
 	_timer_thread_exit = false;
 	pthread_create(&_timer_thread, 0, timerThreadFunc, this);
 
 	OSystem::initBackend();
 
-	setupScummVMSurface();
+	setupSurface();
 }
 
 void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
 	ENTER();
 
-	JNIEnv *env = JNI::getEnv();
-	jobjectArray array =
-		(jobjectArray)env->CallObjectMethod(back_ptr, MID_getPluginDirectories);
-
-	if (env->ExceptionCheck()) {
-		warning("Error finding plugin directories");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-
-		return;
-	}
-
-	jsize size = env->GetArrayLength(array);
-	for (jsize i = 0; i < size; ++i) {
-		jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
-
-		if (path_obj == 0)
-			continue;
-
-		const char *path = env->GetStringUTFChars(path_obj, 0);
-		if (path == 0) {
-			warning("Error getting string characters from plugin directory");
-
-			env->ExceptionClear();
-			env->DeleteLocalRef(path_obj);
-
-			continue;
-		}
-
-		dirs.push_back(Common::FSNode(path));
-
-		env->ReleaseStringUTFChars(path_obj, path);
-		env->DeleteLocalRef(path_obj);
-	}
+	JNI::getPluginDirectories(dirs);
 }
 
 bool OSystem_Android::hasFeature(Feature f) {
@@ -380,8 +300,8 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 	case Common::EVENT_SCREEN_CHANGED:
 		debug("EVENT_SCREEN_CHANGED");
 		_screen_changeid++;
-		destroyScummVMSurface();
-		setupScummVMSurface();
+		JNI::destroySurface();
+		setupSurface();
 		break;
 	default:
 		break;
@@ -475,49 +395,19 @@ void OSystem_Android::quit() {
 void OSystem_Android::setWindowCaption(const char *caption) {
 	ENTER("%s", caption);
 
-	JNIEnv *env = JNI::getEnv();
-	jstring java_caption = env->NewStringUTF(caption);
-	env->CallVoidMethod(back_ptr, MID_setWindowCaption, java_caption);
-
-	if (env->ExceptionCheck()) {
-		warning("Failed to set window caption");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-	}
-
-	env->DeleteLocalRef(java_caption);
+	JNI::setWindowCaption(caption);
 }
 
 void OSystem_Android::displayMessageOnOSD(const char *msg) {
 	ENTER("%s", msg);
 
-	JNIEnv *env = JNI::getEnv();
-	jstring java_msg = env->NewStringUTF(msg);
-	env->CallVoidMethod(back_ptr, MID_displayMessageOnOSD, java_msg);
-
-	if (env->ExceptionCheck()) {
-		warning("Failed to display OSD message");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-	}
-
-	env->DeleteLocalRef(java_msg);
+	JNI::displayMessageOnOSD(msg);
 }
 
 void OSystem_Android::showVirtualKeyboard(bool enable) {
 	ENTER("%d", enable);
 
-	JNIEnv *env = JNI::getEnv();
-	env->CallVoidMethod(back_ptr, MID_showVirtualKeyboard, enable);
-
-	if (env->ExceptionCheck()) {
-		error("Error trying to show virtual keyboard");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
-	}
+	JNI::showVirtualKeyboard(enable);
 }
 
 Common::SaveFileManager *OSystem_Android::getSavefileManager() {
@@ -554,33 +444,9 @@ FilesystemFactory *OSystem_Android::getFilesystemFactory() {
 
 void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
 												int priority) {
-	s.add("ASSET", _asset_archive, priority, false);
-
-	JNIEnv *env = JNI::getEnv();
-	jobjectArray array =
-		(jobjectArray)env->CallObjectMethod(back_ptr, MID_getSysArchives);
-
-	if (env->ExceptionCheck()) {
-		warning("Error finding system archive path");
-
-		env->ExceptionDescribe();
-		env->ExceptionClear();
+	ENTER("");
 
-		return;
-	}
-
-	jsize size = env->GetArrayLength(array);
-	for (jsize i = 0; i < size; ++i) {
-		jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
-		const char *path = env->GetStringUTFChars(path_obj, 0);
-
-		if (path != 0) {
-			s.addDirectory(path, path, priority);
-			env->ReleaseStringUTFChars(path_obj, path);
-		}
-
-		env->DeleteLocalRef(path_obj);
-	}
+	JNI::addSysArchivesToSearchSet(s, priority);
 }
 
 void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) {
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 0ccf57e..8fc138d 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -36,12 +36,10 @@
 #include "backends/plugins/posix/posix-provider.h"
 #include "backends/fs/posix/posix-fs-factory.h"
 
-#include "backends/platform/android/jni.h"
 #include "backends/platform/android/texture.h"
 
 #include <pthread.h>
 
-#include <jni.h>
 #include <android/log.h>
 
 #include <GLES/gl.h>
@@ -79,9 +77,6 @@ extern void checkGlError(const char *expr, const char *file, int line);
 #define GLCALL(x) do { (x); } while (false)
 #endif
 
-// back pointer to (java) peer instance
-extern jobject back_ptr;
-
 #ifdef DYNAMIC_MODULES
 class AndroidPluginProvider : public POSIXPluginProvider {
 protected:
@@ -91,17 +86,6 @@ protected:
 
 class OSystem_Android : public BaseBackend, public PaletteManager {
 private:
-	jmethodID MID_displayMessageOnOSD;
-	jmethodID MID_setWindowCaption;
-	jmethodID MID_initBackend;
-	jmethodID MID_audioSampleRate;
-	jmethodID MID_showVirtualKeyboard;
-	jmethodID MID_getSysArchives;
-	jmethodID MID_getPluginDirectories;
-	jmethodID MID_setupScummVMSurface;
-	jmethodID MID_destroyScummVMSurface;
-	jmethodID MID_swapBuffers;
-
 	int _screen_changeid;
 	int _egl_surface_width;
 	int _egl_surface_height;
@@ -138,18 +122,15 @@ private:
 	Audio::MixerImpl *_mixer;
 	Common::TimerManager *_timer;
 	FilesystemFactory *_fsFactory;
-	Common::Archive *_asset_archive;
 	timeval _startTime;
 
-	void setupScummVMSurface();
-	void destroyScummVMSurface();
+	void setupSurface();
 	void setupKeymapper();
 	void _setCursorPalette(const byte *colors, uint start, uint num);
 
 public:
-	OSystem_Android(jobject am);
+	OSystem_Android();
 	virtual ~OSystem_Android();
-	bool initJavaHooks(JNIEnv *env);
 
 	virtual void initBackend();
 	void addPluginDirectories(Common::FSList &dirs) const;
diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h
index 28e4842..6ec86e4 100644
--- a/backends/platform/android/asset-archive.h
+++ b/backends/platform/android/asset-archive.h
@@ -23,6 +23,9 @@
  *
  */
 
+#ifndef _ANDROID_ASSET_H_
+#define _ANDROID_ASSET_H_
+
 #if defined(__ANDROID__)
 
 #include <jni.h>
@@ -51,3 +54,5 @@ private:
 };
 
 #endif
+#endif
+
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 2370958..838e5bc 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -26,6 +26,7 @@
 #if defined(__ANDROID__)
 
 #include "backends/platform/android/android.h"
+#include "backends/platform/android/jni.h"
 
 static inline GLfixed xdiv(int numerator, int denominator) {
 	assert(numerator < (1 << 16));
@@ -47,11 +48,13 @@ int OSystem_Android::getDefaultGraphicsMode() const {
 
 bool OSystem_Android::setGraphicsMode(const char *mode) {
 	ENTER("%s", mode);
+
 	return true;
 }
 
 bool OSystem_Android::setGraphicsMode(int mode) {
 	ENTER("%d", mode);
+
 	return true;
 }
 
@@ -59,13 +62,10 @@ int OSystem_Android::getGraphicsMode() const {
 	return 1;
 }
 
-void OSystem_Android::setupScummVMSurface() {
+void OSystem_Android::setupSurface() {
 	ENTER();
 
-	JNIEnv *env = JNI::getEnv();
-	env->CallVoidMethod(back_ptr, MID_setupScummVMSurface);
-
-	if (env->ExceptionCheck())
+	if (!JNI::setupSurface())
 		return;
 
 	// EGL set up with a new surface.  Initialise OpenGLES context.
@@ -115,12 +115,6 @@ void OSystem_Android::setupScummVMSurface() {
 	clearFocusRectangle();
 }
 
-void OSystem_Android::destroyScummVMSurface() {
-	JNIEnv *env = JNI::getEnv();
-	env->CallVoidMethod(back_ptr, MID_destroyScummVMSurface);
-	// Can't use OpenGLES functions after this
-}
-
 void OSystem_Android::initSize(uint width, uint height,
 								const Graphics::PixelFormat *format) {
 	ENTER("%d, %d, %p", width, height, format);
@@ -158,6 +152,7 @@ void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
 
 void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
 	ENTER("%p, %u, %u", colors, start, num);
+
 	memcpy(colors, _game_texture->palette_const() + start * 3, num * 3);
 }
 
@@ -261,11 +256,10 @@ void OSystem_Android::updateScreen() {
 
 	GLCALL(glPopMatrix());
 
-	JNIEnv *env = JNI::getEnv();
-	if (!env->CallBooleanMethod(back_ptr, MID_swapBuffers)) {
+	if (!JNI::swapBuffers()) {
 		// Context lost -> need to reinit GL
-		destroyScummVMSurface();
-		setupScummVMSurface();
+		JNI::destroySurface();
+		setupSurface();
 	}
 }
 
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
index 4fa08ef..f24a60d 100644
--- a/backends/platform/android/jni.cpp
+++ b/backends/platform/android/jni.cpp
@@ -29,8 +29,8 @@
 #include "common/config-manager.h"
 
 #include "backends/platform/android/android.h"
-
-jobject back_ptr;
+#include "backends/platform/android/asset-archive.h"
+#include "backends/platform/android/jni.h"
 
 __attribute__ ((visibility("default")))
 jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
@@ -39,6 +39,8 @@ jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
 
 JavaVM *JNI::_vm = 0;
 jobject JNI::_jobj = 0;
+
+Common::Archive *JNI::_asset_archive = 0;
 OSystem_Android *JNI::_system = 0;
 
 jfieldID JNI::_FID_Event_type = 0;
@@ -51,6 +53,17 @@ jfieldID JNI::_FID_Event_mouse_y = 0;
 jfieldID JNI::_FID_Event_mouse_relative = 0;
 jfieldID JNI::_FID_ScummVM_nativeScummVM = 0;
 
+jmethodID JNI::_MID_displayMessageOnOSD = 0;
+jmethodID JNI::_MID_setWindowCaption = 0;
+jmethodID JNI::_MID_initBackend = 0;
+jmethodID JNI::_MID_audioSampleRate = 0;
+jmethodID JNI::_MID_showVirtualKeyboard = 0;
+jmethodID JNI::_MID_getSysArchives = 0;
+jmethodID JNI::_MID_getPluginDirectories = 0;
+jmethodID JNI::_MID_setupScummVMSurface = 0;
+jmethodID JNI::_MID_destroyScummVMSurface = 0;
+jmethodID JNI::_MID_swapBuffers = 0;
+
 const JNINativeMethod JNI::_natives[] = {
 	{ "create", "(Landroid/content/res/AssetManager;)V",
 		(void *)JNI::create },
@@ -179,21 +192,192 @@ void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) {
 	env->DeleteLocalRef(cls);
 }
 
+// calls to the dark side
+
+int JNI::getAudioSampleRate() {
+	JNIEnv *env = JNI::getEnv();
+
+	jint sample_rate = env->CallIntMethod(_jobj, _MID_audioSampleRate);
+
+	if (env->ExceptionCheck()) {
+		warning("Error finding audio sample rate - assuming 11025HZ");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+
+		return 11025;
+	}
+
+	return sample_rate;
+}
+
+void JNI::initBackend() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj, _MID_initBackend);
+
+	if (env->ExceptionCheck()) {
+		error("Error in Java initBackend");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+
+		// TODO now what?
+	}
+}
+
+void JNI::getPluginDirectories(Common::FSList &dirs) {
+	JNIEnv *env = JNI::getEnv();
+
+	jobjectArray array =
+		(jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories);
+
+	if (env->ExceptionCheck()) {
+		warning("Error finding plugin directories");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+
+		return;
+	}
+
+	jsize size = env->GetArrayLength(array);
+	for (jsize i = 0; i < size; ++i) {
+		jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+
+		if (path_obj == 0)
+			continue;
+
+		const char *path = env->GetStringUTFChars(path_obj, 0);
+
+		if (path == 0) {
+			warning("Error getting string characters from plugin directory");
+
+			env->ExceptionClear();
+			env->DeleteLocalRef(path_obj);
+
+			continue;
+		}
+
+		dirs.push_back(Common::FSNode(path));
+
+		env->ReleaseStringUTFChars(path_obj, path);
+		env->DeleteLocalRef(path_obj);
+	}
+}
+
+void JNI::setWindowCaption(const char *caption) {
+	JNIEnv *env = JNI::getEnv();
+	jstring java_caption = env->NewStringUTF(caption);
+
+	env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption);
+
+	if (env->ExceptionCheck()) {
+		warning("Failed to set window caption");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+
+	env->DeleteLocalRef(java_caption);
+}
+
+void JNI::displayMessageOnOSD(const char *msg) {
+	JNIEnv *env = JNI::getEnv();
+	jstring java_msg = env->NewStringUTF(msg);
+
+	env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg);
+
+	if (env->ExceptionCheck()) {
+		warning("Failed to display OSD message");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+
+	env->DeleteLocalRef(java_msg);
+}
+
+void JNI::showVirtualKeyboard(bool enable) {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable);
+
+	if (env->ExceptionCheck()) {
+		error("Error trying to show virtual keyboard");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+	}
+}
+
+void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+	JNIEnv *env = JNI::getEnv();
+
+	s.add("ASSET", _asset_archive, priority, false);
+
+	jobjectArray array =
+		(jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives);
+
+	if (env->ExceptionCheck()) {
+		warning("Error finding system archive path");
+
+		env->ExceptionDescribe();
+		env->ExceptionClear();
+
+		return;
+	}
+
+	jsize size = env->GetArrayLength(array);
+	for (jsize i = 0; i < size; ++i) {
+		jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+		const char *path = env->GetStringUTFChars(path_obj, 0);
+
+		if (path != 0) {
+			s.addDirectory(path, path, priority);
+			env->ReleaseStringUTFChars(path_obj, path);
+		}
+
+		env->DeleteLocalRef(path_obj);
+	}
+}
+
+// natives for the dark side
+
 void JNI::create(JNIEnv *env, jobject self, jobject am) {
 	assert(!_system);
 
-	_system = new OSystem_Android(am);
+	_asset_archive = new AndroidAssetArchive(am);
+	assert(_asset_archive);
+
+	_system = new OSystem_Android();
 	assert(_system);
 
 	// weak global ref to allow class to be unloaded
 	// ... except dalvik implements NewWeakGlobalRef only on froyo
 	//_jobj = env->NewWeakGlobalRef(self);
 	_jobj = env->NewGlobalRef(self);
-	back_ptr = _jobj;
 
-	// Exception already thrown by initJavaHooks?
-	if (!_system->initJavaHooks(env))
-		return;
+	jclass cls = env->GetObjectClass(_jobj);
+
+#define FIND_METHOD(name, signature) do {							\
+		_MID_ ## name = env->GetMethodID(cls, #name, signature);	\
+		if (_MID_ ## name == 0)										\
+			return;													\
+	} while (0)
+
+	FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
+	FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
+	FIND_METHOD(initBackend, "()V");
+	FIND_METHOD(audioSampleRate, "()I");
+	FIND_METHOD(showVirtualKeyboard, "(Z)V");
+	FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
+	FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
+	FIND_METHOD(setupScummVMSurface, "()V");
+	FIND_METHOD(destroyScummVMSurface, "()V");
+	FIND_METHOD(swapBuffers, "()Z");
+
+#undef FIND_METHOD
 
 	env->SetLongField(self, _FID_ScummVM_nativeScummVM, (jlong)_system);
 
@@ -208,6 +392,9 @@ void JNI::destroy(JNIEnv *env, jobject self) {
 	_system = 0;
 	delete tmp;
 
+	delete _asset_archive;
+	_asset_archive = 0;
+
 	// see above
 	//JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
 	JNI::getEnv()->DeleteGlobalRef(_jobj);
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
index 39276b9..02eabba 100644
--- a/backends/platform/android/jni.h
+++ b/backends/platform/android/jni.h
@@ -30,11 +30,16 @@
 
 #include <jni.h>
 
-extern jobject back_ptr;
+#include "common/fs.h"
+#include "common/archive.h"
 
 class OSystem_Android;
 
 class JNI {
+private:
+	JNI();
+	virtual ~JNI();
+
 public:
 	static jint onLoad(JavaVM *vm);
 
@@ -43,14 +48,24 @@ public:
 	static void attachThread();
 	static void detachThread();
 
-private:
-	JNI();
-	virtual ~JNI();
+	static int getAudioSampleRate();
+	static void initBackend();
+	static void getPluginDirectories(Common::FSList &dirs);
+	static void setWindowCaption(const char *caption);
+	static void displayMessageOnOSD(const char *msg);
+	static void showVirtualKeyboard(bool enable);
+	static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
+
+	static inline bool setupSurface();
+	static inline void destroySurface();
+	static inline bool swapBuffers();
 
 private:
 	static JavaVM *_vm;
 	// back pointer to (java) peer instance
 	static jobject _jobj;
+
+	static Common::Archive *_asset_archive;
 	static OSystem_Android *_system;
 
 	static jfieldID _FID_Event_type;
@@ -63,6 +78,17 @@ private:
 	static jfieldID _FID_Event_mouse_relative;
 	static jfieldID _FID_ScummVM_nativeScummVM;
 
+	static jmethodID _MID_displayMessageOnOSD;
+	static jmethodID _MID_setWindowCaption;
+	static jmethodID _MID_initBackend;
+	static jmethodID _MID_audioSampleRate;
+	static jmethodID _MID_showVirtualKeyboard;
+	static jmethodID _MID_getSysArchives;
+	static jmethodID _MID_getPluginDirectories;
+	static jmethodID _MID_setupScummVMSurface;
+	static jmethodID _MID_destroyScummVMSurface;
+	static jmethodID _MID_swapBuffers;
+
 	static const JNINativeMethod _natives[];
 
 	static void throwByName(JNIEnv *env, const char *name, const char *msg);
@@ -82,6 +108,26 @@ private:
 								jint height);
 };
 
+inline bool JNI::setupSurface() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj, _MID_setupScummVMSurface);
+
+	return !env->ExceptionCheck();
+}
+
+inline void JNI::destroySurface() {
+	JNIEnv *env = JNI::getEnv();
+
+	env->CallVoidMethod(_jobj, _MID_destroyScummVMSurface);
+}
+
+inline bool JNI::swapBuffers() {
+	JNIEnv *env = JNI::getEnv();
+
+	return env->CallBooleanMethod(_jobj, _MID_swapBuffers);
+}
+
 #endif
 #endif
 


Commit: 0e9b4f3c506d64b0dfd931ac510ed773789f272e
    https://github.com/scummvm/scummvm/commit/0e9b4f3c506d64b0dfd931ac510ed773789f272e
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:32-08:00

Commit Message:
ANDROID: We are not a text editor

This was probably set to ensure onCreateInputConnection() gets called,
but it is regardless of this flag. Now the soft keyboard doesn't show
up on startup on devices without physical keyboard, which prevents
unnecessary surface changes.

Changed paths:
    backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java



diff --git a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
index 5b71d4a..1a0972d 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
@@ -25,7 +25,7 @@ public class EditableSurfaceView extends SurfaceView {
 
 	@Override
 	public boolean onCheckIsTextEditor() {
-		return true;
+		return false;
 	}
 
 	private class MyInputConnection extends BaseInputConnection {


Commit: 50a682e7e1c69082735a07b2261d1c0c61ac12c9
    https://github.com/scummvm/scummvm/commit/50a682e7e1c69082735a07b2261d1c0c61ac12c9
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:33-08:00

Commit Message:
GUI: Make the ThemeParser less dumb

Instead of running into assert()s due to dumb parser decisions, use
'less than' and 'greater than' width/height conditions on the
'resolution' tags.
Seems better than listing >9000 different android resolutions.

Changed paths:
    gui/ThemeParser.cpp
    gui/themes/default.inc
    gui/themes/scummclassic.zip
    gui/themes/scummclassic/classic_gfx.stx
    gui/themes/scummclassic/classic_layout.stx
    gui/themes/scummclassic/classic_layout_lowres.stx
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/scummmodern_gfx.stx
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx



diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index 70d81a9..e3523d1 100644
--- a/gui/ThemeParser.cpp
+++ b/gui/ThemeParser.cpp
@@ -861,30 +861,50 @@ bool ThemeParser::resolutionCheck(const Common::String &resolution) {
 		return true;
 
 	Common::StringTokenizer globTokenizer(resolution, ", ");
-	Common::String cur, w, h;
-	bool definedRes = false;
+	Common::String cur;
 
 	while (!globTokenizer.empty()) {
-		bool ignore = false;
 		cur = globTokenizer.nextToken();
 
-		if (cur[0] == '-') {
-			ignore = true;
-			cur.deleteChar(0);
+		bool lt;
+		int val;
+
+		if (cur.size() < 5) {
+			warning("Invalid theme 'resolution' token '%s'", resolution.c_str());
+			return false;
+		}
+
+		if (cur[0] == 'x') {
+			val = g_system->getOverlayWidth();
+		} else if (cur[0] == 'y') {
+			val = g_system->getOverlayHeight();
+		} else {
+			warning("Error parsing theme 'resolution' token '%s'", resolution.c_str());
+			return false;
+		}
+
+		if (cur[1] == '<') {
+			lt = true;
+		} else if (cur[1] == '>') {
+			lt = false;
 		} else {
-			definedRes = true;
+			warning("Error parsing theme 'resolution' token '%s'", resolution.c_str());
+			return false;
 		}
 
-		Common::StringTokenizer resTokenizer(cur, "x");
-		w = resTokenizer.nextToken();
-		h = resTokenizer.nextToken();
+		int token = atoi(cur.c_str() + 2);
 
-		if ((w == "X" || atoi(w.c_str()) == g_system->getOverlayWidth()) &&
-			(h == "Y" || atoi(h.c_str()) == g_system->getOverlayHeight()))
-			return !ignore;
+		// check inverse for unfulfilled requirements
+		if (lt) {
+			if (val >= token)
+				return false;
+		} else {
+			if (val <= token)
+				return false;
+		}
 	}
 
-	return !definedRes;
+	return true;
 }
 
 } // End of namespace GUI
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 3236071..62a796a 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1,614 +1,688 @@
  "<?xml version = '1.0'?>"
-"<layout_info resolution='-320xY,-256x240,-Xx272,-544x332,-Xx350'> "
-"<globals> "
-"<def var='Line.Height' value='16' /> "
-"<def var='Font.Height' value='16' /> "
-"<def var='About.OuterBorder' value='80'/> "
-"<def var='Layout.Spacing' value='8' /> "
-"<def var='ShowLauncherLogo' value='0'/> "
-"<def var='ShowGlobalMenuLogo' value='0'/> "
-"<def var='ShowSearchPic' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
-"<def var='KeyMapper.Spacing' value='10'/> "
-"<def var='KeyMapper.LabelWidth' value='100'/> "
-"<def var='KeyMapper.ButtonWidth' value='80'/> "
-"<def var='Tooltip.MaxWidth' value='200'/> "
-"<def var='Tooltip.XDelta' value='16'/> "
-"<def var='Tooltip.YDelta' value='16'/> "
-"<widget name='OptionsLabel' "
-"size='110,Globals.Line.Height' "
-"textalign='right' "
-"/> "
-"<widget name='SmallLabel' "
-"size='24,Globals.Line.Height' "
+"<render_info> "
+"<palette> "
+"<color name='black' "
+"rgb='0,0,0' "
 "/> "
-"<widget name='ShortOptionsLabel' "
-"size='60,Globals.Line.Height' "
+"<color name='lightgrey' "
+"rgb='104,104,104' "
 "/> "
-"<widget name='Button' "
-"size='108,24' "
+"<color name='darkgrey' "
+"rgb='64,64,64' "
 "/> "
-"<widget name='Slider' "
-"size='128,18' "
+"<color name='green' "
+"rgb='32,160,32' "
 "/> "
-"<widget name='PopUp' "
-"size='-1,19' "
+"<color name='green2' "
+"rgb='0,255,0' "
 "/> "
-"<widget name='Checkbox' "
-"size='-1,14' "
+"</palette> "
+"<fonts> "
+"<font id='text_default' "
+"file='helvb12.bdf' "
 "/> "
-"<widget name='Radiobutton' "
-"size='-1,Globals.Line.Height' "
+"<font resolution='y<400' "
+"id='text_default' "
+"file='clR6x12.bdf' "
 "/> "
-"<widget name='ListWidget' "
-"padding='5,0,8,0' "
+"<font id='text_button' "
+"file='helvb12.bdf' "
 "/> "
-"<widget name='PopUpWidget' "
-"padding='7,5,0,0' "
+"<font resolution='y<400' "
+"id='text_button' "
+"file='clR6x12.bdf' "
 "/> "
-"<widget name='EditTextWidget' "
-"padding='5,5,0,0' "
+"<font id='text_normal' "
+"file='helvb12.bdf' "
 "/> "
-"<widget name='Console' "
-"padding='7,5,5,5' "
+"<font resolution='y<400' "
+"id='text_normal' "
+"file='clR6x12.bdf' "
 "/> "
-"<widget name='Scrollbar' "
-"size='15,0' "
+"<font id='tooltip_normal' "
+"file='fixed5x8.bdf' "
 "/> "
-"<widget name='TabWidget.Tab' "
-"size='75,27' "
-"padding='0,0,8,0' "
+"<text_color id='color_normal' "
+"color='green' "
 "/> "
-"<widget name='TabWidget.Body' "
-"padding='0,0,0,0' "
+"<text_color id='color_normal_inverted' "
+"color='black' "
 "/> "
-"<widget name='TabWidget.NavButton' "
-"size='15,18' "
-"padding='0,3,4,0' "
+"<text_color id='color_normal_hover' "
+"color='green2' "
 "/> "
-"</globals> "
-"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='16,16,8,8'> "
-"<widget name='Version' "
-"height='Globals.Line.Height' "
+"<text_color id='color_normal_disabled' "
+"color='lightgrey' "
 "/> "
-"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
-"<widget name='SearchDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"<text_color id='color_alternative' "
+"color='lightgrey' "
 "/> "
-"<widget name='Search' "
-"width='150' "
-"height='Globals.Line.Height' "
+"<text_color id='color_alternative_inverted' "
+"color='255,255,255' "
 "/> "
-"<widget name='SearchClearButton' "
-"height='Globals.Line.Height' "
-"width='Globals.Line.Height' "
+"<text_color id='color_alternative_hover' "
+"color='176,176,176' "
 "/> "
-"<space /> "
-"</layout> "
-"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='LoadGameButton' "
-"height='20' "
+"<text_color id='color_alternative_disabled' "
+"color='darkgrey' "
 "/> "
-"<widget name='AddGameButton' "
-"height='20' "
+"<text_color id='color_button' "
+"color='green' "
 "/> "
-"<widget name='EditGameButton' "
-"height='20' "
+"<text_color id='color_button_hover' "
+"color='green2' "
 "/> "
-"<widget name='RemoveGameButton' "
-"height='20' "
+"<text_color id='color_button_disabled' "
+"color='lightgrey' "
 "/> "
-"</layout> "
-"<space size='4'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='QuitButton' "
-"height='20' "
+"</fonts> "
+"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> "
+"<drawdata id='text_selection' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='lightgrey' "
 "/> "
-"<widget name='AboutButton' "
-"height='20' "
+"</drawdata> "
+"<drawdata id='text_selection_focus' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
 "/> "
-"<widget name='OptionsButton' "
-"height='20' "
+"</drawdata> "
+"<drawdata id='mainmenu_bg' cache='false'> "
+"<drawstep func='fill' "
+"fill='foreground' "
+"fg_color='black' "
 "/> "
-"<widget name='StartButton' "
-"height='20' "
+"</drawdata> "
+"<drawdata id='special_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<widget name='Headline' "
-"height='Globals.Line.Height' "
+"</drawdata> "
+"<drawdata id='tooltip_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='foreground' "
+"fg_color='black' "
 "/> "
-"<widget name='Path' "
-"height='Globals.Line.Height' "
+"</drawdata> "
+"<drawdata id='separator' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"height='2' "
+"ypos='center' "
+"fg_color='lightgrey' "
 "/> "
-"<widget name='List'/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
-"<widget name='Up' "
-"type='Button' "
+"</drawdata> "
+"<drawdata id='scrollbar_base' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
 "/> "
-"<space/> "
-"<widget name='Cancel' "
-"type='Button' "
+"</drawdata> "
+"<drawdata id='scrollbar_handle_hover' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green2' "
 "/> "
-"<widget name='Choose' "
-"type='Button' "
+"</drawdata> "
+"<drawdata id='scrollbar_handle_idle' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='0,0,0,0'> "
-"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
-"<space/> "
-"<widget name='Cancel' "
-"type='Button' "
+"</drawdata> "
+"<drawdata id='scrollbar_button_idle' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='Ok' "
-"type='Button' "
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='auto' "
+"height='auto' "
+"xpos='center' "
+"ypos='center' "
+"orientation='top' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='grModePopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='scrollbar_button_hover' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='grModePopup' "
-"type='PopUp' "
+"<drawstep func='triangle' "
+"fg_color='green2' "
+"fill='foreground' "
+"width='auto' "
+"height='auto' "
+"xpos='center' "
+"ypos='center' "
+"orientation='top' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='grRenderPopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='tab_active' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal_hover' "
+"vertical_align='center' "
+"horizontal_align='center' "
 "/> "
-"<widget name='grRenderPopup' "
-"type='PopUp' "
+"<drawstep func='tab' "
+"bevel='2' "
+"radius='0' "
+"fill='none' "
 "/> "
-"</layout> "
-"<widget name='grAspectCheckbox' "
-"type='Checkbox' "
+"</drawdata> "
+"<drawdata id='tab_inactive' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='center' "
 "/> "
-"<widget name='grFullscreenCheckbox' "
-"type='Checkbox' "
+"<drawstep func='tab' "
+"bevel='2' "
+"radius='0' "
+"fill='none' "
 "/> "
-"<widget name='grDisableDitheringCheckbox' "
-"type='Checkbox' "
+"</drawdata> "
+"<drawdata id='tab_background' cache='false'> "
+"</drawdata> "
+"<drawdata id='widget_slider' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='auMidiPopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='slider_disabled' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='lightgrey' "
 "/> "
-"<widget name='auMidiPopup' "
-"type='PopUp' "
+"</drawdata> "
+"<drawdata id='slider_full' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='auOPLPopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='slider_hover' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green2' "
 "/> "
-"<widget name='auOPLPopup' "
-"type='PopUp' "
+"</drawdata> "
+"<drawdata id='widget_small' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='auSampleRatePopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='popup_idle' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='auSampleRatePopup' "
-"type='PopUp' "
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='height' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"orientation='bottom' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='subToggleDesc' "
-"type='OptionsLabel' "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='left' "
 "/> "
-"<widget name='subToggleSpeechOnly' "
-"type='Radiobutton' "
+"</drawdata> "
+"<drawdata id='popup_disabled' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='subToggleSubOnly' "
-"type='Radiobutton' "
+"<drawstep func='triangle' "
+"fg_color='lightgrey' "
+"fill='foreground' "
+"width='height' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"orientation='bottom' "
 "/> "
-"<widget name='subToggleSubBoth' "
-"type='Radiobutton' "
+"<text font='text_default' "
+"text_color='color_normal_disabled' "
+"vertical_align='center' "
+"horizontal_align='left' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='subSubtitleSpeedDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='popup_hover' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='subSubtitleSpeedSlider' "
-"type='Slider' "
+"<drawstep func='triangle' "
+"fg_color='green2' "
+"fill='foreground' "
+"width='height' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"orientation='bottom' "
 "/> "
-"<widget name='subSubtitleSpeedLabel' "
-"type='SmallLabel' "
+"<text font='text_default' "
+"text_color='color_normal_hover' "
+"vertical_align='center' "
+"horizontal_align='left' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='vcMusicText' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='widget_textedit' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='vcMusicSlider' "
-"type='Slider' "
+"</drawdata> "
+"<drawdata id='plain_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
 "/> "
-"<widget name='vcMusicLabel' "
-"type='SmallLabel' "
+"</drawdata> "
+"<drawdata id='caret' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='lightgrey' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='vcSfxText' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='default_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
 "/> "
-"<widget name='vcSfxSlider' "
-"type='Slider' "
+"</drawdata> "
+"<drawdata id='button_idle' cache='false'> "
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
 "/> "
-"<widget name='vcSfxLabel' "
-"type='SmallLabel' "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='vcSpeechText' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='button_hover' cache='false'> "
+"<text font='text_button' "
+"text_color='color_button_hover' "
+"vertical_align='center' "
+"horizontal_align='center' "
 "/> "
-"<widget name='vcSpeechSlider' "
-"type='Slider' "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='vcSpeechLabel' "
-"type='SmallLabel' "
+"</drawdata> "
+"<drawdata id='button_disabled' cache='false'> "
+"<text font='text_button' "
+"text_color='color_button_disabled' "
+"vertical_align='center' "
+"horizontal_align='center' "
 "/> "
-"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,0,24,0' center='true'> "
-"<widget name='vcMuteCheckbox' "
-"type='Checkbox' "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='auPrefGmPopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='checkbox_disabled' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal_disabled' "
+"vertical_align='top' "
+"horizontal_align='left' "
 "/> "
-"<widget name='auPrefGmPopup' "
-"type='PopUp' "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='mcFontButton' "
-"type='Button' "
+"</drawdata> "
+"<drawdata id='checkbox_selected' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='top' "
+"horizontal_align='left' "
 "/> "
-"<widget name='mcFontPath' "
-"height='Globals.Line.Height' "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='mcFontClearButton' "
-"height='Globals.Line.Height' "
-"width='Globals.Line.Height' "
+"<drawstep func='cross' "
+"fill='foreground' "
+"stroke='2' "
+"fg_color='green' "
 "/> "
-"</layout> "
-"<widget name='mcMixedCheckbox' "
-"type='Checkbox' "
+"</drawdata> "
+"<drawdata id='checkbox_default' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='top' "
+"horizontal_align='left' "
 "/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='mcMidiGainText' "
-"type='OptionsLabel' "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
 "/> "
-"<widget name='mcMidiGainSlider' "
-"type='Slider' "
+"</drawdata> "
+"<drawdata id='radiobutton_default' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='left' "
 "/> "
-"<widget name='mcMidiGainLabel' "
-"width='32' "
-"height='Globals.Line.Height' "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='7' "
+"fill='background' "
+"bg_color='darkgrey' "
+"xpos='0' "
+"ypos='0' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='auPrefMt32PopupDesc' "
-"type='OptionsLabel' "
+"</drawdata> "
+"<drawdata id='radiobutton_selected' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='left' "
 "/> "
-"<widget name='auPrefMt32Popup' "
-"type='PopUp' "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='7' "
+"fg_color='darkgrey' "
+"fill='none' "
+"xpos='0' "
+"ypos='0' "
 "/> "
-"</layout> "
-"<widget name='mcMt32Checkbox' "
-"type='Checkbox' "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='5' "
+"fg_color='green' "
+"fill='foreground' "
+"xpos='2' "
+"ypos='2' "
 "/> "
-"<widget name='mcGSCheckbox' "
-"type='Checkbox' "
+"</drawdata> "
+"<drawdata id='radiobutton_disabled' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal_disabled' "
+"vertical_align='center' "
+"horizontal_align='left' "
 "/> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='SaveButton' "
-"type='Button' "
+"<drawstep func='circle' "
+"width='7' "
+"height='7' "
+"radius='7' "
+"bg_color='lightgrey' "
+"fill='background' "
+"xpos='0' "
+"ypos='0' "
 "/> "
-"<widget name='SavePath' "
-"height='Globals.Line.Height' "
+"</drawdata> "
+"<drawdata id='widget_default' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='ThemeButton' "
-"type='Button' "
+"</drawdata> "
+"<drawdata id='widget_small' cache='false'> "
+"<drawstep func='square' "
+"stroke='0' "
 "/> "
-"<widget name='ThemePath' "
-"height='Globals.Line.Height' "
+"</drawdata> "
+"</render_info> "
+"<layout_info resolution='y>399'> "
+"<globals> "
+"<def var='Line.Height' value='16' /> "
+"<def var='Font.Height' value='16' /> "
+"<def var='About.OuterBorder' value='80'/> "
+"<def var='Layout.Spacing' value='8' /> "
+"<def var='ShowLauncherLogo' value='0'/> "
+"<def var='ShowGlobalMenuLogo' value='0'/> "
+"<def var='ShowSearchPic' value='0'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
+"<def var='KeyMapper.Spacing' value='10'/> "
+"<def var='KeyMapper.LabelWidth' value='100'/> "
+"<def var='KeyMapper.ButtonWidth' value='80'/> "
+"<def var='Tooltip.MaxWidth' value='200'/> "
+"<def var='Tooltip.XDelta' value='16'/> "
+"<def var='Tooltip.YDelta' value='16'/> "
+"<widget name='OptionsLabel' "
+"size='110,Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='ExtraButton' "
-"type='Button' "
+"<widget name='SmallLabel' "
+"size='24,Globals.Line.Height' "
 "/> "
-"<widget name='ExtraPath' "
-"height='Globals.Line.Height' "
+"<widget name='ShortOptionsLabel' "
+"size='60,Globals.Line.Height' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
-"<widget name='PluginsButton' "
-"type='Button' "
+"<widget name='Button' "
+"size='108,24' "
 "/> "
-"<widget name='PluginsPath' "
-"height='Globals.Line.Height' "
+"<widget name='Slider' "
+"size='128,18' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='ThemeButton' "
-"type='Button' "
+"<widget name='PopUp' "
+"size='-1,19' "
 "/> "
-"<widget name='CurTheme' "
-"height='Globals.Line.Height' "
+"<widget name='Checkbox' "
+"size='-1,14' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='RendererPopupDesc' "
-"type='OptionsLabel' "
+"<widget name='Radiobutton' "
+"size='-1,Globals.Line.Height' "
 "/> "
-"<widget name='RendererPopup' "
-"type='PopUp' "
+"<widget name='ListWidget' "
+"padding='5,0,8,0' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='AutosavePeriodPopupDesc' "
-"type='OptionsLabel' "
+"<widget name='PopUpWidget' "
+"padding='7,5,0,0' "
 "/> "
-"<widget name='AutosavePeriodPopup' "
-"type='PopUp' "
+"<widget name='EditTextWidget' "
+"padding='5,5,0,0' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='GuiLanguagePopupDesc' "
-"type='OptionsLabel' "
+"<widget name='Console' "
+"padding='7,5,5,5' "
 "/> "
-"<widget name='GuiLanguagePopup' "
-"type='PopUp' "
+"<widget name='Scrollbar' "
+"size='15,0' "
 "/> "
-"</layout> "
-"<widget name='KeysButton' "
-"type='Button' "
+"<widget name='TabWidget.Tab' "
+"size='75,27' "
+"padding='0,0,8,0' "
 "/> "
-"</layout> "
-"</dialog> "
-"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Action' "
-"height='Globals.Line.Height' "
+"<widget name='TabWidget.Body' "
+"padding='0,0,0,0' "
 "/> "
-"<widget name='List'/> "
-"<widget name='Mapping' "
+"<widget name='TabWidget.NavButton' "
+"size='15,18' "
+"padding='0,3,4,0' "
+"/> "
+"</globals> "
+"<dialog name='Launcher' overlays='screen'> "
+"<layout type='vertical' center='true' padding='16,16,8,8'> "
+"<widget name='Version' "
 "height='Globals.Line.Height' "
 "/> "
-"<space size='Globals.Line.Height'/> "
-"<layout type='horizontal'> "
-"<widget name='Map' "
-"type='Button' "
+"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
+"<widget name='SearchDesc' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"<space/> "
-"<widget name='Cancel' "
-"type='Button' "
+"<widget name='Search' "
+"width='150' "
+"height='Globals.Line.Height' "
 "/> "
-"<widget name='Ok' "
-"type='Button' "
+"<widget name='SearchClearButton' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
 "/> "
+"<space /> "
 "</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
-"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,4'> "
-"<space/> "
-"<widget name='Cancel' "
-"type='Button' "
+"<widget name='GameList'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='LoadGameButton' "
+"height='20' "
 "/> "
-"<widget name='Ok' "
-"type='Button' "
+"<widget name='AddGameButton' "
+"height='20' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<widget name='EditGameButton' "
+"height='20' "
 "/> "
-"<import layout='Dialog.GlobalOptions_Graphics' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<widget name='RemoveGameButton' "
+"height='20' "
 "/> "
-"<import layout='Dialog.GlobalOptions_Audio' /> "
 "</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<space size='4'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='QuitButton' "
+"height='20' "
 "/> "
-"<import layout='Dialog.GlobalOptions_MIDI' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<widget name='AboutButton' "
+"height='20' "
 "/> "
-"<import layout='Dialog.GlobalOptions_MT32' /> "
+"<widget name='OptionsButton' "
+"height='20' "
+"/> "
+"<widget name='StartButton' "
+"height='20' "
+"/> "
+"</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='Headline' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='Path' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='List'/> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Up' "
+"type='Button' "
+"/> "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='Choose' "
+"type='Button' "
 "/> "
-"<import layout='Dialog.GlobalOptions_Volume' /> "
+"</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='Id' "
-"type='OptionsLabel' "
+"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='0,0,0,0'> "
+"<widget name='TabWidget'/> "
+"<layout type='horizontal' padding='16,16,16,16'> "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"<widget name='Domain' "
-"type='PopUp' "
+"<widget name='Ok' "
+"type='Button' "
 "/> "
 "</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='Name' "
+"<widget name='grModePopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='Desc' "
+"<widget name='grModePopup' "
 "type='PopUp' "
 "/> "
 "</layout> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='LangPopupDesc' "
+"<widget name='grRenderPopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='LangPopup' "
+"<widget name='grRenderPopup' "
 "type='PopUp' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='PlatformPopupDesc' "
-"type='OptionsLabel' "
+"<widget name='grAspectCheckbox' "
+"type='Checkbox' "
 "/> "
-"<widget name='PlatformPopup' "
-"type='PopUp' "
+"<widget name='grFullscreenCheckbox' "
+"type='Checkbox' "
+"/> "
+"<widget name='grDisableDitheringCheckbox' "
+"type='Checkbox' "
 "/> "
-"</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
+"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='Savepath' "
-"type='Button' "
+"<widget name='auMidiPopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='SavepathText' "
-"height='Globals.Line.Height' "
+"<widget name='auMidiPopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='Extrapath' "
-"type='Button' "
+"<widget name='auOPLPopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='ExtrapathText' "
-"height='Globals.Line.Height' "
+"<widget name='auOPLPopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='Gamepath' "
-"type='Button' "
+"<widget name='auSampleRatePopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='GamepathText' "
-"height='Globals.Line.Height' "
+"<widget name='auSampleRatePopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='16,16,16,16' center='true'> "
-"<widget name='Title' "
-"width='210' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Version' "
-"width='210' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Resume' "
-"width='150' "
-"height='Globals.Button.Height' "
-"/> "
-"<space size='10'/> "
-"<widget name='Load' "
-"width='150' "
-"height='Globals.Button.Height' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='subToggleDesc' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='Save' "
-"width='150' "
-"height='Globals.Button.Height' "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
 "/> "
-"<space size='10'/> "
-"<widget name='Options' "
-"width='150' "
-"height='Globals.Button.Height' "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
 "/> "
-"<widget name='Help' "
-"width='150' "
-"height='Globals.Button.Height' "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
 "/> "
-"<widget name='About' "
-"width='150' "
-"height='Globals.Button.Height' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='subSubtitleSpeedDesc' "
+"type='OptionsLabel' "
 "/> "
-"<space size='10'/> "
-"<widget name='RTL' "
-"width='150' "
-"height='Globals.Button.Height' "
+"<widget name='subSubtitleSpeedSlider' "
+"type='Slider' "
 "/> "
-"<widget name='Quit' "
-"width='150' "
-"height='Globals.Button.Height' "
+"<widget name='subSubtitleSpeedLabel' "
+"type='SmallLabel' "
 "/> "
 "</layout> "
+"</layout> "
 "</dialog> "
-"<dialog name='GlobalConfig' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
 "<layout type='horizontal' padding='0,0,0,0'> "
-"<layout type='vertical' padding='0,0,0,0' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
 "<widget name='vcMusicText' "
 "type='OptionsLabel' "
 "/> "
@@ -619,7 +693,7 @@
 "type='SmallLabel' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
 "<widget name='vcSfxText' "
 "type='OptionsLabel' "
 "/> "
@@ -630,7 +704,7 @@
 "type='SmallLabel' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
 "<widget name='vcSpeechText' "
 "type='OptionsLabel' "
 "/> "
@@ -642,392 +716,339 @@
 "/> "
 "</layout> "
 "</layout> "
-"<layout type='vertical' padding='24,24,24,24' center='true'> "
+"<layout type='vertical' padding='24,0,24,0' center='true'> "
 "<widget name='vcMuteCheckbox' "
 "type='Checkbox' "
-"width='80'  "
 "/> "
 "</layout> "
 "</layout> "
-"<space size='8' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='subToggleDesc' "
+"</dialog> "
+"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='auPrefGmPopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='subToggleSpeechOnly' "
-"type='Radiobutton' "
-"width='100' "
-"/> "
-"<widget name='subToggleSubOnly' "
-"type='Radiobutton' "
-"width='100' "
-"/> "
-"<widget name='subToggleSubBoth' "
-"type='Radiobutton' "
-"width='100' "
+"<widget name='auPrefGmPopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='subSubtitleSpeedDesc' "
-"type='OptionsLabel' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='mcFontButton' "
+"type='Button' "
 "/> "
-"<widget name='subSubtitleSpeedSlider' "
-"type='Slider' "
+"<widget name='mcFontPath' "
+"height='Globals.Line.Height' "
 "/> "
-"<widget name='subSubtitleSpeedLabel' "
-"type='SmallLabel' "
+"<widget name='mcFontClearButton' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
 "/> "
 "</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
-"<widget name='Keys' "
-"type='Button' "
+"<widget name='mcMixedCheckbox' "
+"type='Checkbox' "
 "/> "
-"<space size='Globals.Button.Width' /> "
-"<widget name='Cancel' "
-"type='Button' "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='mcMidiGainText' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='Ok' "
-"type='Button' "
+"<widget name='mcMidiGainSlider' "
+"type='Slider' "
+"/> "
+"<widget name='mcMidiGainLabel' "
+"width='32' "
+"height='Globals.Line.Height' "
 "/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,32' center='true'> "
-"<widget name='Title' "
-"height='Globals.Line.Height' "
+"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='auPrefMt32PopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
-"<widget name='List' /> "
-"<widget name='Thumbnail' "
-"width='180' "
-"height='200' "
+"<widget name='auPrefMt32Popup' "
+"type='PopUp' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<space/> "
-"<widget name='Delete' "
+"<widget name='mcMt32Checkbox' "
+"type='Checkbox' "
+"/> "
+"<widget name='mcGSCheckbox' "
+"type='Checkbox' "
+"/> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='SaveButton' "
 "type='Button' "
 "/> "
-"<space size='32'/> "
-"<widget name='Cancel' "
+"<widget name='SavePath' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='ThemeButton' "
 "type='Button' "
 "/> "
-"<widget name='Choose' "
+"<widget name='ThemePath' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='ExtraButton' "
+"type='Button' "
+"/> "
+"<widget name='ExtraPath' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<widget name='PluginsButton' "
 "type='Button' "
 "/> "
+"<widget name='PluginsPath' "
+"height='Globals.Line.Height' "
+"/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='ScummHelp' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Title' "
-"width='320' "
+"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='ThemeButton' "
+"type='Button' "
+"/> "
+"<widget name='CurTheme' "
 "height='Globals.Line.Height' "
 "/> "
-"<widget name='HelpText' "
-"height='200' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='RendererPopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
-"<widget name='Prev' "
-"type='Button' "
+"<widget name='RendererPopup' "
+"type='PopUp' "
 "/> "
-"<widget name='Next' "
-"type='Button' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='AutosavePeriodPopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<space size='32'/> "
-"<widget name='Close' "
-"type='Button' "
+"<widget name='AutosavePeriodPopup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='GuiLanguagePopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='GuiLanguagePopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
+"<widget name='KeysButton' "
+"type='Button' "
+"/> "
 "</layout> "
 "</dialog> "
-"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' center='true'> "
-"<widget name='DirProgressText' "
-"width='480' "
+"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Action' "
 "height='Globals.Line.Height' "
 "/> "
-"<widget name='GameProgressText' "
-"width='480' "
+"<widget name='List'/> "
+"<widget name='Mapping' "
 "height='Globals.Line.Height' "
 "/> "
-"<widget name='GameList' "
-"width='480' "
-"height='250' "
+"<space size='Globals.Line.Height'/> "
+"<layout type='horizontal'> "
+"<widget name='Map' "
+"type='Button' "
+"/> "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
 "<widget name='Ok' "
 "type='Button' "
 "/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
+"<widget name='TabWidget'/> "
+"<layout type='horizontal' padding='16,16,16,4'> "
+"<space/> "
 "<widget name='Cancel' "
 "type='Button' "
 "/> "
+"<widget name='Ok' "
+"type='Button' "
+"/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='PopupDesc' "
-"type='OptionsLabel' "
-"/> "
-"<widget name='Popup' "
-"type='PopUp' "
-"width='400' "
-"height='Globals.Line.Height' "
+"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
+"<import layout='Dialog.GlobalOptions_Graphics' /> "
 "</layout> "
-"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
+"</dialog> "
+"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"<widget name='Close' "
-"type='Button' "
+"<import layout='Dialog.GlobalOptions_Audio' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
+"<import layout='Dialog.GlobalOptions_MIDI' /> "
 "</layout> "
 "</dialog> "
-"</layout_info> "
-"<layout_info resolution='320xY,256x240,Xx272,544x332,Xx350'> "
-"<globals> "
-"<def var='Line.Height' value='12' /> "
-"<def var='Font.Height' value='10' /> "
-"<def var='About.OuterBorder' value='10'/> "
-"<def var='Layout.Spacing' value='8'/> "
-"<def var='ShowLauncherLogo' value='0'/> "
-"<def var='ShowGlobalMenuLogo' value='0'/> "
-"<def var='ShowSearchPic' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
-"<def var='KeyMapper.Spacing' value='5'/> "
-"<def var='KeyMapper.LabelWidth' value='80'/> "
-"<def var='KeyMapper.ButtonWidth' value='60'/> "
-"<def var='Tooltip.MaxWidth' value='70'/> "
-"<def var='Tooltip.XDelta' value='8'/> "
-"<def var='Tooltip.YDelta' value='8'/> "
-"<widget name='Button' "
-"size='72,16' "
+"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"<widget name='Slider' "
-"size='85,12' "
+"<import layout='Dialog.GlobalOptions_MT32' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"<widget name='OptionsLabel' "
-"size='110,Globals.Line.Height' "
-"textalign='right' "
+"<import layout='Dialog.GlobalOptions_Volume' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='Id' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='SmallLabel' "
-"size='18,Globals.Line.Height' "
+"<widget name='Domain' "
+"type='PopUp' "
 "/> "
-"<widget name='PopUp' "
-"size='-1,15' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='Name' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='Checkbox' "
-"size='-1,Globals.Line.Height' "
+"<widget name='Desc' "
+"type='PopUp' "
 "/> "
-"<widget name='Radiobutton' "
-"size='-1,Globals.Line.Height' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='LangPopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='ListWidget' "
-"padding='5,0,0,0' "
-"/> "
-"<widget name='PopUpWidget' "
-"padding='7,5,0,0' "
-"/> "
-"<widget name='EditTextWidget' "
-"padding='5,5,0,0' "
-"/> "
-"<widget name='Console' "
-"padding='7,5,5,5' "
-"/> "
-"<widget name='Scrollbar' "
-"size='9,0' "
-"/> "
-"<widget name='TabWidget.Tab' "
-"size='45,16' "
-"padding='0,0,2,0' "
-"/> "
-"<widget name='TabWidget.Body' "
-"padding='0,0,0,-8' "
-"/> "
-"<widget name='TabWidget.NavButton' "
-"size='32,18' "
-"padding='0,0,1,0' "
-"/> "
-"</globals> "
-"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='6,6,2,2'> "
-"<widget name='Version' "
-"height='Globals.Line.Height' "
-"/> "
-"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
-"<widget name='SearchDesc' "
-"width='50' "
-"height='Globals.Line.Height' "
-"textalign='right' "
-"/> "
-"<widget name='Search' "
-"width='150' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='SearchClearButton' "
-"height='Globals.Line.Height' "
-"width='Globals.Line.Height' "
-"/> "
-"<space /> "
-"</layout> "
-"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
-"<widget name='LoadGameButton' "
-"height='12' "
-"/> "
-"<widget name='AddGameButton' "
-"height='12' "
-"/> "
-"<widget name='EditGameButton' "
-"height='12' "
-"/> "
-"<widget name='RemoveGameButton' "
-"height='12' "
+"<widget name='LangPopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
-"<widget name='QuitButton' "
-"height='12' "
-"/> "
-"<widget name='AboutButton' "
-"height='12' "
-"/> "
-"<widget name='OptionsButton' "
-"height='12' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='PlatformPopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='StartButton' "
-"height='12' "
+"<widget name='PlatformPopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,0,4'> "
-"<widget name='Headline' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Path' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='List'/> "
-"<layout type='horizontal' padding='0,0,8,0'> "
-"<widget name='Up' "
-"type='Button' "
-"/> "
-"<space/> "
-"<widget name='Cancel' "
+"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='Savepath' "
 "type='Button' "
 "/> "
-"<widget name='Choose' "
-"type='Button' "
+"<widget name='SavepathText' "
+"height='Globals.Line.Height' "
 "/> "
 "</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
-"<layout type='vertical' padding='0,0,0,0'> "
-"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
-"<space/> "
-"<widget name='Cancel' "
-"type='Button' "
-"/> "
-"<widget name='Ok' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='Extrapath' "
 "type='Button' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='grModePopupDesc' "
-"type='OptionsLabel' "
-"/> "
-"<widget name='grModePopup' "
-"type='PopUp' "
+"<widget name='ExtrapathText' "
+"height='Globals.Line.Height' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='grRenderPopupDesc' "
-"type='OptionsLabel' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='Gamepath' "
+"type='Button' "
 "/> "
-"<widget name='grRenderPopup' "
-"type='PopUp' "
+"<widget name='GamepathText' "
+"height='Globals.Line.Height' "
 "/> "
 "</layout> "
-"<widget name='grAspectCheckbox' "
-"type='Checkbox' "
-"/> "
-"<widget name='grFullscreenCheckbox' "
-"type='Checkbox' "
-"/> "
-"<widget name='grDisableDitheringCheckbox' "
-"type='Checkbox' "
-"/> "
 "</layout> "
 "</dialog> "
-"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='auMidiPopupDesc' "
-"type='OptionsLabel' "
-"/> "
-"<widget name='auMidiPopup' "
-"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='auOPLPopupDesc' "
-"type='OptionsLabel' "
-"/> "
-"<widget name='auOPLPopup' "
-"type='PopUp' "
+"<dialog name='GlobalMenu' overlays='screen_center'> "
+"<layout type='vertical' padding='16,16,16,16' center='true'> "
+"<widget name='Title' "
+"width='210' "
+"height='Globals.Line.Height' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='auSampleRatePopupDesc' "
-"type='OptionsLabel' "
+"<widget name='Version' "
+"width='210' "
+"height='Globals.Line.Height' "
 "/> "
-"<widget name='auSampleRatePopup' "
-"type='PopUp' "
+"<widget name='Resume' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
-"<widget name='subToggleDesc' "
-"type='OptionsLabel' "
+"<space size='10'/> "
+"<widget name='Load' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"<widget name='subToggleSpeechOnly' "
-"type='Radiobutton' "
+"<widget name='Save' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"<widget name='subToggleSubOnly' "
-"type='Radiobutton' "
+"<space size='10'/> "
+"<widget name='Options' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"<widget name='subToggleSubBoth' "
-"type='Radiobutton' "
+"<widget name='Help' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='subSubtitleSpeedDesc' "
-"type='OptionsLabel' "
+"<widget name='About' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"<widget name='subSubtitleSpeedSlider' "
-"type='Slider' "
+"<space size='10'/> "
+"<widget name='RTL' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
-"<widget name='subSubtitleSpeedLabel' "
-"type='SmallLabel' "
+"<widget name='Quit' "
+"width='150' "
+"height='Globals.Button.Height' "
 "/> "
 "</layout> "
-"</layout> "
 "</dialog> "
-"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<dialog name='GlobalConfig' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='0,0,0,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
 "<widget name='vcMusicText' "
 "type='OptionsLabel' "
 "/> "
@@ -1038,7 +1059,7 @@
 "type='SmallLabel' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
 "<widget name='vcSfxText' "
 "type='OptionsLabel' "
 "/> "
@@ -1049,7 +1070,7 @@
 "type='SmallLabel' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
 "<widget name='vcSpeechText' "
 "type='OptionsLabel' "
 "/> "
@@ -1060,412 +1081,377 @@
 "type='SmallLabel' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,24,24,24' center='true'> "
 "<widget name='vcMuteCheckbox' "
 "type='Checkbox' "
+"width='80'  "
 "/> "
 "</layout> "
 "</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='auPrefGmPopupDesc' "
+"<space size='8' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='subToggleDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='auPrefGmPopup' "
-"type='PopUp' "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
+"width='100' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
-"<widget name='mcFontButton' "
-"type='Button' "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
+"width='100' "
 "/> "
-"<widget name='mcFontPath' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='mcFontClearButton' "
-"height='Globals.Line.Height' "
-"width='Globals.Line.Height' "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
+"width='100' "
 "/> "
 "</layout> "
-"<widget name='mcMixedCheckbox' "
-"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='mcMidiGainText' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='subSubtitleSpeedDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='mcMidiGainSlider' "
+"<widget name='subSubtitleSpeedSlider' "
 "type='Slider' "
 "/> "
-"<widget name='mcMidiGainLabel' "
-"width='32' "
-"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='auPrefMt32PopupDesc' "
-"type='OptionsLabel' "
-"/> "
-"<widget name='auPrefMt32Popup' "
-"type='PopUp' "
-"/> "
-"</layout> "
-"<widget name='mcMt32Checkbox' "
-"type='Checkbox' "
-"/> "
-"<widget name='mcGSCheckbox' "
-"type='Checkbox' "
-"/> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
-"<widget name='SaveButton' "
-"type='Button' "
-"/> "
-"<widget name='SavePath' "
-"height='Globals.Line.Height' "
+"<widget name='subSubtitleSpeedLabel' "
+"type='SmallLabel' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
-"<widget name='ThemeButton' "
+"<space size='60'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<widget name='Keys' "
 "type='Button' "
 "/> "
-"<widget name='ThemePath' "
-"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
-"<widget name='ExtraButton' "
+"<space size='Globals.Button.Width' /> "
+"<widget name='Cancel' "
 "type='Button' "
 "/> "
-"<widget name='ExtraPath' "
-"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
-"<widget name='PluginsButton' "
+"<widget name='Ok' "
 "type='Button' "
 "/> "
-"<widget name='PluginsPath' "
-"height='Globals.Line.Height' "
-"/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
-"<widget name='ThemeButton' "
-"type='Button' "
-"/> "
-"<widget name='CurTheme' "
-"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='RendererPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
-"/> "
-"<widget name='RendererPopup' "
-"type='PopUp' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='AutosavePeriodPopupDesc' "
-"width='80' "
+"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
+"<widget name='Title' "
 "height='Globals.Line.Height' "
-"textalign='right' "
 "/> "
-"<widget name='AutosavePeriodPopup' "
-"type='PopUp' "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
+"<widget name='List' /> "
+"<widget name='Thumbnail' "
+"width='180' "
+"height='200' "
 "/> "
 "</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='GuiLanguagePopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<space/> "
+"<widget name='Delete' "
+"type='Button' "
 "/> "
-"<widget name='GuiLanguagePopup' "
-"type='PopUp' "
+"<space size='32'/> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"</layout> "
-"<widget name='KeysButton' "
+"<widget name='Choose' "
 "type='Button' "
 "/> "
 "</layout> "
+"</layout> "
 "</dialog> "
-"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'> "
+"<dialog name='ScummHelp' overlays='screen_center'> "
 "<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Action' "
+"<widget name='Title' "
+"width='320' "
 "height='Globals.Line.Height' "
 "/> "
-"<widget name='List'/> "
-"<widget name='Mapping' "
-"height='Globals.Line.Height' "
+"<widget name='HelpText' "
+"height='200' "
 "/> "
-"<space size='Globals.Line.Height'/> "
-"<layout type='horizontal'> "
-"<widget name='Map' "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Prev' "
 "type='Button' "
 "/> "
-"<space/> "
-"<widget name='Cancel' "
+"<widget name='Next' "
 "type='Button' "
 "/> "
-"<widget name='Ok' "
+"<space size='32'/> "
+"<widget name='Close' "
 "type='Button' "
 "/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
-"<widget name='TabWidget'/> "
+"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
+"<layout type='vertical' padding='8,8,32,8' center='true'> "
+"<widget name='DirProgressText' "
+"width='480' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='GameProgressText' "
+"width='480' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='GameList' "
+"width='480' "
+"height='250' "
+"/> "
 "<layout type='horizontal' padding='8,8,8,8'> "
-"<space/> "
-"<widget name='Cancel' "
+"<widget name='Ok' "
 "type='Button' "
 "/> "
-"<widget name='Ok' "
+"<widget name='Cancel' "
 "type='Button' "
 "/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
-"/> "
-"<import layout='Dialog.GlobalOptions_Graphics' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
+"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='PopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"<import layout='Dialog.GlobalOptions_Audio' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<widget name='Popup' "
+"type='PopUp' "
+"width='400' "
+"height='Globals.Line.Height' "
 "/> "
-"<import layout='Dialog.GlobalOptions_MIDI' /> "
 "</layout> "
-"</dialog> "
-"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<widget name='KeymapArea' "
+"width='600' "
+"height='280' "
 "/> "
-"<import layout='Dialog.GlobalOptions_MT32' /> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
-"<widget name='EnableTabCheckbox' "
-"type='Checkbox' "
+"<widget name='Close' "
+"type='Button' "
 "/> "
-"<import layout='Dialog.GlobalOptions_Volume' /> "
 "</layout> "
 "</dialog> "
-"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='Id' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"</layout_info> "
+"<layout_info resolution='y<400'> "
+"<globals> "
+"<def var='Line.Height' value='12' /> "
+"<def var='Font.Height' value='10' /> "
+"<def var='About.OuterBorder' value='10'/> "
+"<def var='Layout.Spacing' value='8'/> "
+"<def var='ShowLauncherLogo' value='0'/> "
+"<def var='ShowGlobalMenuLogo' value='0'/> "
+"<def var='ShowSearchPic' value='0'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
+"<def var='KeyMapper.Spacing' value='5'/> "
+"<def var='KeyMapper.LabelWidth' value='80'/> "
+"<def var='KeyMapper.ButtonWidth' value='60'/> "
+"<def var='Tooltip.MaxWidth' value='70'/> "
+"<def var='Tooltip.XDelta' value='8'/> "
+"<def var='Tooltip.YDelta' value='8'/> "
+"<widget name='Button' "
+"size='72,16' "
 "/> "
-"<widget name='Domain' "
-"type='PopUp' "
+"<widget name='Slider' "
+"size='85,12' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='Name' "
-"width='35' "
-"height='Globals.Line.Height' "
+"<widget name='OptionsLabel' "
+"size='110,Globals.Line.Height' "
 "textalign='right' "
 "/> "
-"<widget name='Desc' "
-"type='PopUp' "
+"<widget name='SmallLabel' "
+"size='18,Globals.Line.Height' "
 "/> "
-"</layout> "
-"<space size='8'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='LangPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"<widget name='PopUp' "
+"size='-1,15' "
 "/> "
-"<widget name='LangPopup' "
-"type='PopUp' "
+"<widget name='Checkbox' "
+"size='-1,Globals.Line.Height' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='PlatformPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"<widget name='Radiobutton' "
+"size='-1,Globals.Line.Height' "
 "/> "
-"<widget name='PlatformPopup' "
-"type='PopUp' "
+"<widget name='ListWidget' "
+"padding='5,0,0,0' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
-"<widget name='Savepath' "
-"type='Button' "
+"<widget name='PopUpWidget' "
+"padding='7,5,0,0' "
 "/> "
-"<widget name='SavepathText' "
-"height='Globals.Line.Height' "
+"<widget name='EditTextWidget' "
+"padding='5,5,0,0' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
-"<widget name='Extrapath' "
-"type='Button' "
+"<widget name='Console' "
+"padding='7,5,5,5' "
 "/> "
-"<widget name='ExtrapathText' "
-"height='Globals.Line.Height' "
+"<widget name='Scrollbar' "
+"size='9,0' "
 "/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
-"<widget name='Gamepath' "
-"type='Button' "
+"<widget name='TabWidget.Tab' "
+"size='45,16' "
+"padding='0,0,2,0' "
 "/> "
-"<widget name='GamepathText' "
-"height='Globals.Line.Height' "
+"<widget name='TabWidget.Body' "
+"padding='0,0,0,-8' "
 "/> "
-"</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
-"<widget name='Title' "
-"width='160' "
-"height='4' "
+"<widget name='TabWidget.NavButton' "
+"size='32,18' "
+"padding='0,0,1,0' "
 "/> "
+"</globals> "
+"<dialog name='Launcher' overlays='screen'> "
+"<layout type='vertical' center='true' padding='6,6,2,2'> "
 "<widget name='Version' "
-"width='160' "
-"height='4' "
+"height='Globals.Line.Height' "
 "/> "
-"<space size='1'/> "
-"<widget name='Load' "
-"width='120' "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
+"<widget name='SearchDesc' "
+"width='50' "
+"height='Globals.Line.Height' "
+"textalign='right' "
+"/> "
+"<widget name='Search' "
+"width='150' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='SearchClearButton' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
+"<space /> "
+"</layout> "
+"<widget name='GameList'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<widget name='LoadGameButton' "
 "height='12' "
 "/> "
-"<widget name='Save' "
-"width='120' "
+"<widget name='AddGameButton' "
 "height='12' "
 "/> "
-"<space size='1'/> "
-"<widget name='Options' "
-"width='120' "
+"<widget name='EditGameButton' "
 "height='12' "
 "/> "
-"<widget name='Help' "
-"width='120' "
+"<widget name='RemoveGameButton' "
 "height='12' "
 "/> "
-"<widget name='About' "
-"width='120' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<widget name='QuitButton' "
 "height='12' "
 "/> "
-"<space size='1'/> "
-"<widget name='Resume' "
-"width='120' "
+"<widget name='AboutButton' "
 "height='12' "
 "/> "
-"<widget name='RTL' "
-"width='120' "
+"<widget name='OptionsButton' "
 "height='12' "
 "/> "
-"<widget name='Quit' "
-"width='120' "
+"<widget name='StartButton' "
 "height='12' "
 "/> "
 "</layout> "
+"</layout> "
 "</dialog> "
-"<dialog name='GlobalConfig' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,0,4'> "
+"<widget name='Headline' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='Path' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='List'/> "
+"<layout type='horizontal' padding='0,0,8,0'> "
+"<widget name='Up' "
+"type='Button' "
+"/> "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='Choose' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
+"<layout type='vertical' padding='0,0,0,0'> "
+"<widget name='TabWidget'/> "
+"<layout type='horizontal' padding='8,8,8,8'> "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='Ok' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='vcMusicText' "
+"<widget name='grModePopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='vcMusicSlider' "
-"type='Slider' "
-"/> "
-"<widget name='vcMusicLabel' "
-"type='SmallLabel' "
+"<widget name='grModePopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='vcSfxText' "
+"<widget name='grRenderPopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='vcSfxSlider' "
-"type='Slider' "
+"<widget name='grRenderPopup' "
+"type='PopUp' "
 "/> "
-"<widget name='vcSfxLabel' "
-"type='SmallLabel' "
+"</layout> "
+"<widget name='grAspectCheckbox' "
+"type='Checkbox' "
+"/> "
+"<widget name='grFullscreenCheckbox' "
+"type='Checkbox' "
+"/> "
+"<widget name='grDisableDitheringCheckbox' "
+"type='Checkbox' "
 "/> "
 "</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<widget name='vcSpeechText' "
+"<widget name='auMidiPopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='vcSpeechSlider' "
-"type='Slider' "
+"<widget name='auMidiPopup' "
+"type='PopUp' "
 "/> "
-"<widget name='vcSpeechLabel' "
-"type='SmallLabel' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='auOPLPopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auOPLPopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
-"<widget name='vcMuteCheckbox' "
-"type='Checkbox' "
-"width='80' "
+"<widget name='auSampleRatePopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auSampleRatePopup' "
+"type='PopUp' "
 "/> "
 "</layout> "
-"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
 "<widget name='subToggleDesc' "
 "type='OptionsLabel' "
 "/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
 "<widget name='subToggleSpeechOnly' "
 "type='Radiobutton' "
-"width='90' "
 "/> "
 "<widget name='subToggleSubOnly' "
 "type='Radiobutton' "
-"width='90' "
 "/> "
 "<widget name='subToggleSubBoth' "
 "type='Radiobutton' "
-"width='90' "
 "/> "
 "</layout> "
-"</layout> "
-"<space size='2' /> "
 "<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
 "<widget name='subSubtitleSpeedDesc' "
 "type='OptionsLabel' "
@@ -1477,546 +1463,560 @@
 "type='SmallLabel' "
 "/> "
 "</layout> "
-"<space size='16'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
-"<widget name='Keys' "
-"type='Button' "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='vcMusicText' "
+"type='OptionsLabel' "
 "/> "
-"<space size='Globals.Button.Width' /> "
-"<widget name='Cancel' "
-"type='Button' "
+"<widget name='vcMusicSlider' "
+"type='Slider' "
 "/> "
-"<widget name='Ok' "
-"type='Button' "
+"<widget name='vcMusicLabel' "
+"type='SmallLabel' "
 "/> "
 "</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Title' height='Globals.Line.Height'/> "
-"<widget name='List' /> "
-"<layout type='horizontal' padding='0,0,16,0'> "
-"<space/> "
-"<widget name='Delete' "
-"type='Button' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='vcSfxText' "
+"type='OptionsLabel' "
 "/> "
-"<space size='16'/> "
-"<widget name='Cancel' "
-"type='Button' "
+"<widget name='vcSfxSlider' "
+"type='Slider' "
 "/> "
-"<widget name='Choose' "
-"type='Button' "
+"<widget name='vcSfxLabel' "
+"type='SmallLabel' "
 "/> "
 "</layout> "
-"</layout> "
-"</dialog> "
-"<dialog name='ScummHelp' overlays='screen'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<widget name='Title' "
-"width='180' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='HelpText' "
-"height='140' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='vcSpeechText' "
+"type='OptionsLabel' "
 "/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='Prev' "
-"type='Button' "
+"<widget name='vcSpeechSlider' "
+"type='Slider' "
 "/> "
-"<widget name='Next' "
-"type='Button' "
+"<widget name='vcSpeechLabel' "
+"type='SmallLabel' "
 "/> "
-"<space size='32'/> "
-"<widget name='Close' "
-"type='Button' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
+"<widget name='vcMuteCheckbox' "
+"type='Checkbox' "
 "/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='4,4,16,4' center='true'> "
-"<widget name='DirProgressText' "
-"width='280' "
+"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='auPrefGmPopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefGmPopup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<widget name='mcFontButton' "
+"type='Button' "
+"/> "
+"<widget name='mcFontPath' "
 "height='Globals.Line.Height' "
 "/> "
-"<widget name='GameProgressText' "
-"width='280' "
+"<widget name='mcFontClearButton' "
 "height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
 "/> "
-"<widget name='GameList' "
-"width='280' "
-"height='100' "
+"</layout> "
+"<widget name='mcMixedCheckbox' "
+"type='Checkbox' "
 "/> "
-"<layout type='horizontal' padding='4,4,4,4'> "
-"<widget name='Ok' "
-"type='Button' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='mcMidiGainText' "
+"type='OptionsLabel' "
 "/> "
-"<widget name='Cancel' "
-"type='Button' "
+"<widget name='mcMidiGainSlider' "
+"type='Slider' "
+"/> "
+"<widget name='mcMidiGainLabel' "
+"width='32' "
+"height='Globals.Line.Height' "
 "/> "
 "</layout> "
 "</layout> "
 "</dialog> "
-"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
-"<widget name='PopupDesc' "
+"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='auPrefMt32PopupDesc' "
 "type='OptionsLabel' "
 "/> "
-"<widget name='Popup' "
+"<widget name='auPrefMt32Popup' "
 "type='PopUp' "
-"width='150' "
-"height='Globals.Line.Height' "
 "/> "
 "</layout> "
-"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
+"<widget name='mcMt32Checkbox' "
+"type='Checkbox' "
 "/> "
-"<widget name='Close' "
-"type='Button' "
+"<widget name='mcGSCheckbox' "
+"type='Checkbox' "
 "/> "
 "</layout> "
 "</dialog> "
-"</layout_info> "
-"<render_info> "
-"<palette> "
-"<color name='black' "
-"rgb='0,0,0' "
+"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<widget name='SaveButton' "
+"type='Button' "
 "/> "
-"<color name='lightgrey' "
-"rgb='104,104,104' "
+"<widget name='SavePath' "
+"height='Globals.Line.Height' "
 "/> "
-"<color name='darkgrey' "
-"rgb='64,64,64' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<widget name='ThemeButton' "
+"type='Button' "
 "/> "
-"<color name='green' "
-"rgb='32,160,32' "
+"<widget name='ThemePath' "
+"height='Globals.Line.Height' "
 "/> "
-"<color name='green2' "
-"rgb='0,255,0' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<widget name='ExtraButton' "
+"type='Button' "
 "/> "
-"</palette> "
-"<fonts> "
-"<font id='text_default' "
-"file='helvb12.bdf' "
+"<widget name='ExtraPath' "
+"height='Globals.Line.Height' "
 "/> "
-"<font resolution='320xY,256x240' "
-"id='text_default' "
-"file='clR6x12.bdf' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<widget name='PluginsButton' "
+"type='Button' "
 "/> "
-"<font id='text_button' "
-"file='helvb12.bdf' "
+"<widget name='PluginsPath' "
+"height='Globals.Line.Height' "
 "/> "
-"<font resolution='320xY,256x240' "
-"id='text_button' "
-"file='clR6x12.bdf' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<widget name='ThemeButton' "
+"type='Button' "
 "/> "
-"<font id='text_normal' "
-"file='helvb12.bdf' "
+"<widget name='CurTheme' "
+"height='Globals.Line.Height' "
 "/> "
-"<font resolution='320xY,256x240' "
-"id='text_normal' "
-"file='clR6x12.bdf' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='RendererPopupDesc' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"<font id='tooltip_normal' "
-"file='fixed5x8.bdf' "
+"<widget name='RendererPopup' "
+"type='PopUp' "
 "/> "
-"<text_color id='color_normal' "
-"color='green' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='AutosavePeriodPopupDesc' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"<text_color id='color_normal_inverted' "
-"color='black' "
+"<widget name='AutosavePeriodPopup' "
+"type='PopUp' "
 "/> "
-"<text_color id='color_normal_hover' "
-"color='green2' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='GuiLanguagePopupDesc' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"<text_color id='color_normal_disabled' "
-"color='lightgrey' "
+"<widget name='GuiLanguagePopup' "
+"type='PopUp' "
 "/> "
-"<text_color id='color_alternative' "
-"color='lightgrey' "
+"</layout> "
+"<widget name='KeysButton' "
+"type='Button' "
 "/> "
-"<text_color id='color_alternative_inverted' "
-"color='255,255,255' "
+"</layout> "
+"</dialog> "
+"<dialog name='KeysDialog' overlays='Dialog.GlobalOptions' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Action' "
+"height='Globals.Line.Height' "
 "/> "
-"<text_color id='color_alternative_hover' "
-"color='176,176,176' "
+"<widget name='List'/> "
+"<widget name='Mapping' "
+"height='Globals.Line.Height' "
 "/> "
-"<text_color id='color_alternative_disabled' "
-"color='darkgrey' "
+"<space size='Globals.Line.Height'/> "
+"<layout type='horizontal'> "
+"<widget name='Map' "
+"type='Button' "
 "/> "
-"<text_color id='color_button' "
-"color='green' "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"<text_color id='color_button_hover' "
-"color='green2' "
+"<widget name='Ok' "
+"type='Button' "
 "/> "
-"<text_color id='color_button_disabled' "
-"color='lightgrey' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
+"<widget name='TabWidget'/> "
+"<layout type='horizontal' padding='8,8,8,8'> "
+"<space/> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"</fonts> "
-"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> "
-"<drawdata id='text_selection' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='lightgrey' "
+"<widget name='Ok' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='text_selection_focus' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"</drawdata> "
-"<drawdata id='mainmenu_bg' cache='false'> "
-"<drawstep func='fill' "
-"fill='foreground' "
-"fg_color='black' "
+"<import layout='Dialog.GlobalOptions_Graphics' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"</drawdata> "
-"<drawdata id='special_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
+"<import layout='Dialog.GlobalOptions_Audio' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"</drawdata> "
-"<drawdata id='tooltip_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='foreground' "
-"fg_color='black' "
+"<import layout='Dialog.GlobalOptions_MIDI' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"</drawdata> "
-"<drawdata id='separator' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"height='2' "
-"ypos='center' "
-"fg_color='lightgrey' "
+"<import layout='Dialog.GlobalOptions_MT32' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<widget name='EnableTabCheckbox' "
+"type='Checkbox' "
 "/> "
-"</drawdata> "
-"<drawdata id='scrollbar_base' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
+"<import layout='Dialog.GlobalOptions_Volume' /> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='Id' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"</drawdata> "
-"<drawdata id='scrollbar_handle_hover' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green2' "
+"<widget name='Domain' "
+"type='PopUp' "
 "/> "
-"</drawdata> "
-"<drawdata id='scrollbar_handle_idle' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='Name' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_idle' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='Desc' "
+"type='PopUp' "
 "/> "
-"<drawstep func='triangle' "
-"fg_color='green' "
-"fill='foreground' "
-"width='auto' "
-"height='auto' "
-"xpos='center' "
-"ypos='center' "
-"orientation='top' "
+"</layout> "
+"<space size='8'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='LangPopupDesc' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_hover' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='LangPopup' "
+"type='PopUp' "
 "/> "
-"<drawstep func='triangle' "
-"fg_color='green2' "
-"fill='foreground' "
-"width='auto' "
-"height='auto' "
-"xpos='center' "
-"ypos='center' "
-"orientation='top' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='PlatformPopupDesc' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
 "/> "
-"</drawdata> "
-"<drawdata id='tab_active' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal_hover' "
-"vertical_align='center' "
-"horizontal_align='center' "
+"<widget name='PlatformPopup' "
+"type='PopUp' "
 "/> "
-"<drawstep func='tab' "
-"bevel='2' "
-"radius='0' "
-"fill='none' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<widget name='Savepath' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='tab_inactive' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='center' "
-"horizontal_align='center' "
+"<widget name='SavepathText' "
+"height='Globals.Line.Height' "
 "/> "
-"<drawstep func='tab' "
-"bevel='2' "
-"radius='0' "
-"fill='none' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<widget name='Extrapath' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='tab_background' cache='false'> "
-"</drawdata> "
-"<drawdata id='widget_slider' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='ExtrapathText' "
+"height='Globals.Line.Height' "
 "/> "
-"</drawdata> "
-"<drawdata id='slider_disabled' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='lightgrey' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<widget name='Gamepath' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='slider_full' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green' "
+"<widget name='GamepathText' "
+"height='Globals.Line.Height' "
 "/> "
-"</drawdata> "
-"<drawdata id='slider_hover' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green2' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalMenu' overlays='screen_center'> "
+"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
+"<widget name='Title' "
+"width='160' "
+"height='4' "
 "/> "
-"</drawdata> "
-"<drawdata id='widget_small' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='Version' "
+"width='160' "
+"height='4' "
 "/> "
-"</drawdata> "
-"<drawdata id='popup_idle' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<space size='1'/> "
+"<widget name='Load' "
+"width='120' "
+"height='12' "
 "/> "
-"<drawstep func='triangle' "
-"fg_color='green' "
-"fill='foreground' "
-"width='height' "
-"height='auto' "
-"xpos='right' "
-"ypos='center' "
-"orientation='bottom' "
+"<widget name='Save' "
+"width='120' "
+"height='12' "
 "/> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='center' "
-"horizontal_align='left' "
+"<space size='1'/> "
+"<widget name='Options' "
+"width='120' "
+"height='12' "
 "/> "
-"</drawdata> "
-"<drawdata id='popup_disabled' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='Help' "
+"width='120' "
+"height='12' "
 "/> "
-"<drawstep func='triangle' "
-"fg_color='lightgrey' "
-"fill='foreground' "
-"width='height' "
-"height='auto' "
-"xpos='right' "
-"ypos='center' "
-"orientation='bottom' "
+"<widget name='About' "
+"width='120' "
+"height='12' "
 "/> "
-"<text font='text_default' "
-"text_color='color_normal_disabled' "
-"vertical_align='center' "
-"horizontal_align='left' "
+"<space size='1'/> "
+"<widget name='Resume' "
+"width='120' "
+"height='12' "
 "/> "
-"</drawdata> "
-"<drawdata id='popup_hover' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='RTL' "
+"width='120' "
+"height='12' "
 "/> "
-"<drawstep func='triangle' "
-"fg_color='green2' "
-"fill='foreground' "
-"width='height' "
-"height='auto' "
-"xpos='right' "
-"ypos='center' "
-"orientation='bottom' "
+"<widget name='Quit' "
+"width='120' "
+"height='12' "
+"/> "
+"</layout> "
+"</dialog> "
+"<dialog name='GlobalConfig' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='vcMusicText' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='vcMusicSlider' "
+"type='Slider' "
+"/> "
+"<widget name='vcMusicLabel' "
+"type='SmallLabel' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='vcSfxText' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='vcSfxSlider' "
+"type='Slider' "
+"/> "
+"<widget name='vcSfxLabel' "
+"type='SmallLabel' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='vcSpeechText' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='vcSpeechSlider' "
+"type='Slider' "
+"/> "
+"<widget name='vcSpeechLabel' "
+"type='SmallLabel' "
 "/> "
-"<text font='text_default' "
-"text_color='color_normal_hover' "
-"vertical_align='center' "
-"horizontal_align='left' "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
+"<widget name='vcMuteCheckbox' "
+"type='Checkbox' "
+"width='80' "
 "/> "
-"</drawdata> "
-"<drawdata id='widget_textedit' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"</layout> "
+"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
+"<widget name='subToggleDesc' "
+"type='OptionsLabel' "
 "/> "
-"</drawdata> "
-"<drawdata id='plain_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='subToggleSpeechOnly' "
+"type='Radiobutton' "
+"width='90' "
 "/> "
-"</drawdata> "
-"<drawdata id='caret' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='lightgrey' "
+"<widget name='subToggleSubOnly' "
+"type='Radiobutton' "
+"width='90' "
 "/> "
-"</drawdata> "
-"<drawdata id='default_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
+"<widget name='subToggleSubBoth' "
+"type='Radiobutton' "
+"width='90' "
 "/> "
-"</drawdata> "
-"<drawdata id='button_idle' cache='false'> "
-"<text font='text_button' "
-"text_color='color_button' "
-"vertical_align='center' "
-"horizontal_align='center' "
+"</layout> "
+"</layout> "
+"<space size='2' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<widget name='subSubtitleSpeedDesc' "
+"type='OptionsLabel' "
 "/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='subSubtitleSpeedSlider' "
+"type='Slider' "
 "/> "
-"</drawdata> "
-"<drawdata id='button_hover' cache='false'> "
-"<text font='text_button' "
-"text_color='color_button_hover' "
-"vertical_align='center' "
-"horizontal_align='center' "
+"<widget name='subSubtitleSpeedLabel' "
+"type='SmallLabel' "
 "/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"</layout> "
+"<space size='16'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
+"<widget name='Keys' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='button_disabled' cache='false'> "
-"<text font='text_button' "
-"text_color='color_button_disabled' "
-"vertical_align='center' "
-"horizontal_align='center' "
+"<space size='Globals.Button.Width' /> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='Ok' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='checkbox_disabled' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal_disabled' "
-"vertical_align='top' "
-"horizontal_align='left' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' height='Globals.Line.Height'/> "
+"<widget name='List' /> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<space/> "
+"<widget name='Delete' "
+"type='Button' "
 "/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<space size='16'/> "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='checkbox_selected' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='top' "
-"horizontal_align='left' "
+"<widget name='Choose' "
+"type='Button' "
 "/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='Title' "
+"width='180' "
+"height='Globals.Line.Height' "
 "/> "
-"<drawstep func='cross' "
-"fill='foreground' "
-"stroke='2' "
-"fg_color='green' "
+"<widget name='HelpText' "
+"height='140' "
 "/> "
-"</drawdata> "
-"<drawdata id='checkbox_default' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='top' "
-"horizontal_align='left' "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='Prev' "
+"type='Button' "
 "/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
+"<widget name='Next' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='radiobutton_default' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='center' "
-"horizontal_align='left' "
+"<space size='32'/> "
+"<widget name='Close' "
+"type='Button' "
 "/> "
-"<drawstep func='circle' "
-"width='7' "
-"height='7' "
-"radius='7' "
-"fill='background' "
-"bg_color='darkgrey' "
-"xpos='0' "
-"ypos='0' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
+"<layout type='vertical' padding='4,4,16,4' center='true'> "
+"<widget name='DirProgressText' "
+"width='280' "
+"height='Globals.Line.Height' "
 "/> "
-"</drawdata> "
-"<drawdata id='radiobutton_selected' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='center' "
-"horizontal_align='left' "
+"<widget name='GameProgressText' "
+"width='280' "
+"height='Globals.Line.Height' "
 "/> "
-"<drawstep func='circle' "
-"width='7' "
-"height='7' "
-"radius='7' "
-"fg_color='darkgrey' "
-"fill='none' "
-"xpos='0' "
-"ypos='0' "
+"<widget name='GameList' "
+"width='280' "
+"height='100' "
 "/> "
-"<drawstep func='circle' "
-"width='7' "
-"height='7' "
-"radius='5' "
-"fg_color='green' "
-"fill='foreground' "
-"xpos='2' "
-"ypos='2' "
+"<layout type='horizontal' padding='4,4,4,4'> "
+"<widget name='Ok' "
+"type='Button' "
 "/> "
-"</drawdata> "
-"<drawdata id='radiobutton_disabled' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal_disabled' "
-"vertical_align='center' "
-"horizontal_align='left' "
+"<widget name='Cancel' "
+"type='Button' "
 "/> "
-"<drawstep func='circle' "
-"width='7' "
-"height='7' "
-"radius='7' "
-"bg_color='lightgrey' "
-"fill='background' "
-"xpos='0' "
-"ypos='0' "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<widget name='PopupDesc' "
+"type='OptionsLabel' "
 "/> "
-"</drawdata> "
-"<drawdata id='widget_default' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
+"<widget name='Popup' "
+"type='PopUp' "
+"width='150' "
+"height='Globals.Line.Height' "
 "/> "
-"</drawdata> "
-"<drawdata id='widget_small' cache='false'> "
-"<drawstep func='square' "
-"stroke='0' "
+"</layout> "
+"<widget name='KeymapArea' "
+"width='300' "
+"height='120' "
 "/> "
-"</drawdata> "
-"</render_info> "
+"<widget name='Close' "
+"type='Button' "
+"/> "
+"</layout> "
+"</dialog> "
+"</layout_info> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 9fd2c18..ecc2ebb 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx
index d672db2..3fd00ab 100644
--- a/gui/themes/scummclassic/classic_gfx.stx
+++ b/gui/themes/scummclassic/classic_gfx.stx
@@ -46,21 +46,21 @@
 		<font	id = 'text_default'
 				file = 'helvb12.bdf'
 		/>
-		<font	resolution = '320xY, 256x240'
+		<font	resolution = 'y<400'
 		   		id = 'text_default'
 				file = 'clR6x12.bdf'
 		/>
 		<font	id = 'text_button'
 				file = 'helvb12.bdf'
 		/>
-		<font	resolution = '320xY, 256x240'
+		<font	resolution = 'y<400'
 		   		id = 'text_button'
 				file = 'clR6x12.bdf'
 		/>
 		<font	id = 'text_normal'
 				file = 'helvb12.bdf'
 		/>
-		<font	resolution = '320xY, 256x240'
+		<font	resolution = 'y<400'
 		   		id = 'text_normal'
 				file = 'clR6x12.bdf'
 		/>
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 416ffb3..f09c29e 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -23,7 +23,7 @@
  - $Id$
  -
  -->
-<layout_info resolution = '-320xY, -256x240, -Xx272, -544x332, -Xx350'>
+<layout_info resolution = 'y>399'>
 	<globals>
 		<def var = 'Line.Height' value = '16' />
 		<def var = 'Font.Height' value = '16' />
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index fe0eb66..a440be7 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -23,7 +23,7 @@
  - $Id$
  -
  -->
-<layout_info resolution = "320xY, 256x240, Xx272, 544x332, Xx350">
+<layout_info resolution = 'y<400'>
 	<globals>
 		<def var = 'Line.Height' value = '12' />
 		<def var = 'Font.Height' value = '10' />
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index f4e18ef..6fd88c1 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index cfe00a7..a325d49 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -108,21 +108,21 @@
 		<font	id = 'text_default'
 				file = 'helvb12.bdf'
 		/>
-		<font	resolution = '320xY, 256x240'
+		<font	resolution = 'y<400'
 		   		id = 'text_default'
 				file = 'clR6x12.bdf'
 		/>
 		<font	id = 'text_button'
 				file = 'helvb12.bdf'
 		/>
-		<font	resolution = '320xY, 256x240'
+		<font	resolution = 'y<400'
 		   		id = 'text_button'
 				file = 'clR6x12.bdf'
 		/>
 		<font	id = 'text_normal'
 				file = 'helvb12.bdf'
 		/>
-		<font	resolution = '320xY, 256x240'
+		<font	resolution = 'y<400'
 		   		id = 'text_normal'
 				file = 'clR6x12.bdf'
 		/>
@@ -178,7 +178,7 @@
 	<!-- <defaults fill = 'gradient' fg_color = 'white'/> -->
 
 	<cursor file = 'cursor.bmp' hotspot = '0, 0' scale = '3'/>
-	<cursor resolution = '320xY, 256x240' file = 'cursor_small.bmp' hotspot = '0, 0' scale = '3'/>
+	<cursor resolution = 'y<400' file = 'cursor_small.bmp' hotspot = '0, 0' scale = '3'/>
 
 	<!-- Selection (text or list items) -->
 	<drawdata id = 'text_selection' cache = 'false'>
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 879be2a..32d6d19 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -23,7 +23,7 @@
  - $Id$
  -
  -->
-<layout_info resolution = '-320xY, -256x240, -Xx272, -544x332, -Xx350'>
+<layout_info resolution = 'y>399'>
 	<globals>
 		<def var = 'Line.Height' value = '16' />
 		<def var = 'Font.Height' value = '16' />
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 3a7a4b6..06916a8 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -23,7 +23,7 @@
  - $Id$
  -
  -->
-<layout_info resolution = "320xY, 256x240, Xx272, 544x332, Xx350">
+<layout_info resolution = 'y<400'>
 	<globals>
 		<def var = 'Line.Height' value = '12' />
 		<def var = 'Font.Height' value = '10' />


Commit: 867fa2696def58300cd376d03be6755007abbe43
    https://github.com/scummvm/scummvm/commit/867fa2696def58300cd376d03be6755007abbe43
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:33-08:00

Commit Message:
ANDROID: Let's not do that on the stack

Changed paths:
    backends/platform/android/texture.cpp



diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
index b638976..c5cba97 100644
--- a/backends/platform/android/texture.cpp
+++ b/backends/platform/android/texture.cpp
@@ -166,9 +166,11 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
 			return;
 
 #if TEXSUBIMAGE_IS_EXPENSIVE
-		byte tmpbuf[w * h * bytesPerPixel()];
+		byte *tmp = new byte[w * h * bytesPerPixel()];
+		assert(tmp);
+
 		const byte *src = static_cast<const byte *>(buf);
-		byte *dst = tmpbuf;
+		byte *dst = tmp;
 		GLuint count = h;
 
 		do {
@@ -178,7 +180,9 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
 		} while (--count);
 
 		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
-								glFormat(), glType(), tmpbuf));
+								glFormat(), glType(), tmp));
+
+		delete[] tmp;
 #else
 		// This version avoids the intermediate copy at the expense of
 		// repeat glTexSubImage2D calls.  On some devices this is worse.
@@ -194,10 +198,15 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
 }
 
 void GLESTexture::fillBuffer(byte x) {
-	int rowbytes = _surface.w * bytesPerPixel();
-	byte tmpbuf[_surface.h * rowbytes];
-	memset(tmpbuf, x, _surface.h * rowbytes);
-	updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes);
+	uint rowbytes = _surface.w * bytesPerPixel();
+
+	byte *tmp = new byte[_surface.h * rowbytes];
+	assert(tmp);
+
+	memset(tmp, x, _surface.h * rowbytes);
+	updateBuffer(0, 0, _surface.w, _surface.h, tmp, rowbytes);
+
+	delete[] tmp;
 }
 
 void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {


Commit: d8acbc0311fd126b0b3a2298082dadc98022f933
    https://github.com/scummvm/scummvm/commit/d8acbc0311fd126b0b3a2298082dadc98022f933
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:33-08:00

Commit Message:
ANDROID: Deuglify overlay gfx

Use the native surface resolution of the device if its not too big.
If it is, use a clean scale factor of 2 to prevent eyecancer.

Changed paths:
    backends/platform/android/gfx.cpp



diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index 838e5bc..d4d96a2 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -121,9 +121,22 @@ void OSystem_Android::initSize(uint width, uint height,
 
 	_game_texture->allocBuffer(width, height);
 
-	// Cap at 320x200 or the ScummVM themes abort :/
-	GLuint overlay_width = MIN(_egl_surface_width, 320);
-	GLuint overlay_height = MIN(_egl_surface_height, 200);
+	GLuint overlay_width = _egl_surface_width;
+	GLuint overlay_height = _egl_surface_height;
+
+	// the 'normal' theme layout uses a max height of 400 pixels. if the
+	// surface is too big we use only a quarter of the size so that the widgets
+	// don't get too small. if the surface height has less than 800 pixels, this
+	// enforces the 'lowres' layout, which will be scaled back up by factor 2x,
+	// but this looks way better than the 'normal' layout scaled by some
+	// calculated factors
+	if (overlay_height > 480) {
+		overlay_width /= 2;
+		overlay_height /= 2;
+	}
+
+	LOGI("overlay size is %ux%u", overlay_width, overlay_height);
+
 	_overlay_texture->allocBuffer(overlay_width, overlay_height);
 
 	// Don't know mouse size yet - it gets reallocated in


Commit: 36135443b9263e0125c8f9f2834818c2f9465983
    https://github.com/scummvm/scummvm/commit/36135443b9263e0125c8f9f2834818c2f9465983
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:33-08:00

Commit Message:
ANDROID: Disable zoning for now

Changed paths:
    backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java



diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index fae35b6..09d39d2 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -52,7 +52,9 @@ public class ScummVMActivity extends Activity {
 			super(ScummVMActivity.this);
 
 			// Enable ScummVM zoning on 'small' screens.
-			enableZoning(usingSmallScreen());
+			// FIXME make this optional for the user
+			// disabled for now since it crops too much
+			//enableZoning(usingSmallScreen());
 		}
 
 		@Override


Commit: a636d41ca8c066adfed4fd16d9a2e46de5fab871
    https://github.com/scummvm/scummvm/commit/a636d41ca8c066adfed4fd16d9a2e46de5fab871
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:34-08:00

Commit Message:
ANDROID: Check thread origin when debugging GL

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/gfx.cpp



diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 3639987..4968e4b 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -156,6 +156,8 @@ void *OSystem_Android::timerThreadFunc(void *arg) {
 void OSystem_Android::initBackend() {
 	ENTER();
 
+	_main_thread = pthread_self();
+
 	ConfMan.setInt("autosave_period", 0);
 	ConfMan.setInt("FM_medium_quality", true);
 
@@ -350,6 +352,7 @@ void OSystem_Android::delayMillis(uint msecs) {
 
 OSystem::MutexRef OSystem_Android::createMutex() {
 	pthread_mutexattr_t attr;
+
 	pthread_mutexattr_init(&attr);
 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
 
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 8fc138d..23c1e85 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -61,7 +61,7 @@ extern const char *android_log_tag;
 #ifdef ANDROID_DEBUG_ENTER
 #define ENTER(fmt, args...) LOGD("%s(" fmt ")", __FUNCTION__, ##args)
 #else
-#define ENTER(fmt, args...) /**/
+#define ENTER(fmt, args...) do {  } while (false)
 #endif
 
 #ifdef ANDROID_DEBUG_GL
@@ -73,8 +73,14 @@ extern void checkGlError(const char *expr, const char *file, int line);
 		checkGlError(#x, __FILE__, __LINE__); \
 	} while (false)
 
+#define GLTHREADCHECK \
+	do { \
+		assert(pthread_self() == _main_thread); \
+	} while (false)
+
 #else
 #define GLCALL(x) do { (x); } while (false)
+#define GLTHREADCHECK do {  } while (false)
 #endif
 
 #ifdef DYNAMIC_MODULES
@@ -111,6 +117,8 @@ private:
 	Common::Queue<Common::Event> _event_queue;
 	MutexRef _event_queue_lock;
 
+	pthread_t _main_thread;
+
 	bool _timer_thread_exit;
 	pthread_t _timer_thread;
 	static void *timerThreadFunc(void *arg);
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
index d4d96a2..a84e5ce 100644
--- a/backends/platform/android/gfx.cpp
+++ b/backends/platform/android/gfx.cpp
@@ -119,6 +119,8 @@ void OSystem_Android::initSize(uint width, uint height,
 								const Graphics::PixelFormat *format) {
 	ENTER("%d, %d, %p", width, height, format);
 
+	GLTHREADCHECK;
+
 	_game_texture->allocBuffer(width, height);
 
 	GLuint overlay_width = _egl_surface_width;
@@ -157,6 +159,8 @@ int16 OSystem_Android::getWidth() {
 void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
 	ENTER("%p, %u, %u", colors, start, num);
 
+	GLTHREADCHECK;
+
 	if (!_use_mouse_palette)
 		_setCursorPalette(colors, start, num);
 
@@ -166,6 +170,8 @@ void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
 void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
 	ENTER("%p, %u, %u", colors, start, num);
 
+	GLTHREADCHECK;
+
 	memcpy(colors, _game_texture->palette_const() + start * 3, num * 3);
 }
 
@@ -173,12 +179,16 @@ void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
 										int x, int y, int w, int h) {
 	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
 
+	GLTHREADCHECK;
+
 	_game_texture->updateBuffer(x, y, w, h, buf, pitch);
 }
 
 void OSystem_Android::updateScreen() {
 	//ENTER();
 
+	GLTHREADCHECK;
+
 	if (!_force_redraw &&
 			!_game_texture->dirty() &&
 			!_overlay_texture->dirty() &&
@@ -279,6 +289,8 @@ void OSystem_Android::updateScreen() {
 Graphics::Surface *OSystem_Android::lockScreen() {
 	ENTER();
 
+	GLTHREADCHECK;
+
 	Graphics::Surface *surface = _game_texture->surface();
 	assert(surface->pixels);
 
@@ -288,6 +300,8 @@ Graphics::Surface *OSystem_Android::lockScreen() {
 void OSystem_Android::unlockScreen() {
 	ENTER();
 
+	GLTHREADCHECK;
+
 	assert(_game_texture->dirty());
 }
 
@@ -303,6 +317,8 @@ void OSystem_Android::setShakePos(int shake_offset) {
 void OSystem_Android::fillScreen(uint32 col) {
 	ENTER("%u", col);
 
+	GLTHREADCHECK;
+
 	assert(col < 256);
 	_game_texture->fillBuffer(col);
 }
@@ -342,6 +358,8 @@ void OSystem_Android::hideOverlay() {
 void OSystem_Android::clearOverlay() {
 	ENTER();
 
+	GLTHREADCHECK;
+
 	_overlay_texture->fillBuffer(0);
 
 	// Shouldn't need this, but works around a 'blank screen' bug on Nexus1
@@ -351,6 +369,8 @@ void OSystem_Android::clearOverlay() {
 void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
 	ENTER("%p, %d", buf, pitch);
 
+	GLTHREADCHECK;
+
 	// We support overlay alpha blending, so the pixel data here
 	// shouldn't actually be used.	Let's fill it with zeros, I'm sure
 	// it will be fine...
@@ -371,6 +391,8 @@ void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
 										int x, int y, int w, int h) {
 	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
 
+	GLTHREADCHECK;
+
 	const Graphics::Surface *surface = _overlay_texture->surface_const();
 	assert(surface->bytesPerPixel == sizeof(buf[0]));
 
@@ -411,6 +433,8 @@ void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
 	ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
 			keycolor, cursorTargetScale, format);
 
+	GLTHREADCHECK;
+
 	assert(keycolor < 256);
 
 	_mouse_texture->allocBuffer(w, h);
@@ -452,6 +476,8 @@ void OSystem_Android::setCursorPalette(const byte *colors,
 										uint start, uint num) {
 	ENTER("%p, %u, %u", colors, start, num);
 
+	GLTHREADCHECK;
+
 	_setCursorPalette(colors, start, num);
 	_use_mouse_palette = true;
 }


Commit: c8551b80dd917c35d367c1f15f4b9c2618da3684
    https://github.com/scummvm/scummvm/commit/c8551b80dd917c35d367c1f15f4b9c2618da3684
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:34-08:00

Commit Message:
GUI: Properly clear the screen buffer

Don't operate on the overlay, it might be a pointer to a texture
used by the hardware. This get's rid of some annoying flickers on
androids

Changed paths:
    gui/ThemeEngine.cpp



diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index ee83ca6..356ed0f 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -421,10 +421,9 @@ bool ThemeEngine::init() {
 }
 
 void ThemeEngine::clearAll() {
-	if (_initOk) {
-		_system->clearOverlay();
-		_system->grabOverlay((OverlayColor *)_screen.pixels, _screen.w);
-	}
+	if (_initOk)
+		memset(_screen.pixels, _overlayFormat.RGBToColor(0, 0, 0),
+				_screen.w * _screen.h * sizeof(uint16));
 }
 
 void ThemeEngine::refresh() {


Commit: a017cb3d00293c2f4c916c375fff172a6d962e33
    https://github.com/scummvm/scummvm/commit/a017cb3d00293c2f4c916c375fff172a6d962e33
Author: dhewg (dhewg at wiibrew.org)
Date: 2011-02-24T14:18:34-08:00

Commit Message:
GUI: Fix two-step rendering

This is used when changing directories in the 'add game' dialog or when
choosing another tab in the option dialog. Only blit to the overlay on
the final pass. Gets rid of highly annoying flickers on androids

Changed paths:
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/gui-manager.cpp



diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 356ed0f..235ea24 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1192,7 +1192,7 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) {
 /**********************************************************
  *	Screen/overlay management
  *********************************************************/
-void ThemeEngine::updateScreen() {
+void ThemeEngine::updateScreen(bool render) {
 	if (!_bufferQueue.empty()) {
 		_vectorRenderer->setSurface(&_backBuffer);
 
@@ -1217,7 +1217,8 @@ void ThemeEngine::updateScreen() {
 		_screenQueue.clear();
 	}
 
-	renderDirtyScreen();
+	if (render)
+		renderDirtyScreen();
 }
 
 void ThemeEngine::addDirtyRect(Common::Rect r) {
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index e852760..2a3964a 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -280,7 +280,7 @@ public:
 	 *	It processes all the drawing queues and then copies dirty rects
 	 *	in the current Screen surface to the overlay.
 	 */
-	void updateScreen();
+	void updateScreen(bool render = true);
 
 
 	/** @name FONT MANAGEMENT METHODS */
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 7644cbe..3ad4b2e 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -201,14 +201,15 @@ void GuiManager::redraw() {
 			_theme->clearAll();
 			_theme->openDialog(true, ThemeEngine::kShadingNone);
 
-			for (i = 0; i < _dialogStack.size() - 1; i++) {
+			for (i = 0; i < _dialogStack.size() - 1; i++)
 				_dialogStack[i]->drawDialog();
-			}
 
 			_theme->finishBuffering();
 
+			// fall through
+
 		case kRedrawOpenDialog:
-			_theme->updateScreen();
+			_theme->updateScreen(false);
 			_theme->openDialog(true, shading);
 			_dialogStack.top()->drawDialog();
 			_theme->finishBuffering();






More information about the Scummvm-git-logs mailing list