aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
Diffstat (limited to 'backends')
-rw-r--r--backends/base-backend.cpp3
-rw-r--r--backends/events/gp2xsdl/gp2xsdl-events.cpp13
-rw-r--r--backends/events/gp2xsdl/gp2xsdl-events.h5
-rw-r--r--backends/events/gph/gph-events.cpp (renamed from backends/platform/gph/gph-events.cpp)150
-rw-r--r--backends/events/gph/gph-events.h56
-rw-r--r--backends/events/openpandora/op-events.cpp (renamed from backends/platform/openpandora/op-events.cpp)146
-rw-r--r--backends/events/openpandora/op-events.h44
-rw-r--r--backends/events/webossdl/webossdl-events.cpp241
-rw-r--r--backends/events/webossdl/webossdl-events.h44
-rw-r--r--backends/events/wincesdl/wincesdl-events.cpp332
-rw-r--r--backends/events/wincesdl/wincesdl-events.h73
-rw-r--r--backends/graphics/default-palette.h6
-rw-r--r--backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp5
-rw-r--r--backends/graphics/gph/gph-graphics.cpp (renamed from backends/platform/gph/gph-graphics.cpp)176
-rw-r--r--backends/graphics/gph/gph-graphics.h62
-rw-r--r--backends/graphics/opengl/gltexture.cpp2
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp461
-rw-r--r--backends/graphics/opengl/opengl-graphics.h83
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp195
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h9
-rw-r--r--backends/graphics/openpandora/op-graphics.cpp (renamed from backends/platform/openpandora/op-graphics.cpp)22
-rw-r--r--backends/graphics/openpandora/op-graphics.h62
-rw-r--r--backends/graphics/sdl/sdl-graphics.cpp154
-rw-r--r--backends/graphics/sdl/sdl-graphics.h14
-rw-r--r--backends/graphics/wincesdl/wincesdl-graphics.cpp1639
-rw-r--r--backends/graphics/wincesdl/wincesdl-graphics.h206
-rw-r--r--backends/midi/alsa.cpp53
-rw-r--r--backends/midi/camd.cpp1
-rw-r--r--backends/midi/coreaudio.cpp17
-rw-r--r--backends/midi/coremidi.cpp11
-rw-r--r--backends/midi/dmedia.cpp3
-rw-r--r--backends/midi/seq.cpp1
-rw-r--r--backends/midi/stmidi.cpp39
-rw-r--r--backends/midi/timidity.cpp52
-rw-r--r--backends/midi/windows.cpp3
-rw-r--r--backends/mixer/wincesdl/wincesdl-mixer.cpp183
-rw-r--r--backends/mixer/wincesdl/wincesdl-mixer.h53
-rw-r--r--backends/module.mk8
-rw-r--r--backends/platform/android/README.build90
-rw-r--r--backends/platform/android/android.cpp1501
-rw-r--r--backends/platform/android/android.h307
-rw-r--r--backends/platform/android/android.mk205
-rw-r--r--backends/platform/android/asset-archive.cpp204
-rw-r--r--backends/platform/android/asset-archive.h7
-rw-r--r--backends/platform/android/events.cpp805
-rw-r--r--backends/platform/android/gfx.cpp819
-rw-r--r--backends/platform/android/jni.cpp605
-rw-r--r--backends/platform/android/jni.h151
-rw-r--r--backends/platform/android/module.mk81
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java15
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Event.java330
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java18
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVM.java710
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java411
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java10
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java232
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Unpacker.java31
-rw-r--r--backends/platform/android/texture.cpp477
-rw-r--r--backends/platform/android/texture.h277
-rw-r--r--backends/platform/android/video.cpp354
-rw-r--r--backends/platform/android/video.h140
-rw-r--r--backends/platform/dc/display.cpp7
-rw-r--r--backends/platform/dc/dreamcast.mk2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp5
-rwxr-xr-xbackends/platform/ds/build-ds.sh4
-rw-r--r--backends/platform/gp2x/build/README-GP2X54
-rwxr-xr-xbackends/platform/gp2x/build/bundle.sh10
-rw-r--r--backends/platform/gp2x/gp2x-common.h15
-rw-r--r--backends/platform/gp2x/gp2x-main.cpp10
-rw-r--r--backends/platform/gp2x/gp2x.cpp8
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-build.sh (renamed from backends/platform/gph/caanoo/build.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-bundle-debug.sh (renamed from backends/platform/gph/caanoo/bundle-debug.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-bundle.sh (renamed from backends/platform/gph/caanoo/bundle.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-config-alleng.sh (renamed from backends/platform/gph/caanoo/config-alleng.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/caanoo-config.sh (renamed from backends/platform/gph/caanoo/config.sh)0
-rwxr-xr-xbackends/platform/gph/build/clean.sh2
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2x-build.sh (renamed from backends/platform/gp2x/build/build.sh)0
-rw-r--r--backends/platform/gph/build/gp2x-bundle.sh19
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2x-config-alleng.sh (renamed from backends/platform/gp2x/build/config-alleng.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2x-config.sh (renamed from backends/platform/gp2x/build/config.sh)2
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-build.sh (renamed from backends/platform/gph/build/build.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-bundle-debug.sh (renamed from backends/platform/gph/build/bundle-debug.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-bundle.sh (renamed from backends/platform/gph/build/bundle.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-config-alleng.sh (renamed from backends/platform/gph/build/config-alleng.sh)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/build/gp2xwiz-config.sh (renamed from backends/platform/gph/build/config.sh)0
-rw-r--r--backends/platform/gph/build/scummvm.pngbin2656 -> 0 bytes
-rwxr-xr-xbackends/platform/gph/caanoo-bundle.mk20
-rwxr-xr-xbackends/platform/gph/caanoo/clean.sh8
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/caanoo/scummvm-gdb.gpe (renamed from backends/platform/gph/build/scummvm-gdb.gpe)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/caanoo/scummvm.gpe (renamed from backends/platform/gph/caanoo/scummvm.gpe)0
-rw-r--r--backends/platform/gph/devices/common/README-GPH (renamed from backends/platform/gph/build/README-GPH)4
-rw-r--r--backends/platform/gph/devices/common/scummvm.ini (renamed from backends/platform/gph/build/scummvm.ini)0
-rw-r--r--backends/platform/gph/devices/common/scummvm.png (renamed from backends/platform/gp2x/build/scummvm.png)bin2656 -> 2656 bytes
-rw-r--r--backends/platform/gph/devices/common/scummvmb.png (renamed from backends/platform/gph/build/scummvmb.png)bin34274 -> 34274 bytes
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/Makefile (renamed from backends/platform/gp2x/mmuhack/Makefile)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h (renamed from backends/platform/gp2x/mmuhack/flush_uppermem_cache.h)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s (renamed from backends/platform/gp2x/mmuhack/flush_uppermem_cache.s)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c (renamed from backends/platform/gp2x/mmuhack/mmuhack.c)0
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o (renamed from backends/platform/gp2x/build/mmuhack.o)bin1720 -> 1720 bytes
-rw-r--r--backends/platform/gph/devices/gp2x/mmuhack/readme.txt (renamed from backends/platform/gp2x/mmuhack/readme.txt)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/gp2x/scummvm.gpe (renamed from backends/platform/gp2x/build/scummvm.gpe)4
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe (renamed from backends/platform/gph/caanoo/scummvm-gdb.gpe)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/devices/gp2xwiz/scummvm.gpe (renamed from backends/platform/gph/build/scummvm.gpe)0
-rw-r--r--[-rwxr-xr-x]backends/platform/gph/gp2x-bundle.mk (renamed from backends/platform/gp2x/gp2x-bundle.mk)23
-rwxr-xr-xbackends/platform/gph/gp2xwiz-bundle.mk21
-rw-r--r--backends/platform/gph/gph-backend.cpp211
-rw-r--r--backends/platform/gph/gph-main.cpp191
-rw-r--r--backends/platform/gph/gph-sdl.h53
-rw-r--r--backends/platform/gph/module.mk7
-rw-r--r--backends/platform/iphone/osys_video.cpp5
-rw-r--r--backends/platform/n64/osys_n64.h7
-rw-r--r--backends/platform/n64/osys_n64_base.cpp18
-rw-r--r--backends/platform/n64/osys_n64_events.cpp4
-rwxr-xr-xbackends/platform/openpandora/module.mk3
-rw-r--r--backends/platform/openpandora/op-backend.cpp273
-rw-r--r--backends/platform/openpandora/op-main.cpp234
-rw-r--r--backends/platform/openpandora/op-sdl.h22
-rw-r--r--backends/platform/ps2/Gs2dScreen.cpp20
-rw-r--r--backends/platform/ps2/Gs2dScreen.h4
-rw-r--r--backends/platform/ps2/systemps2.cpp4
-rw-r--r--backends/platform/psp/README.PSP2
-rw-r--r--backends/platform/psp/display_client.cpp6
-rw-r--r--backends/platform/sdl/posix/posix-main.cpp2
-rw-r--r--backends/platform/sdl/sdl.cpp26
-rw-r--r--backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in2
-rw-r--r--backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_agi.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_agos.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_base.mmp.in10
-rw-r--r--backends/platform/symbian/mmp/scummvm_cine.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_cruise.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_draci.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_drascula.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_gob.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_groovie.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_hugo.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_kyra.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_lure.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_m4.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_made.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_mohawk.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_parallaction.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_queen.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_saga.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sci.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_scumm.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sky.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sword1.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_sword2.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_teenagent.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_tinsel.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_toon.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_touche.mmp.in2
-rw-r--r--backends/platform/symbian/mmp/scummvm_tucker.mmp.in2
-rw-r--r--backends/platform/webos/main.cpp53
-rw-r--r--backends/platform/webos/module.mk10
-rw-r--r--backends/platform/webos/webos.cpp73
-rw-r--r--backends/platform/webos/webos.h40
-rw-r--r--backends/platform/webos/webos.mk23
-rw-r--r--backends/platform/wii/osystem_gfx.cpp28
-rw-r--r--backends/platform/wince/CEActionsPocket.cpp58
-rw-r--r--backends/platform/wince/CEActionsSmartphone.cpp169
-rw-r--r--backends/platform/wince/CEDevice.cpp31
-rw-r--r--backends/platform/wince/CEDevice.h2
-rw-r--r--backends/platform/wince/CEException.cpp22
-rw-r--r--backends/platform/wince/CELauncherDialog.cpp9
-rw-r--r--backends/platform/wince/CEgui/GUIElement.cpp9
-rw-r--r--backends/platform/wince/CEgui/ItemAction.cpp2
-rw-r--r--backends/platform/wince/CEgui/ItemSwitch.cpp6
-rw-r--r--backends/platform/wince/CEgui/Panel.cpp11
-rw-r--r--backends/platform/wince/CEgui/Panel.h2
-rw-r--r--backends/platform/wince/CEgui/PanelItem.h2
-rw-r--r--backends/platform/wince/CEgui/PanelKeyboard.cpp21
-rw-r--r--backends/platform/wince/CEgui/SDL_ImageResource.cpp4
-rw-r--r--backends/platform/wince/CEgui/SDL_ImageResource.h4
-rw-r--r--backends/platform/wince/CEgui/ToolbarHandler.cpp13
-rw-r--r--backends/platform/wince/CEgui/ToolbarHandler.h2
-rw-r--r--backends/platform/wince/CEkeys/EventsBuffer.cpp98
-rw-r--r--backends/platform/wince/CEkeys/EventsBuffer.h16
-rw-r--r--backends/platform/wince/Makefile2
-rw-r--r--backends/platform/wince/missing/io.h6
-rw-r--r--backends/platform/wince/missing/missing.cpp60
-rw-r--r--backends/platform/wince/missing/time.h7
-rw-r--r--backends/platform/wince/portdefs.h38
-rw-r--r--backends/platform/wince/wince-sdl.cpp2113
-rw-r--r--backends/platform/wince/wince-sdl.h186
-rw-r--r--backends/saves/savefile.cpp15
-rw-r--r--backends/timer/default/default-timer.cpp2
-rw-r--r--backends/timer/default/default-timer.h6
190 files changed, 10165 insertions, 6765 deletions
diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp
index 42ab7b887a..f349cc8005 100644
--- a/backends/base-backend.cpp
+++ b/backends/base-backend.cpp
@@ -101,7 +101,4 @@ AudioCDManager *BaseBackend::getAudioCDManager() {
}
void BaseBackend::resetGraphicsScale() {
- // As a hack, we use 0 here. Backends should override this method
- // and provide their own.
- setGraphicsMode(0);
}
diff --git a/backends/events/gp2xsdl/gp2xsdl-events.cpp b/backends/events/gp2xsdl/gp2xsdl-events.cpp
index 184f1d9b64..86d4de384f 100644
--- a/backends/events/gp2xsdl/gp2xsdl-events.cpp
+++ b/backends/events/gp2xsdl/gp2xsdl-events.cpp
@@ -18,22 +18,15 @@
* 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$
- *
*/
#include "common/scummsys.h"
-#if defined(GP2X) || defined(GP2XWIZ)
+#if defined(GP2X_OLD)
#include "backends/events/gp2xsdl/gp2xsdl-events.h"
-#if defined(GP2X)
#include "backends/platform/gp2x/gp2x-hw.h"
#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
-#else
-#include "backends/platform/gp2xwiz/gp2xwiz-hw.h"
-#endif
#include "backends/platform/sdl/sdl.h"
@@ -88,7 +81,6 @@ enum {
GP2XSdlEventSource::GP2XSdlEventSource()
: _buttonStateL(false){
-
}
void GP2XSdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
@@ -441,7 +433,7 @@ bool GP2XSdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event
_km.x_down_count = 0;
}
#endif
-
+
} else if (ev.jaxis.axis == JOY_YAXIS) {
#ifndef JOY_INVERT_Y
axis = -axis;
@@ -468,5 +460,4 @@ bool GP2XSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
return false;
}
-
#endif
diff --git a/backends/events/gp2xsdl/gp2xsdl-events.h b/backends/events/gp2xsdl/gp2xsdl-events.h
index 8ea533d052..0d74c1bcac 100644
--- a/backends/events/gp2xsdl/gp2xsdl-events.h
+++ b/backends/events/gp2xsdl/gp2xsdl-events.h
@@ -18,9 +18,6 @@
* 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(BACKEND_EVENTS_SDL_GP2X_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
@@ -29,7 +26,7 @@
#include "backends/events/sdl/sdl-events.h"
/**
- * SDL events manager for GP2X and GP2XWIZ
+ * SDL events manager for GP2X
*/
class GP2XSdlEventSource : public SdlEventSource {
public:
diff --git a/backends/platform/gph/gph-events.cpp b/backends/events/gph/gph-events.cpp
index 2a6237c794..d2b3483f84 100644
--- a/backends/platform/gph/gph-events.cpp
+++ b/backends/events/gph/gph-events.cpp
@@ -18,19 +18,19 @@
* 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$
- *
*/
+#include "common/scummsys.h"
+
/*
* GPH: Device Specific Event Handling.
- *
*/
-#include "backends/platform/gph/gph-sdl.h"
+#if defined(GPH_DEVICE)
+
+#include "backends/events/gph/gph-events.h"
+#include "backends/graphics/gph/gph-graphics.h"
#include "backends/platform/gph/gph-hw.h"
-#include "graphics/scaler/aspect.h"
#include "common/util.h"
#include "common/events.h"
@@ -78,7 +78,9 @@ int BUTTON_STATE_L = false;
BUTTON_SELECT = 62
};
-#else
+#endif
+
+#if defined(GP2XWIZ)
/* Wiz: Main Joystick Mappings */
enum {
@@ -115,6 +117,42 @@ int BUTTON_STATE_L = false;
#endif
+#if defined(GP2X)
+
+enum {
+ /* DPAD/Stick */
+ BUTTON_UP = 0,
+ BUTTON_UPLEFT = 1,
+ BUTTON_LEFT = 2,
+ BUTTON_DOWNLEFT = 3,
+ BUTTON_DOWN = 4,
+ BUTTON_DOWNRIGHT = 5,
+ BUTTON_RIGHT = 6,
+ BUTTON_UPRIGHT = 7,
+ /* Joystick Buttons */
+ BUTTON_MENU = 8, // Start on F100 GP2X
+ BUTTON_SELECT = 9,
+ BUTTON_L = 10,
+ BUTTON_R = 11,
+ BUTTON_A = 12,
+ BUTTON_B = 13,
+ BUTTON_X = 14,
+ BUTTON_Y = 15,
+ BUTTON_VOLUP = 16,
+ BUTTON_VOLDOWN = 17,
+ BUTTON_CLICK = 18
+};
+
+enum {
+ /* Unused Joystick Buttons on the GP2X */
+ BUTTON_HOME = 51,
+ BUTTON_HOLD = 52,
+ BUTTON_HELP = 53,
+ BUTTON_HELP2 = 54
+};
+
+#endif
+
enum {
/* Touchscreen TapMode */
TAPMODE_LEFT = 0,
@@ -122,48 +160,34 @@ enum {
TAPMODE_HOVER = 2
};
-static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
- if (key >= SDLK_F1 && key <= SDLK_F9) {
- return key - SDLK_F1 + Common::ASCII_F1;
- } else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
- return key - SDLK_KP0 + '0';
- } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
- return key;
- } else if (unicode) {
- return unicode;
- } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {
- return key & ~0x20;
- } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
- return 0;
- }
- return key;
-}
-
-
-void OSystem_GPH::fillMouseEvent(Common::Event &event, int x, int y) {
- if (_videoMode.mode == GFX_HALF && !_overlayVisible){
- event.mouse.x = x*2;
- event.mouse.y = y*2;
- } else {
- event.mouse.x = x;
- event.mouse.y = y;
- }
-
- // Update the "keyboard mouse" coords
- _km.x = x;
- _km.y = y;
-
- // Adjust for the screen scaling
- if (!_overlayVisible) {
- event.mouse.x /= _videoMode.scaleFactor;
- event.mouse.y /= _videoMode.scaleFactor;
- if (_videoMode.aspectRatioCorrection)
- event.mouse.y = aspect2Real(event.mouse.y);
- }
+GPHEventSource::GPHEventSource()
+ : _buttonStateL(false){
}
-
-void OSystem_GPH::moveStick() {
+//void GPHEventSource::fillMouseEvent(Common::Event &event, int x, int y) {
+// if (GPHGraphicsManager::_videoMode.mode == GFX_HALF && !GPHGraphicsManager::_overlayVisible){
+// event.mouse.x = x*2;
+// event.mouse.y = y*2;
+// } else {
+// event.mouse.x = x;
+// event.mouse.y = y;
+// }
+//
+// // Update the "keyboard mouse" coords
+// _km.x = x;
+// _km.y = y;
+//
+// // Adjust for the screen scaling
+// if (!_overlayVisible) {
+// event.mouse.x /= _videoMode.scaleFactor;
+// event.mouse.y /= _videoMode.scaleFactor;
+// if (_videoMode.aspectRatioCorrection)
+// event.mouse.y = aspect2Real(event.mouse.y);
+// }
+//}
+
+
+void GPHEventSource::moveStick() {
bool stickBtn[32];
memcpy(stickBtn, _stickBtn, sizeof(stickBtn));
@@ -208,7 +232,7 @@ void OSystem_GPH::moveStick() {
/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */
-bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONDOWN;
@@ -241,7 +265,7 @@ bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
return true;
}
-bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONUP;
@@ -270,7 +294,7 @@ bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
/* Custom handleJoyButtonDown/handleJoyButtonUp to deal with the joystick buttons on GPH devices */
-bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
_stickBtn[ev.jbutton.button] = 1;
event.kbd.flags = 0;
@@ -339,11 +363,11 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
if (BUTTON_STATE_L == true) {
GPH::ToggleTapMode();
if (GPH::tapmodeLevel == TAPMODE_LEFT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
} else if (GPH::tapmodeLevel == TAPMODE_RIGHT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
} else if (GPH::tapmodeLevel == TAPMODE_HOVER) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
}
} else {
event.kbd.keycode = Common::KEYCODE_SPACE;
@@ -363,17 +387,17 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
case BUTTON_VOLUP:
WIZ_HW::mixerMoveVolume(2);
if (WIZ_HW::volumeLevel == 100) {
- displayMessageOnOSD("Maximum Volume");
+ g_system->displayMessageOnOSD("Maximum Volume");
} else {
- displayMessageOnOSD("Increasing Volume");
+ g_system->displayMessageOnOSD("Increasing Volume");
}
break;
case BUTTON_VOLDOWN:
WIZ_HW::mixerMoveVolume(1);
if (WIZ_HW::volumeLevel == 0) {
- displayMessageOnOSD("Minimal Volume");
+ g_system->displayMessageOnOSD("Minimal Volume");
} else {
- displayMessageOnOSD("Decreasing Volume");
+ g_system->displayMessageOnOSD("Decreasing Volume");
}
break;
case BUTTON_HOLD:
@@ -382,18 +406,18 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
case BUTTON_HELP2:
GPH::ToggleTapMode();
if (GPH::tapmodeLevel == TAPMODE_LEFT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click");
} else if (GPH::tapmodeLevel == TAPMODE_RIGHT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click");
} else if (GPH::tapmodeLevel == TAPMODE_HOVER) {
- displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)");
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)");
}
break;
}
return true;
}
-bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
+bool GPHEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
_stickBtn[ev.jbutton.button] = 0;
event.kbd.flags = 0;
@@ -476,6 +500,8 @@ bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
return true;
}
-bool OSystem_GPH::remapKey(SDL_Event &ev,Common::Event &event) {
+bool GPHEventSource::remapKey(SDL_Event &ev,Common::Event &event) {
return false;
}
+
+#endif
diff --git a/backends/events/gph/gph-events.h b/backends/events/gph/gph-events.h
new file mode 100644
index 0000000000..7672bffed2
--- /dev/null
+++ b/backends/events/gph/gph-events.h
@@ -0,0 +1,56 @@
+/* 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.
+ *
+ */
+
+#if !defined(BACKEND_EVENTS_GPH_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_GPH_H
+
+#include "backends/events/sdl/sdl-events.h"
+
+/*
+ * SDL Events manager for GPH devices.
+ */
+
+class GPHEventSource : public SdlEventSource {
+public:
+ GPHEventSource();
+
+protected:
+ bool _stickBtn[32];
+
+ /**
+ * Button state for L button modifier
+ */
+ bool _buttonStateL;
+
+ /**
+ * Handles the stick movement
+ */
+ void moveStick();
+
+ bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
+ bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
+ bool remapKey(SDL_Event &ev, Common::Event &event);
+};
+
+#endif /* BACKEND_EVENTS_GPH_H */
diff --git a/backends/platform/openpandora/op-events.cpp b/backends/events/openpandora/op-events.cpp
index 24283aa8ba..381cbf89e9 100644
--- a/backends/platform/openpandora/op-events.cpp
+++ b/backends/events/openpandora/op-events.cpp
@@ -18,16 +18,19 @@
* 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$
- *
*/
+#include "common/scummsys.h"
+
/*
* OpenPandora: Device Specific Event Handling.
*
*/
+#if defined(OPENPANDORA)
+
+#include "backends/events/openpandora/op-events.h"
+#include "backends/graphics/openpandora/op-graphics.h"
#include "backends/platform/openpandora/op-sdl.h"
#include "backends/platform/openpandora/op-options.h"
@@ -41,81 +44,87 @@ enum {
TAPMODE_HOVER = 2
};
+OPEventSource::OPEventSource()
+ : _buttonStateL(false){
+}
+
/* On the OpenPandora by default the ABXY and L/R Trigger buttons are returned by SDL as
(A): SDLK_HOME (B): SDLK_END (X): SDLK_PAGEDOWN (Y): SDLK_PAGEUP (L): SDLK_RSHIFT (R): SDLK_RCTRL
*/
-bool OSystem_OP::handleKeyDown(SDL_Event &ev, Common::Event &event) {
- switch (ev.key.keysym.sym) {
- case SDLK_HOME:
- event.type = Common::EVENT_LBUTTONDOWN;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_END:
- event.type = Common::EVENT_RBUTTONDOWN;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_PAGEDOWN:
- event.type = Common::EVENT_MAINMENU;
- return true;
- break;
- case SDLK_PAGEUP:
- OP::ToggleTapMode();
- if (OP::tapmodeLevel == TAPMODE_LEFT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
- } else if (OP::tapmodeLevel == TAPMODE_RIGHT) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
- } else if (OP::tapmodeLevel == TAPMODE_HOVER) {
- displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
- }
- break;
- case SDLK_RSHIFT:
- BUTTON_STATE_L = true;
- break;
- case SDLK_RCTRL:
- break;
- default:
- return OSystem_SDL::handleKeyDown(ev, event);
- break;
- }
- return false;
-}
+bool OPEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
-bool OSystem_OP::handleKeyUp(SDL_Event &ev, Common::Event &event) {
- switch (ev.key.keysym.sym) {
- case SDLK_HOME:
- event.type = Common::EVENT_LBUTTONUP;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_END:
- event.type = Common::EVENT_RBUTTONUP;
- fillMouseEvent(event, _km.x, _km.y);
- return true;
- break;
- case SDLK_PAGEDOWN:
- event.type = Common::EVENT_MAINMENU;
- return true;
- break;
- case SDLK_PAGEUP:
- break;
- case SDLK_RSHIFT:
- BUTTON_STATE_L = false;
- break;
- case SDLK_RCTRL:
- break;
- default:
- return OSystem_SDL::handleKeyUp(ev, event);
- break;
+ if (ev.type == SDL_KEYDOWN) {
+ switch (ev.key.keysym.sym) {
+ case SDLK_HOME:
+ event.type = Common::EVENT_LBUTTONDOWN;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_END:
+ event.type = Common::EVENT_RBUTTONDOWN;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_PAGEDOWN:
+ event.type = Common::EVENT_MAINMENU;
+ return true;
+ break;
+ case SDLK_PAGEUP:
+ OP::ToggleTapMode();
+ if (OP::tapmodeLevel == TAPMODE_LEFT) {
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click");
+ } else if (OP::tapmodeLevel == TAPMODE_RIGHT) {
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click");
+ } else if (OP::tapmodeLevel == TAPMODE_HOVER) {
+ g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)");
+ }
+ break;
+ case SDLK_RSHIFT:
+ BUTTON_STATE_L = true;
+ break;
+ case SDLK_RCTRL:
+ break;
+ default:
+ return false;
+ break;
+ }
+ return false;
+ } else {
+ switch (ev.key.keysym.sym) {
+ case SDLK_HOME:
+ event.type = Common::EVENT_LBUTTONUP;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_END:
+ event.type = Common::EVENT_RBUTTONUP;
+ fillMouseEvent(event, _km.x, _km.y);
+ return true;
+ break;
+ case SDLK_PAGEDOWN:
+ event.type = Common::EVENT_MAINMENU;
+ return true;
+ break;
+ case SDLK_PAGEUP:
+ break;
+ case SDLK_RSHIFT:
+ BUTTON_STATE_L = false;
+ break;
+ case SDLK_RCTRL:
+ break;
+ default:
+ return false;
+ break;
+ }
+ return false;
}
return false;
}
/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */
-bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
+bool OPEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONDOWN;
@@ -148,7 +157,7 @@ bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
return true;
}
-bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
+bool OPEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT){
if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */
event.type = Common::EVENT_RBUTTONUP;
@@ -174,3 +183,4 @@ bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
return true;
}
+#endif
diff --git a/backends/events/openpandora/op-events.h b/backends/events/openpandora/op-events.h
new file mode 100644
index 0000000000..9aa637992a
--- /dev/null
+++ b/backends/events/openpandora/op-events.h
@@ -0,0 +1,44 @@
+/* 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.
+ *
+ */
+
+#if !defined(BACKEND_EVENTS_OP_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_OP_H
+
+#include "backends/events/sdl/sdl-events.h"
+
+/**
+ * Events manager for the OpenPandora.
+ */
+class OPEventSource : public SdlEventSource {
+public:
+ OPEventSource();
+
+protected:
+ /** Button state for L button modifier */
+ bool _buttonStateL;
+
+ bool remapKey(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
+ bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
+};
+
+#endif /* BACKEND_EVENTS_OP_H */
diff --git a/backends/events/webossdl/webossdl-events.cpp b/backends/events/webossdl/webossdl-events.cpp
new file mode 100644
index 0000000000..fd9628995d
--- /dev/null
+++ b/backends/events/webossdl/webossdl-events.cpp
@@ -0,0 +1,241 @@
+/* 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$
+ *
+ */
+
+#ifdef WEBOS
+
+#include "common/scummsys.h"
+#include "sys/time.h"
+#include "time.h"
+
+#include "backends/events/webossdl/webossdl-events.h"
+#include "gui/message.h"
+
+// Inidicates if gesture area is pressed down or not.
+static bool gestureDown = false;
+
+// The timestamp when gesture area was pressed down.
+static int gestureDownTime = 0;
+
+// The timestamp when screen was pressed down.
+static int screenDownTime = 0;
+
+// The timestamp when a possible drag operation was triggered.
+static int dragStartTime = 0;
+
+// The index of the motion pointer.
+static int motionPtrIndex = -1;
+
+// The maximum horizontal motion during dragging (For tap recognition).
+static int dragDiffX = 0;
+
+// The maximum vertical motion during dragging (For tap recognition).
+static int dragDiffY = 0;
+
+// Indicates if we are in drag mode.
+static bool dragging = false;
+
+// The current mouse position on the screen.
+static int curX = 0, curY = 0;
+
+// The time (seconds after 1/1/1970) when program started.
+static time_t programStartTime = time(0);
+
+/**
+ * Returns the number of passed milliseconds since program start.
+ *
+ * @return The number of passed milliseconds.
+ */
+static time_t getMillis()
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (time(0) - programStartTime) * 1000 + tv.tv_usec / 1000;
+}
+
+/**
+ * WebOS devices only have a Shift key and a CTRL key. There is also an Alt
+ * key (the orange key) but this is already processed by WebOS to change the
+ * mode of the keys so ScummVM must not use this key as a modifier. Instead
+ * pressing down the gesture area is used as Alt key.
+ *
+ * @param mod The pressed key modifier as detected by SDL.
+ * @param event The ScummVM event to setup.
+ */
+void WebOSSdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod,
+ Common::Event &event) {
+ event.kbd.flags = 0;
+
+ if (mod & KMOD_SHIFT)
+ event.kbd.flags |= Common::KBD_SHIFT;
+ if (mod & KMOD_CTRL)
+ event.kbd.flags |= Common::KBD_CTRL;
+ if (gestureDown)
+ event.kbd.flags |= Common::KBD_ALT;
+}
+
+/**
+ * Before calling the original SDL implementation this method checks if the
+ * gesture area is pressed down.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
+ // Handle gesture area tap.
+ if (ev.key.keysym.sym == SDLK_WORLD_71) {
+ gestureDown = true;
+ gestureDownTime = getMillis();
+ return true;
+ }
+
+ // Call original SDL key handler.
+ return SdlEventSource::handleKeyDown(ev, event);
+}
+
+/**
+ * Before calling the original SDL implementation this method checks if the
+ * gesture area has been released.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
+ // Handle gesture area tap.
+ if (ev.key.keysym.sym == SDLK_WORLD_71) {
+ gestureDown = false;
+ return true;
+ }
+
+ // Call original SDL key handler.
+ return SdlEventSource::handleKeyUp(ev, event);
+}
+
+/**
+ * Handles mouse button press.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
+ if (motionPtrIndex == -1) {
+ motionPtrIndex = ev.button.which;
+ dragDiffX = 0;
+ dragDiffY = 0;
+ screenDownTime = getMillis();
+
+ // Start dragging when pressing the screen shortly after a tap.
+ if (getMillis() - dragStartTime < 250) {
+ dragging = true;
+ event.type = Common::EVENT_LBUTTONDOWN;
+ fillMouseEvent(event, curX, curY);
+ }
+ }
+ return true;
+}
+
+/**
+ * Handles mouse button release.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
+ if (motionPtrIndex == ev.button.which) {
+ motionPtrIndex = -1;
+
+ // When drag mode was active then simply send a mouse up event
+ if (dragging)
+ {
+ event.type = Common::EVENT_LBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ dragging = false;
+ return true;
+ }
+
+ // When mouse was moved 5 pixels or less then emulate a mouse button
+ // click.
+ if (ABS(dragDiffX) < 6 && ABS(dragDiffY) < 6)
+ {
+ int duration = getMillis() - screenDownTime;
+
+ // When screen was pressed for less than 500ms then emulate a
+ // left mouse click.
+ if (duration < 500) {
+ event.type = Common::EVENT_LBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ g_system->getEventManager()->pushEvent(event);
+ event.type = Common::EVENT_LBUTTONDOWN;
+ dragStartTime = getMillis();
+ }
+
+ // When screen was pressed for less than 1000ms then emulate a
+ // right mouse click.
+ else if (duration < 1000) {
+ event.type = Common::EVENT_RBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ g_system->getEventManager()->pushEvent(event);
+ event.type = Common::EVENT_RBUTTONDOWN;
+ }
+
+ // When screen was pressed for more than 1000ms then emulate a
+ // middle mouse click.
+ else {
+ event.type = Common::EVENT_MBUTTONUP;
+ fillMouseEvent(event, curX, curY);
+ g_system->getEventManager()->pushEvent(event);
+ event.type = Common::EVENT_MBUTTONDOWN;
+ }
+
+ }
+ }
+ return true;
+}
+
+/**
+ * Handles mouse motion.
+ *
+ * @param ev The SDL event
+ * @param event The ScummVM event.
+ * @return True if event was processed, false if not.
+ */
+bool WebOSSdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) {
+ if (ev.motion.which == motionPtrIndex) {
+ int screenX = g_system->getWidth();
+ int screenY = g_system->getHeight();
+ curX = MIN(screenX, MAX(0, curX + ev.motion.xrel));
+ curY = MIN(screenY, MAX(0, curY + ev.motion.yrel));
+ dragDiffX += ev.motion.xrel;
+ dragDiffY += ev.motion.yrel;
+ event.type = Common::EVENT_MOUSEMOVE;
+ fillMouseEvent(event, curX, curY);
+ }
+ return true;
+}
+
+#endif
diff --git a/backends/events/webossdl/webossdl-events.h b/backends/events/webossdl/webossdl-events.h
new file mode 100644
index 0000000000..3a41111cf2
--- /dev/null
+++ b/backends/events/webossdl/webossdl-events.h
@@ -0,0 +1,44 @@
+/* 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(BACKEND_EVENTS_SDL_WEBOS_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_SDL_WEBOS_H
+
+#include "backends/events/sdl/sdl-events.h"
+
+/**
+ * SDL events manager for WebOS
+ */
+class WebOSSdlEventSource : public SdlEventSource {
+protected:
+ virtual void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event);
+ virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event);
+ virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event);
+ virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
+ virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
+ virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event);
+};
+
+#endif
diff --git a/backends/events/wincesdl/wincesdl-events.cpp b/backends/events/wincesdl/wincesdl-events.cpp
new file mode 100644
index 0000000000..2505b0fb31
--- /dev/null
+++ b/backends/events/wincesdl/wincesdl-events.cpp
@@ -0,0 +1,332 @@
+/* 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$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef _WIN32_WCE
+
+#include "common/config-manager.h"
+
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/platform/wince/CEActionsPocket.h"
+#include "backends/platform/wince/CEActionsSmartphone.h"
+#include "backends/platform/wince/CEDevice.h"
+
+#include "backends/platform/sdl/sdl.h"
+
+WINCESdlEventSource::WINCESdlEventSource()
+ : _tapTime(0), _closeClick(false), _rbutton(false),
+ _freeLook(false), _graphicsMan(0) {
+}
+
+void WINCESdlEventSource::init(WINCESdlGraphicsManager *graphicsMan) {
+ assert(graphicsMan);
+ _graphicsMan = graphicsMan;
+}
+
+void WINCESdlEventSource::fillMouseEvent(Common::Event &event, int x, int y) {
+ event.mouse.x = x;
+ event.mouse.y = y;
+
+ // Update the "keyboard mouse" coords
+ _km.x = event.mouse.x;
+ _km.y = event.mouse.y;
+
+ // Adjust for the screen scaling
+ if (_graphicsMan->_zoomDown)
+ event.mouse.y += 240;
+
+ event.mouse.x = event.mouse.x * _graphicsMan->_scaleFactorXd / _graphicsMan->_scaleFactorXm;
+ event.mouse.y = event.mouse.y * _graphicsMan->_scaleFactorYd / _graphicsMan->_scaleFactorYm;
+}
+
+bool WINCESdlEventSource::pollEvent(Common::Event &event) {
+ SDL_Event ev;
+ ev.type = SDL_NOEVENT;
+ DWORD currentTime;
+ bool keyEvent = false;
+ int deltaX, deltaY;
+
+ memset(&event, 0, sizeof(Common::Event));
+
+ handleKbdMouse();
+
+ // If the screen changed, send an Common::EVENT_SCREEN_CHANGED
+ int screenID = _graphicsMan->getScreenChangeID();
+ if (screenID != _lastScreenID) {
+ _lastScreenID = screenID;
+ event.type = Common::EVENT_SCREEN_CHANGED;
+ return true;
+ }
+
+ CEDevice::wakeUp();
+
+ currentTime = GetTickCount();
+
+ while (SDL_PollEvent(&ev)) {
+ switch (ev.type) {
+ case SDL_KEYDOWN:
+ debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
+ // KMOD_RESERVED is used if the key has been injected by an external buffer
+ if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) {
+ keyEvent = true;
+ _graphicsMan->_lastKeyPressed = ev.key.keysym.sym;
+ _graphicsMan->_keyRepeatTime = currentTime;
+ _graphicsMan->_keyRepeat = 0;
+
+ if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true))
+ return true;
+ }
+
+ if (GUI_Actions::Instance()->mappingActive())
+ event.kbd.flags = 0xFF;
+ else if (ev.key.keysym.sym == SDLK_PAUSE) {
+ _graphicsMan->_lastKeyPressed = 0;
+ event.type = Common::EVENT_PREDICTIVE_DIALOG;
+ return true;
+ }
+ event.type = Common::EVENT_KEYDOWN;
+ if (!GUI::Actions::Instance()->mappingActive())
+ event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
+ else
+ event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+ event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+
+ if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
+ event.kbd.ascii ^= 0x20;
+ event.kbd.flags = Common::KBD_SHIFT;
+ }
+
+ return true;
+
+ case SDL_KEYUP:
+ debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
+ // KMOD_RESERVED is used if the key has been injected by an external buffer
+ if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) {
+ keyEvent = true;
+ _graphicsMan->_lastKeyPressed = 0;
+
+ if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false))
+ return true;
+ }
+
+ if (GUI_Actions::Instance()->mappingActive())
+ event.kbd.flags = 0xFF;
+ else if (ev.key.keysym.sym == SDLK_PAUSE) {
+ _graphicsMan->_lastKeyPressed = 0;
+ return false; // chew up the show agi dialog key up event
+ }
+
+ event.type = Common::EVENT_KEYUP;
+ if (!GUI::Actions::Instance()->mappingActive())
+ event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
+ else
+ event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+ event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive());
+
+ if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
+ event.kbd.ascii ^= 0x20;
+ event.kbd.flags = Common::KBD_SHIFT;
+ }
+
+ return true;
+
+ case SDL_MOUSEMOTION:
+ event.type = Common::EVENT_MOUSEMOVE;
+ fillMouseEvent(event, ev.motion.x, ev.motion.y);
+ _graphicsMan->setMousePos(event.mouse.x, event.mouse.y);
+
+ return true;
+
+ case SDL_MOUSEBUTTONDOWN:
+ if (ev.button.button == SDL_BUTTON_LEFT)
+ event.type = Common::EVENT_LBUTTONDOWN;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ event.type = Common::EVENT_RBUTTONDOWN;
+ else
+ break;
+ fillMouseEvent(event, ev.button.x, ev.button.y);
+
+
+ if (event.mouse.x > _tapX)
+ deltaX = event.mouse.x - _tapX;
+ else
+ deltaX = _tapX - event.mouse.x;
+ if (event.mouse.y > _tapY)
+ deltaY = event.mouse.y - _tapY;
+ else
+ deltaY = _tapY - event.mouse.y;
+ _closeClick = (deltaX <= 5 && deltaY <= 5);
+
+ if (!_isSmartphone) {
+ // handle double-taps
+ if (_tapTime) { // second tap
+ if (_closeClick && (GetTickCount() - _tapTime < 1000)) {
+ if (event.mouse.y <= 20 &&
+ _graphicsMan->_panelInitialized) {
+ // top of screen (show panel)
+ _graphicsMan->swap_panel_visibility();
+ } else if (!_graphicsMan->_noDoubleTapRMB) {
+ // right click
+ event.type = Common::EVENT_RBUTTONDOWN;
+ _rbutton = true;
+ }
+ }
+ _tapTime = 0;
+ } else {
+ _tapTime = GetTickCount();
+ _tapX = event.mouse.x;
+ _tapY = event.mouse.y;
+ }
+ }
+
+ if (_freeLook && !_closeClick) {
+ _rbutton = false;
+ _tapTime = 0;
+ _tapX = event.mouse.x;
+ _tapY = event.mouse.y;
+ event.type = Common::EVENT_MOUSEMOVE;
+ _graphicsMan->setMousePos(event.mouse.x, event.mouse.y);
+ }
+
+
+ if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) {
+ if (!_graphicsMan->_toolbarHandler.drawn()) {
+ _graphicsMan->_toolbarHighDrawn = false;
+ _graphicsMan->internUpdateScreen();
+ }
+ if (_graphicsMan->_newOrientation != _graphicsMan->_orientationLandscape) {
+ _graphicsMan->_orientationLandscape = _graphicsMan->_newOrientation;
+ _graphicsMan->_toolbarHighDrawn = false;
+ ConfMan.setInt("landscape", _graphicsMan->_orientationLandscape);
+ ConfMan.flushToDisk();
+ _graphicsMan->hotswapGFXMode();
+ }
+ return false;
+ }
+
+ return true;
+
+ case SDL_MOUSEBUTTONUP:
+ if (ev.button.button == SDL_BUTTON_LEFT)
+ event.type = Common::EVENT_LBUTTONUP;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ event.type = Common::EVENT_RBUTTONUP;
+ else
+ break;
+
+ if (_rbutton) {
+ event.type = Common::EVENT_RBUTTONUP;
+ _rbutton = false;
+ }
+
+ fillMouseEvent(event, ev.button.x, ev.button.y);
+
+ if (_freeLook && !_closeClick) {
+ _tapX = event.mouse.x;
+ _tapY = event.mouse.y;
+ event.type = Common::EVENT_MOUSEMOVE;
+ _graphicsMan->setMousePos(event.mouse.x, event.mouse.y);
+ }
+
+ if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) {
+ if (!_graphicsMan->_toolbarHandler.drawn()) {
+ _graphicsMan->_toolbarHighDrawn = false;
+ _graphicsMan->internUpdateScreen();
+ }
+ return false;
+
+ }
+ return true;
+
+ case SDL_VIDEOEXPOSE:
+ // HACK: Send a fake event, handled by SdlGraphicsManager
+ event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose;
+ break;
+
+ case SDL_QUIT:
+ event.type = Common::EVENT_QUIT;
+ return true;
+
+ case SDL_ACTIVEEVENT:
+ if (ev.active.state & SDL_APPMOUSEFOCUS)
+ debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost");
+ if (ev.active.state & SDL_APPINPUTFOCUS)
+ debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost");
+ if (ev.active.state & SDL_APPACTIVE)
+ debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost");
+ if (ev.active.state & SDL_APPINPUTFOCUS) {
+ _graphicsMan->_hasfocus = ev.active.gain;
+ SDL_PauseAudio(!_graphicsMan->_hasfocus);
+ if (_graphicsMan->_hasfocus) {
+ event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose;
+ }
+ }
+ break;
+ }
+ }
+
+ // Simulate repeated key for backend
+ if (!keyEvent && _graphicsMan->_lastKeyPressed && (int)currentTime > _graphicsMan->_keyRepeatTime + _graphicsMan->_keyRepeatTrigger) {
+ _graphicsMan->_keyRepeatTime = currentTime;
+ _graphicsMan->_keyRepeat++;
+ GUI_Actions::Instance()->performMapped(_graphicsMan->_lastKeyPressed, true);
+ }
+
+ return false;
+}
+
+int WINCESdlEventSource::mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) {
+ if (GUI::Actions::Instance()->mappingActive())
+ return key;
+
+ if (unfilter) {
+ switch (key) {
+ case SDLK_ESCAPE:
+ return SDLK_BACKSPACE;
+ case SDLK_F8:
+ return SDLK_ASTERISK;
+ case SDLK_F9:
+ return SDLK_HASH;
+ default:
+ return key;
+ }
+ }
+
+ if (key >= SDLK_KP0 && key <= SDLK_KP9) {
+ return key - SDLK_KP0 + '0';
+ } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
+ return key;
+ } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
+ return 0;
+ }
+ return key;
+}
+
+void WINCESdlEventSource::swap_freeLook() {
+ _freeLook = !_freeLook;
+}
+
+#endif /* _WIN32_WCE */
diff --git a/backends/events/wincesdl/wincesdl-events.h b/backends/events/wincesdl/wincesdl-events.h
new file mode 100644
index 0000000000..f5b1026c46
--- /dev/null
+++ b/backends/events/wincesdl/wincesdl-events.h
@@ -0,0 +1,73 @@
+/* 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 BACKENDS_EVENTS_SDL_WINCE_H
+#define BACKENDS_EVENTS_SDL_WINCE_H
+
+#include "common/scummsys.h"
+
+#ifdef _WIN32_WCE
+
+#include "backends/events/sdl/sdl-events.h"
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+
+extern bool _isSmartphone;
+
+class WINCESdlEventSource : public SdlEventSource {
+public:
+ WINCESdlEventSource();
+
+ void init(WINCESdlGraphicsManager *graphicsMan);
+
+ void loadDeviceConfiguration();
+
+ // Overloaded from SDL backend (toolbar handling)
+ bool pollEvent(Common::Event &event);
+ // Overloaded from SDL backend (mouse and new scaler handling)
+ void fillMouseEvent(Common::Event &event, int x, int y);
+
+ void swap_freeLook();
+
+protected:
+
+private:
+ int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter);
+
+ WINCESdlGraphicsManager *_graphicsMan;
+
+ // Keyboard tap
+ int _tapX;
+ int _tapY;
+ long _tapTime;
+
+ bool _closeClick; // flag when taps are spatially close together
+ bool _rbutton; // double tap -> right button simulation
+ bool _freeLook; // freeLook mode (do not send mouse button events)
+
+};
+
+#endif
+
+#endif /* BACKENDS_EVENTS_SDL_WINCE_H */
diff --git a/backends/graphics/default-palette.h b/backends/graphics/default-palette.h
index 6e3a75350e..12436aae51 100644
--- a/backends/graphics/default-palette.h
+++ b/backends/graphics/default-palette.h
@@ -38,7 +38,7 @@
*/
class DefaultPaletteManager : public PaletteManager {
protected:
- byte _palette[4 * 256];
+ byte _palette[3 * 256];
/**
* Subclasses should only implement this method and none of the others.
@@ -51,12 +51,12 @@ protected:
public:
void setPalette(const byte *colors, uint start, uint num) {
assert(start + num <= 256);
- memcpy(_palette + 4 * start, colors, 4 * num);
+ memcpy(_palette + 3 * start, colors, 3 * num);
setPaletteIntern(colors, start, num);
}
void grabPalette(byte *colors, uint start, uint num) {
assert(start + num <= 256);
- memcpy(colors, _palette + 4 * start, 4 * num);
+ memcpy(colors, _palette + 3 * start, 3 * num);
}
};
diff --git a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp
index 75a1f17674..6e5a35a1b1 100644
--- a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp
+++ b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp
@@ -18,14 +18,11 @@
* 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$
- *
*/
#include "common/scummsys.h"
-#ifdef GP2X
+#if defined(GP2X_OLD)
#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
#include "graphics/scaler/aspect.h"
diff --git a/backends/platform/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp
index 8fada7e40a..4f2185ef4b 100644
--- a/backends/platform/gph/gph-graphics.cpp
+++ b/backends/graphics/gph/gph-graphics.cpp
@@ -18,35 +18,35 @@
* 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$
- *
*/
-#include "backends/platform/gph/gph-sdl.h"
+#include "common/scummsys.h"
-#include "common/mutex.h"
-#include "graphics/font.h"
-#include "graphics/fontman.h"
-#include "graphics/scaler.h"
+#if defined(GPH_DEVICE)
+
+#include "backends/graphics/gph/gph-graphics.h"
+#include "backends/events/gph/gph-events.h"
#include "graphics/scaler/aspect.h"
-#include "graphics/scaler/downscaler.h"
-#include "graphics/surface.h"
+#include "common/mutex.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- {"1x", "Fullscreen", GFX_NORMAL},
+ {"1x", "Standard", GFX_NORMAL},
{0, 0, 0}
};
-const OSystem::GraphicsMode *OSystem_GPH::getSupportedGraphicsModes() const {
+GPHGraphicsManager::GPHGraphicsManager(SdlEventSource *boss)
+ : SdlGraphicsManager(boss) {
+}
+
+const OSystem::GraphicsMode *GPHGraphicsManager::getSupportedGraphicsModes() const {
return s_supportedGraphicsModes;
}
-int OSystem_GPH::getDefaultGraphicsMode() const {
+int GPHGraphicsManager::getDefaultGraphicsMode() const {
return GFX_NORMAL;
}
-bool OSystem_GPH::setGraphicsMode(int mode) {
+bool GPHGraphicsManager::setGraphicsMode(int mode) {
Common::StackLock lock(_graphicsMutex);
assert(_transactionMode == kTransactionActive);
@@ -80,7 +80,7 @@ bool OSystem_GPH::setGraphicsMode(int mode) {
return true;
}
-void OSystem_GPH::setGraphicsModeIntern() {
+void GPHGraphicsManager::setGraphicsModeIntern() {
Common::StackLock lock(_graphicsMutex);
ScalerProc *newScalerProc = 0;
@@ -109,7 +109,7 @@ void OSystem_GPH::setGraphicsModeIntern() {
blitCursor();
}
-void OSystem_GPH::initSize(uint w, uint h) {
+void GPHGraphicsManager::initSize(uint w, uint h) {
assert(_transactionMode == kTransactionActive);
// Avoid redundant res changes
@@ -121,41 +121,13 @@ void OSystem_GPH::initSize(uint w, uint h) {
if (w > 320 || h > 240){
setGraphicsMode(GFX_HALF);
setGraphicsModeIntern();
- toggleMouseGrab();
+ _sdlEventSource->toggleMouseGrab();
}
_transactionDetails.sizeChanged = true;
}
-bool OSystem_GPH::loadGFXMode() {
- if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) {
- _videoMode.aspectRatioCorrection = false;
- setGraphicsMode(GFX_HALF);
- printf("GFX_HALF\n");
- } else {
- setGraphicsMode(GFX_NORMAL);
- printf("GFX_NORMAL\n");
- }
-
- if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) {
- _videoMode.overlayWidth = _videoMode.screenWidth / 2;
- _videoMode.overlayHeight = _videoMode.screenHeight / 2;
- _videoMode.fullscreen = true;
- } else {
-
- _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
-
- if (_videoMode.aspectRatioCorrection)
- _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
-
- _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.hardwareHeight = effectiveScreenHeight();
- }
- return OSystem_SDL::loadGFXMode();
-}
-
-void OSystem_GPH::drawMouse() {
+void GPHGraphicsManager::drawMouse() {
if (!_mouseVisible || !_mouseSurface) {
_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
return;
@@ -226,7 +198,7 @@ void OSystem_GPH::drawMouse() {
addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);
}
-void OSystem_GPH::undrawMouse() {
+void GPHGraphicsManager::undrawMouse() {
const int x = _mouseBackup.x;
const int y = _mouseBackup.y;
@@ -244,7 +216,7 @@ void OSystem_GPH::undrawMouse() {
}
}
-void OSystem_GPH::internUpdateScreen() {
+void GPHGraphicsManager::internUpdateScreen() {
SDL_Surface *srcSurf, *origSurf;
int height, width;
ScalerProc *scalerProc;
@@ -443,28 +415,124 @@ void OSystem_GPH::internUpdateScreen() {
_mouseNeedsRedraw = false;
}
-void OSystem_GPH::showOverlay() {
+void GPHGraphicsManager::showOverlay() {
if (_videoMode.mode == GFX_HALF){
_mouseCurState.x = _mouseCurState.x / 2;
_mouseCurState.y = _mouseCurState.y / 2;
}
- OSystem_SDL::showOverlay();
+ SdlGraphicsManager::showOverlay();
}
-void OSystem_GPH::hideOverlay() {
+void GPHGraphicsManager::hideOverlay() {
if (_videoMode.mode == GFX_HALF){
_mouseCurState.x = _mouseCurState.x * 2;
_mouseCurState.y = _mouseCurState.y * 2;
}
- OSystem_SDL::hideOverlay();
+ SdlGraphicsManager::hideOverlay();
}
-void OSystem_GPH::warpMouse(int x, int y) {
+
+bool GPHGraphicsManager::loadGFXMode() {
+
+ /* Forcefully disable aspect ratio correction for games
+ that start with a native 240px height resolution
+ This corrects games with non-standard resolutions
+ such as MM Nes (256x240).
+ */
+
+ if(_videoMode.screenHeight == 240) {
+ _videoMode.aspectRatioCorrection = false;
+ }
+
+ fprintf(stdout, "Game ScreenMode = %d*%d\n", _videoMode.screenWidth, _videoMode.screenHeight);
+ if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) {
+ _videoMode.aspectRatioCorrection = false;
+ setGraphicsMode(GFX_HALF);
+ fprintf(stdout, "GraphicsMode set to HALF\n");
+ } else {
+ setGraphicsMode(GFX_NORMAL);
+ fprintf(stdout, "GraphicsMode set to NORMAL\n");
+ }
+
+ if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) {
+ _videoMode.overlayWidth = _videoMode.screenWidth / 2;
+ _videoMode.overlayHeight = _videoMode.screenHeight / 2;
+ _videoMode.fullscreen = true;
+ } else {
+
+ _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+
+ if (_videoMode.aspectRatioCorrection)
+ _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
+
+ _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ _videoMode.hardwareHeight = effectiveScreenHeight();
+ }
+ return SdlGraphicsManager::loadGFXMode();
+}
+
+bool GPHGraphicsManager::hasFeature(OSystem::Feature f) {
+ return
+ (f == OSystem::kFeatureAspectRatioCorrection) ||
+ (f == OSystem::kFeatureCursorHasPalette);
+}
+
+void GPHGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ switch (f) {
+ case OSystem::kFeatureAspectRatioCorrection:
+ setAspectRatioCorrection(enable);
+ break;
+ default:
+ break;
+ }
+}
+
+bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) {
+ assert(_transactionMode == kTransactionNone);
+
+ switch (f) {
+ case OSystem::kFeatureAspectRatioCorrection:
+ return _videoMode.aspectRatioCorrection;
+ default:
+ return false;
+ }
+}
+
+SdlGraphicsManager::MousePos* GPHGraphicsManager::getMouseCurState() {
+ return &_mouseCurState;
+}
+
+SdlGraphicsManager::VideoState* GPHGraphicsManager::getVideoMode() {
+ return &_videoMode;
+}
+
+void GPHGraphicsManager::warpMouse(int x, int y) {
if (_mouseCurState.x != x || _mouseCurState.y != y) {
if (_videoMode.mode == GFX_HALF && !_overlayVisible){
x = x / 2;
y = y / 2;
}
}
- OSystem_SDL::warpMouse(x, y);
+ SdlGraphicsManager::warpMouse(x, y);
+}
+
+void GPHGraphicsManager::adjustMouseEvent(const Common::Event &event) {
+ if (!event.synthetic) {
+ Common::Event newEvent(event);
+ newEvent.synthetic = true;
+ if (!_overlayVisible) {
+ if (_videoMode.mode == GFX_HALF) {
+ newEvent.mouse.x *= 2;
+ newEvent.mouse.y *= 2;
+ }
+ newEvent.mouse.x /= _videoMode.scaleFactor;
+ newEvent.mouse.y /= _videoMode.scaleFactor;
+ if (_videoMode.aspectRatioCorrection)
+ newEvent.mouse.y = aspect2Real(newEvent.mouse.y);
+ }
+ g_system->getEventManager()->pushEvent(newEvent);
+ }
}
+
+#endif
diff --git a/backends/graphics/gph/gph-graphics.h b/backends/graphics/gph/gph-graphics.h
new file mode 100644
index 0000000000..6ba2b344a6
--- /dev/null
+++ b/backends/graphics/gph/gph-graphics.h
@@ -0,0 +1,62 @@
+/* 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.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_GPH_H
+#define BACKENDS_GRAPHICS_GPH_H
+
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "graphics/scaler/aspect.h" // for aspect2Real
+#include "graphics/scaler/downscaler.h"
+
+enum {
+ GFX_HALF = 12
+};
+
+class GPHGraphicsManager : public SdlGraphicsManager {
+public:
+ GPHGraphicsManager(SdlEventSource *boss);
+
+ bool hasFeature(OSystem::Feature f);
+ void setFeatureState(OSystem::Feature f, bool enable);
+ bool getFeatureState(OSystem::Feature f);
+ int getDefaultGraphicsMode() const;
+
+ void initSize(uint w, uint h);
+ const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ bool setGraphicsMode(const char *name);
+ bool setGraphicsMode(int mode);
+ void setGraphicsModeIntern();
+ void internUpdateScreen();
+ void showOverlay();
+ void hideOverlay();
+ bool loadGFXMode();
+ void drawMouse();
+ void undrawMouse();
+ virtual void warpMouse(int x, int y);
+
+ SdlGraphicsManager::MousePos *getMouseCurState();
+ SdlGraphicsManager::VideoState *getVideoMode();
+
+ virtual void adjustMouseEvent(const Common::Event &event);
+};
+
+#endif /* BACKENDS_GRAPHICS_GPH_H */
diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp
index cd9e23cb71..7b7d40f174 100644
--- a/backends/graphics/opengl/gltexture.cpp
+++ b/backends/graphics/opengl/gltexture.cpp
@@ -149,7 +149,7 @@ void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLu
glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
// Check if the buffer has its data contiguously
- if (static_cast<int>(w) * _bytesPerPixel == pitch && w == _textureWidth) {
+ if (static_cast<int>(w) * _bytesPerPixel == pitch) {
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
_glFormat, _glType, buf); CHECK_GL_ERROR();
} else {
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index cee80f9dc0..4ac2747d25 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -33,6 +33,9 @@
#include "common/file.h"
#include "common/mutex.h"
#include "common/translation.h"
+#ifdef USE_OSD
+#include "common/tokenizer.h"
+#endif
#include "graphics/font.h"
#include "graphics/fontman.h"
@@ -50,8 +53,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
_cursorVisible(false), _cursorKeyColor(0),
_cursorTargetScale(1),
_formatBGR(false),
- _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0),
- _aspectRatioCorrection(false) {
+ _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0) {
memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
memset(&_videoMode, 0, sizeof(_videoMode));
@@ -62,8 +64,8 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
_videoMode.fullscreen = ConfMan.getBool("fullscreen");
_videoMode.antialiasing = false;
- _gamePalette = (byte *)calloc(sizeof(byte) * 4, 256);
- _cursorPalette = (byte *)calloc(sizeof(byte) * 4, 256);
+ _gamePalette = (byte *)calloc(sizeof(byte) * 3, 256);
+ _cursorPalette = (byte *)calloc(sizeof(byte) * 3, 256);
}
OpenGLGraphicsManager::~OpenGLGraphicsManager() {
@@ -96,17 +98,31 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ setFullscreenMode(enable);
+ break;
+
case OSystem::kFeatureAspectRatioCorrection:
- _videoMode.mode = OpenGL::GFX_4_3;
- _aspectRatioCorrection = enable;
+ _videoMode.aspectRatioCorrection = enable;
+ _transactionDetails.needRefresh = true;
break;
+
default:
break;
}
}
bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
- return false;
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return _videoMode.fullscreen;
+
+ case OSystem::kFeatureAspectRatioCorrection:
+ return _videoMode.aspectRatioCorrection;
+
+ default:
+ return false;
+ }
}
//
@@ -116,7 +132,6 @@ bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
{"gl1", _s("OpenGL Normal"), OpenGL::GFX_NORMAL},
{"gl2", _s("OpenGL Conserve"), OpenGL::GFX_CONSERVE},
- {"gl3", _s("OpenGL 4/3"), OpenGL::GFX_4_3},
{"gl4", _s("OpenGL Original"), OpenGL::GFX_ORIGINAL},
{0, 0, 0}
};
@@ -136,17 +151,18 @@ int OpenGLGraphicsManager::getDefaultGraphicsMode() const {
bool OpenGLGraphicsManager::setGraphicsMode(int mode) {
assert(_transactionMode == kTransactionActive);
+ setScale(2);
+
if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
return true;
switch (mode) {
case OpenGL::GFX_NORMAL:
case OpenGL::GFX_CONSERVE:
- case OpenGL::GFX_4_3:
case OpenGL::GFX_ORIGINAL:
break;
default:
- warning("unknown gfx mode %d", mode);
+ warning("Unknown gfx mode %d", mode);
return false;
}
@@ -166,11 +182,9 @@ void OpenGLGraphicsManager::resetGraphicsScale() {
}
#ifdef USE_RGB_COLOR
-
Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const {
return _screenFormat;
}
-
#endif
void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
@@ -308,13 +322,13 @@ int16 OpenGLGraphicsManager::getWidth() {
void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
assert(colors);
-
+
#ifdef USE_RGB_COLOR
assert(_screenFormat.bytesPerPixel == 1);
#endif
// Save the screen palette
- memcpy(_gamePalette + start * 4, colors, num * 4);
+ memcpy(_gamePalette + start * 3, colors, num * 3);
_screenNeedsRedraw = true;
@@ -324,13 +338,13 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
assert(colors);
-
+
#ifdef USE_RGB_COLOR
assert(_screenFormat.bytesPerPixel == 1);
#endif
// Copies current palette to buffer
- memcpy(colors, _gamePalette + start * 4, num * 4);
+ memcpy(colors, _gamePalette + start * 3, num * 3);
}
void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
@@ -341,9 +355,9 @@ void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x,
// Copy buffer data to game screen internal buffer
const byte *src = buf;
- byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch;
+ byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch + x * _screenData.bytesPerPixel;
for (int i = 0; i < h; i++) {
- memcpy(dst + x * _screenData.bytesPerPixel, src, w * _screenData.bytesPerPixel);
+ memcpy(dst, src, w * _screenData.bytesPerPixel);
src += pitch;
dst += _screenData.pitch;
}
@@ -367,6 +381,7 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) {
if (_gameTexture == NULL)
return;
+#ifdef USE_RGB_COLOR
if (_screenFormat.bytesPerPixel == 1) {
memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
} else if (_screenFormat.bytesPerPixel == 2) {
@@ -392,7 +407,9 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) {
pixels[i] = col;
}
}
-
+#else
+ memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
+#endif
_screenNeedsRedraw = true;
}
@@ -537,13 +554,53 @@ bool OpenGLGraphicsManager::showMouse(bool visible) {
return last;
}
-void OpenGLGraphicsManager::setMousePos(int x, int y) {
- _cursorState.x = x;
- _cursorState.y = y;
-}
-
void OpenGLGraphicsManager::warpMouse(int x, int y) {
- setMousePos(x, y);
+ int scaledX = x;
+ int scaledY = y;
+
+ int16 currentX = _cursorState.x;
+ int16 currentY = _cursorState.y;
+
+ adjustMousePosition(currentX, currentY);
+
+ // Do not adjust the real screen position, when the current game / overlay
+ // coordinates match the requested coordinates. This avoids a slight
+ // movement which might occur otherwise when the mouse is at a subpixel
+ // position.
+ if (x == currentX && y == currentY)
+ return;
+
+ if (_videoMode.mode == OpenGL::GFX_NORMAL) {
+ if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
+ scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth;
+ if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
+ scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight;
+
+ if (!_overlayVisible) {
+ scaledX *= _videoMode.scaleFactor;
+ scaledY *= _videoMode.scaleFactor;
+ }
+ } else {
+ if (_overlayVisible) {
+ if (_displayWidth != _videoMode.overlayWidth)
+ scaledX = scaledX * _displayWidth / _videoMode.overlayWidth;
+ if (_displayHeight != _videoMode.overlayHeight)
+ scaledY = scaledY * _displayHeight / _videoMode.overlayHeight;
+ } else {
+ if (_displayWidth != _videoMode.screenWidth)
+ scaledX = scaledX * _displayWidth / _videoMode.screenWidth;
+ if (_displayHeight != _videoMode.screenHeight)
+ scaledY = scaledY * _displayHeight / _videoMode.screenHeight;
+ }
+
+ scaledX += _displayX;
+ scaledY += _displayY;
+ }
+
+ setInternalMousePosition(scaledX, scaledY);
+
+ _cursorState.x = scaledX;
+ _cursorState.y = scaledY;
}
void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
@@ -558,7 +615,8 @@ void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int
#endif
// Allocate space for cursor data
- if (_cursorData.w != w || _cursorData.h != h)
+ if (_cursorData.w != w || _cursorData.h != h ||
+ _cursorData.bytesPerPixel != _cursorFormat.bytesPerPixel)
_cursorData.create(w, h, _cursorFormat.bytesPerPixel);
// Save cursor data
@@ -580,7 +638,7 @@ void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uin
assert(colors);
// Save the cursor palette
- memcpy(_cursorPalette + start * 4, colors, num * 4);
+ memcpy(_cursorPalette + start * 3, colors, num * 3);
_cursorPaletteDisabled = false;
_cursorNeedsRedraw = true;
@@ -599,61 +657,13 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
assert(_transactionMode == kTransactionNone);
assert(msg);
- // The font we are going to use:
- const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
-
- if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
- _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2);
- else
- // Clear everything
- memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
-
+#ifdef USE_OSD
// Split the message into separate lines.
- Common::Array<Common::String> lines;
- const char *ptr;
- for (ptr = msg; *ptr; ++ptr) {
- if (*ptr == '\n') {
- lines.push_back(Common::String(msg, ptr - msg));
- msg = ptr + 1;
- }
- }
- lines.push_back(Common::String(msg, ptr - msg));
+ _osdLines.clear();
- // Determine a rect which would contain the message string (clipped to the
- // screen dimensions).
- const int vOffset = 6;
- const int lineSpacing = 1;
- const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
- int width = 0;
- int height = lineHeight * lines.size() + 2 * vOffset;
- for (uint i = 0; i < lines.size(); i++) {
- width = MAX(width, font->getStringWidth(lines[i]) + 14);
- }
-
- // Clip the rect
- if (width > _osdSurface.w)
- width = _osdSurface.w;
- if (height > _osdSurface.h)
- height = _osdSurface.h;
-
- int dstX = (_osdSurface.w - width) / 2;
- int dstY = (_osdSurface.h - height) / 2;
-
- // Draw a dark gray rect
- uint16 color = 0x294B;
- uint16 *dst = (uint16 *)_osdSurface.pixels + dstY * _osdSurface.w + dstX;
- for (int i = 0; i < height; i++) {
- for (int j = 0; j < width; j++)
- dst[j] = color;
- dst += _osdSurface.w;
- }
-
- // Render the message, centered, and in white
- for (uint i = 0; i < lines.size(); i++) {
- font->drawString(&_osdSurface, lines[i],
- dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
- 0xFFFF, Graphics::kTextAlignCenter);
- }
+ Common::StringTokenizer tokenizer(msg, "\n");
+ while (!tokenizer.empty())
+ _osdLines.push_back(tokenizer.nextToken());
// Request update of the texture
_requireOSDUpdate = true;
@@ -661,12 +671,25 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
// Init the OSD display parameters, and the fade out
_osdAlpha = kOSDInitialAlpha;
_osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay;
+#endif
}
//
// Intern
//
+void OpenGLGraphicsManager::setFullscreenMode(bool enable) {
+ assert(_transactionMode == kTransactionActive);
+
+ if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
+ return;
+
+ if (_transactionMode == kTransactionActive) {
+ _videoMode.fullscreen = enable;
+ _transactionDetails.needRefresh = true;
+ }
+}
+
void OpenGLGraphicsManager::refreshGameScreen() {
if (_screenNeedsRedraw)
_screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h);
@@ -686,9 +709,9 @@ void OpenGLGraphicsManager::refreshGameScreen() {
byte *dst = surface;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 4];
- dst[1] = _gamePalette[src[j] * 4 + 1];
- dst[2] = _gamePalette[src[j] * 4 + 2];
+ dst[0] = _gamePalette[src[j] * 3];
+ dst[1] = _gamePalette[src[j] * 3 + 1];
+ dst[2] = _gamePalette[src[j] * 3 + 2];
dst += 3;
}
src += _screenData.pitch;
@@ -728,9 +751,9 @@ void OpenGLGraphicsManager::refreshOverlay() {
byte *dst = surface;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- dst[0] = _gamePalette[src[j] * 4];
- dst[1] = _gamePalette[src[j] * 4 + 1];
- dst[2] = _gamePalette[src[j] * 4 + 2];
+ dst[0] = _gamePalette[src[j] * 3];
+ dst[1] = _gamePalette[src[j] * 3 + 1];
+ dst[2] = _gamePalette[src[j] * 3 + 2];
dst += 3;
}
src += _screenData.pitch;
@@ -754,11 +777,17 @@ void OpenGLGraphicsManager::refreshOverlay() {
void OpenGLGraphicsManager::refreshCursor() {
_cursorNeedsRedraw = false;
- if (_cursorFormat.bytesPerPixel == 1) {
- // Create a temporary RGBA8888 surface
- byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
- memset(surface, 0, _cursorState.w * _cursorState.h * 4);
+ // Allocate a texture big enough for cursor
+ _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
+
+ // Create a temporary RGBA8888 surface
+ byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
+ memset(surface, 0, _cursorState.w * _cursorState.h * 4);
+
+ byte *dst = surface;
+ // Convert the paletted cursor to RGBA8888
+ if (_cursorFormat.bytesPerPixel == 1) {
// Select palette
byte *palette;
if (_cursorPaletteDisabled)
@@ -768,27 +797,52 @@ void OpenGLGraphicsManager::refreshCursor() {
// Convert the paletted cursor to RGBA8888
const byte *src = (byte *)_cursorData.pixels;
- byte *dst = surface;
for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
// Check for keycolor
if (src[i] != _cursorKeyColor) {
- dst[0] = palette[src[i] * 4];
- dst[1] = palette[src[i] * 4 + 1];
- dst[2] = palette[src[i] * 4 + 2];
+ dst[0] = palette[src[i] * 3];
+ dst[1] = palette[src[i] * 3 + 1];
+ dst[2] = palette[src[i] * 3 + 2];
dst[3] = 255;
}
dst += 4;
}
+ } else {
+ const bool gotNoAlpha = (_cursorFormat.aLoss == 8);
+
+ // Convert the RGB cursor to RGBA8888
+ if (_cursorFormat.bytesPerPixel == 2) {
+ const uint16 *src = (uint16 *)_cursorData.pixels;
+ for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
+ // Check for keycolor
+ if (src[i] != _cursorKeyColor) {
+ _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]);
+
+ if (gotNoAlpha)
+ dst[3] = 255;
+ }
+ dst += 4;
+ }
+ } else if (_cursorFormat.bytesPerPixel == 4) {
+ const uint32 *src = (uint32 *)_cursorData.pixels;
+ for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
+ // Check for keycolor
+ if (src[i] != _cursorKeyColor) {
+ _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]);
+
+ if (gotNoAlpha)
+ dst[3] = 255;
+ }
+ dst += 4;
+ }
+ }
+ }
- // Allocate a texture big enough for cursor
- _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
-
- // Update the texture with new cursor
- _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h);
+ // Update the texture with new cursor
+ _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h);
- // Free the temp surface
- delete[] surface;
- }
+ // Free the temp surface
+ delete[] surface;
}
void OpenGLGraphicsManager::refreshCursorScale() {
@@ -811,7 +865,8 @@ void OpenGLGraphicsManager::refreshCursorScale() {
} else {
// Otherwise, scale the cursor for the overlay
int targetScaleFactor = MIN(_cursorTargetScale, _videoMode.scaleFactor);
- int actualFactor = screenScaleFactor - (targetScaleFactor - 1) * 10000;
+ // We limit the maximum scale to 3 here to avoid too big cursors, for large overlay resolutions
+ int actualFactor = MIN<uint>(3, screenScaleFactor - (targetScaleFactor - 1)) * 10000;
_cursorState.rW = (int16)(_cursorState.w * actualFactor / 10000);
_cursorState.rH = (int16)(_cursorState.h * actualFactor / 10000);
_cursorState.rHotX = (int16)(_cursorState.hotX * actualFactor / 10000);
@@ -827,8 +882,8 @@ void OpenGLGraphicsManager::refreshCursorScale() {
void OpenGLGraphicsManager::calculateDisplaySize(int &width, int &height) {
if (_videoMode.mode == OpenGL::GFX_ORIGINAL) {
- width = _videoMode.overlayWidth;
- height = _videoMode.overlayHeight;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
} else {
width = _videoMode.hardwareWidth;
height = _videoMode.hardwareHeight;
@@ -873,6 +928,11 @@ void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat,
intFormat = GL_RGBA;
glFormat = GL_RGBA;
gltype = GL_UNSIGNED_SHORT_5_5_5_1;
+ } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555
+ bpp = 2;
+ intFormat = GL_RGB;
+ glFormat = GL_BGRA;
+ gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444
bpp = 2;
intFormat = GL_RGBA;
@@ -963,7 +1023,7 @@ void OpenGLGraphicsManager::internUpdateScreen() {
refreshOverlay();
// Draw the overlay
- _overlayTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight);
+ _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight);
}
if (_cursorVisible) {
@@ -990,9 +1050,7 @@ void OpenGLGraphicsManager::internUpdateScreen() {
#ifdef USE_OSD
if (_osdAlpha > 0) {
if (_requireOSDUpdate) {
- // Update the texture
- _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
- _osdSurface.w, _osdSurface.h);
+ updateOSD();
_requireOSDUpdate = false;
}
@@ -1059,10 +1117,14 @@ void OpenGLGraphicsManager::initGL() {
void OpenGLGraphicsManager::loadTextures() {
#ifdef USE_RGB_COLOR
- if (_transactionDetails.formatChanged && _gameTexture)
+ if (_transactionDetails.formatChanged && _gameTexture) {
delete _gameTexture;
+ _gameTexture = 0;
+ }
#endif
+ uint gameScreenBPP = 0;
+
if (!_gameTexture) {
byte bpp;
GLenum intformat;
@@ -1073,6 +1135,7 @@ void OpenGLGraphicsManager::loadTextures() {
#else
getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, intformat, format, type);
#endif
+ gameScreenBPP = bpp;
_gameTexture = new GLTexture(bpp, intformat, format, type);
} else
_gameTexture->refresh();
@@ -1093,7 +1156,7 @@ void OpenGLGraphicsManager::loadTextures() {
_cursorTexture = new GLTexture(4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
else
_cursorTexture->refresh();
-
+
GLint filter = _videoMode.antialiasing ? GL_LINEAR : GL_NEAREST;
_gameTexture->setFilter(filter);
_overlayTexture->setFilter(filter);
@@ -1104,21 +1167,43 @@ void OpenGLGraphicsManager::loadTextures() {
_overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
_cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
- if (_transactionDetails.formatChanged ||
+ if (
+#ifdef USE_RGB_COLOR
+ _transactionDetails.formatChanged ||
+#endif
_oldVideoMode.screenWidth != _videoMode.screenWidth ||
_oldVideoMode.screenHeight != _videoMode.screenHeight)
_screenData.create(_videoMode.screenWidth, _videoMode.screenHeight,
- _screenFormat.bytesPerPixel);
+#ifdef USE_RGB_COLOR
+ _screenFormat.bytesPerPixel
+#else
+ 1
+#endif
+ );
+
if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth ||
_oldVideoMode.overlayHeight != _videoMode.overlayHeight)
_overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight,
_overlayFormat.bytesPerPixel);
-
+
_screenNeedsRedraw = true;
_overlayNeedsRedraw = true;
_cursorNeedsRedraw = true;
+ // We need to setup a proper unpack alignment value here, else we will
+ // get problems with the texture updates, in case the surface data is
+ // not properly aligned.
+ // For now we use the gcd of the game screen format and 2, since 2 is
+ // the BPP value for the overlay and the OSD.
+ if (gameScreenBPP)
+ glPixelStorei(GL_UNPACK_ALIGNMENT, Common::gcd<uint>(gameScreenBPP, 2));
+
+ // We use a "pack" alignment (when reading from textures) to 4 here,
+ // since the only place where we really use it is the BMP screenshot
+ // code and that requires the same alignment too.
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
#ifdef USE_OSD
if (!_osdTexture)
_osdTexture = new GLTexture(2, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
@@ -1126,6 +1211,9 @@ void OpenGLGraphicsManager::loadTextures() {
_osdTexture->refresh();
_osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
+
+ // Update the OSD in case it is used right now
+ _requireOSDUpdate = true;
#endif
}
@@ -1149,6 +1237,8 @@ void OpenGLGraphicsManager::unloadGFXMode() {
}
void OpenGLGraphicsManager::setScale(int newScale) {
+ assert(_transactionMode == kTransactionActive);
+
if (newScale == _videoMode.scaleFactor)
return;
@@ -1156,57 +1246,48 @@ void OpenGLGraphicsManager::setScale(int newScale) {
_transactionDetails.sizeChanged = true;
}
+void OpenGLGraphicsManager::toggleAntialiasing() {
+ assert(_transactionMode == kTransactionActive);
+
+ _videoMode.antialiasing = !_videoMode.antialiasing;
+ _transactionDetails.filterChanged = true;
+}
+
uint OpenGLGraphicsManager::getAspectRatio() {
- if (_videoMode.mode == OpenGL::GFX_NORMAL)
- return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight;
- else if (_videoMode.mode == OpenGL::GFX_4_3)
+ // In case we enable aspect ratio correction we force a 4/3 ratio.
+ // TODO: This makes OpenGL Normal behave like OpenGL Conserve, when aspect
+ // ratio correction is enabled, but it's better than the previous 4/3 mode
+ // mess at least...
+ if (_videoMode.aspectRatioCorrection)
return 13333;
+ else if (_videoMode.mode == OpenGL::GFX_NORMAL)
+ return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight;
else
return _videoMode.screenWidth * 10000 / _videoMode.screenHeight;
}
-void OpenGLGraphicsManager::adjustMouseEvent(const Common::Event &event) {
- if (!event.synthetic) {
- Common::Event newEvent(event);
- newEvent.synthetic = true;
-
- if (_videoMode.mode == OpenGL::GFX_NORMAL) {
- if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
- newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _videoMode.hardwareWidth;
- if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
- newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _videoMode.hardwareHeight;
-
- if (!_overlayVisible) {
- newEvent.mouse.x /= _videoMode.scaleFactor;
- newEvent.mouse.y /= _videoMode.scaleFactor;
- }
+void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
+ if (_overlayVisible)
+ return;
- } else {
- newEvent.mouse.x -= _displayX;
- newEvent.mouse.y -= _displayY;
-
- if (_overlayVisible) {
- if (_displayWidth != _videoMode.overlayWidth)
- newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _displayWidth;
- if (_displayHeight != _videoMode.overlayHeight)
- newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _displayHeight;
- } else {
- if (_displayWidth != _videoMode.screenWidth)
- newEvent.mouse.x = newEvent.mouse.x * _videoMode.screenWidth / _displayWidth;
- if (_displayHeight != _videoMode.screenHeight)
- newEvent.mouse.y = newEvent.mouse.y * _videoMode.screenHeight / _displayHeight;
- }
- }
+ if (!_overlayVisible) {
+ x -= _displayX;
+ y -= _displayY;
- g_system->getEventManager()->pushEvent(newEvent);
+ if (_displayWidth != _videoMode.screenWidth)
+ x = x * _videoMode.screenWidth / _displayWidth;
+ if (_displayHeight != _videoMode.screenHeight)
+ y = y * _videoMode.screenHeight / _displayHeight;
}
}
bool OpenGLGraphicsManager::notifyEvent(const Common::Event &event) {
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
- if (!event.synthetic)
- setMousePos(event.mouse.x, event.mouse.y);
+ if (!event.synthetic) {
+ _cursorState.x = event.mouse.x;
+ _cursorState.y = event.mouse.y;
+ }
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_WHEELUP:
@@ -1215,7 +1296,12 @@ bool OpenGLGraphicsManager::notifyEvent(const Common::Event &event) {
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
case Common::EVENT_MBUTTONUP:
- adjustMouseEvent(event);
+ if (!event.synthetic) {
+ Common::Event newEvent(event);
+ newEvent.synthetic = true;
+ adjustMousePosition(newEvent.mouse.x, newEvent.mouse.y);
+ g_system->getEventManager()->pushEvent(newEvent);
+ }
return !event.synthetic;
default:
@@ -1229,8 +1315,16 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
int width = _videoMode.hardwareWidth;
int height = _videoMode.hardwareHeight;
+ // A line of a BMP image must have a size divisible by 4.
+ // We calculate the padding bytes needed here.
+ // Since we use a 3 byte per pixel mode, we can use width % 4 here, since
+ // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the
+ // usual way of computing the padding bytes required).
+ const int linePaddingSize = width % 4;
+ const int lineSize = width * 3 + linePaddingSize;
+
// Allocate memory for screenshot
- uint8 *pixels = new uint8[width * height * 3];
+ uint8 *pixels = new uint8[lineSize * height];
// Get pixel data from OpenGL buffer
#ifdef USE_GLES
@@ -1250,9 +1344,9 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
// Write BMP header
out.writeByte('B');
out.writeByte('M');
- out.writeUint32LE(height * width * 3 + 52);
+ out.writeUint32LE(height * lineSize + 54);
out.writeUint32LE(0);
- out.writeUint32LE(52);
+ out.writeUint32LE(54);
out.writeUint32LE(40);
out.writeUint32LE(width);
out.writeUint32LE(height);
@@ -1266,7 +1360,7 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) {
out.writeUint32LE(0);
// Write pixel data to BMP
- out.write(pixels, width * height * 3);
+ out.write(pixels, lineSize * height);
// Free allocated memory
delete[] pixels;
@@ -1287,21 +1381,52 @@ const char *OpenGLGraphicsManager::getCurrentModeName() {
return modeName;
}
-void OpenGLGraphicsManager::switchDisplayMode(int mode) {
- if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
- return;
+#ifdef USE_OSD
+void OpenGLGraphicsManager::updateOSD() {
+ // The font we are going to use:
+ const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
- if (_transactionMode == kTransactionActive) {
- if (mode == -1) // If -1, switch to next mode
- _videoMode.mode = (_videoMode.mode + 1) % 4;
- else if (mode == -2) // If -2, switch to previous mode
- _videoMode.mode = (_videoMode.mode + 3) % 4;
- else
- _videoMode.mode = mode;
+ if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight())
+ _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2);
+ else
+ // Clear everything
+ memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch);
- _transactionDetails.needRefresh = true;
- _aspectRatioCorrection = false;
+ // Determine a rect which would contain the message string (clipped to the
+ // screen dimensions).
+ const int vOffset = 6;
+ const int lineSpacing = 1;
+ const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
+ int width = 0;
+ int height = lineHeight * _osdLines.size() + 2 * vOffset;
+ for (uint i = 0; i < _osdLines.size(); i++) {
+ width = MAX(width, font->getStringWidth(_osdLines[i]) + 14);
}
+
+ // Clip the rect
+ if (width > _osdSurface.w)
+ width = _osdSurface.w;
+ if (height > _osdSurface.h)
+ height = _osdSurface.h;
+
+ int dstX = (_osdSurface.w - width) / 2;
+ int dstY = (_osdSurface.h - height) / 2;
+
+ // Draw a dark gray rect
+ const uint16 color = 0x294B;
+ _osdSurface.fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color);
+
+ // Render the message, centered, and in white
+ for (uint i = 0; i < _osdLines.size(); i++) {
+ font->drawString(&_osdSurface, _osdLines[i],
+ dstX, dstY + i * lineHeight + vOffset + lineSpacing, width,
+ 0xFFFF, Graphics::kTextAlignCenter);
+ }
+
+ // Update the texture
+ _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0,
+ _osdSurface.w, _osdSurface.h);
}
+#endif
#endif
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 27c850f0ab..374f1c196e 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -39,8 +39,7 @@ namespace OpenGL {
enum {
GFX_NORMAL = 0,
GFX_CONSERVE = 1,
- GFX_4_3 = 2,
- GFX_ORIGINAL = 3
+ GFX_ORIGINAL = 2
};
}
@@ -152,11 +151,11 @@ protected:
bool setup;
bool fullscreen;
- int activeFullscreenMode;
int mode;
int scaleFactor;
bool antialiasing;
+ bool aspectRatioCorrection;
int screenWidth, screenHeight;
int overlayWidth, overlayHeight;
@@ -176,7 +175,41 @@ protected:
virtual bool loadGFXMode();
virtual void unloadGFXMode();
- virtual void setScale(int newScale);
+ /**
+ * Setup the fullscreen mode state.
+ */
+ void setFullscreenMode(bool enable);
+
+ /**
+ * Query the fullscreen state.
+ */
+ inline bool getFullscreenMode() const { return _videoMode.fullscreen; }
+
+ /**
+ * Set the scale factor.
+ *
+ * This can only be used in a GFX transaction.
+ *
+ * @param newScale New scale factor.
+ */
+ void setScale(int newScale);
+
+ /**
+ * Query the scale factor.
+ */
+ inline int getScale() const { return _videoMode.scaleFactor; }
+
+ /**
+ * Toggle the antialiasing state of the current video mode.
+ *
+ * This can only be used in a GFX transaction.
+ */
+ void toggleAntialiasing();
+
+ /**
+ * Query the antialiasing state.
+ */
+ inline bool getAntialiasingState() const { return _videoMode.antialiasing; }
// Drawing coordinates for the current display mode and scale
int _displayX;
@@ -184,19 +217,11 @@ protected:
int _displayWidth;
int _displayHeight;
- /**
- * Sets the dispaly mode.
- * @mode the dispaly mode, if -1 it will switch to next mode. If -2 to previous mode.
- */
- virtual void switchDisplayMode(int mode);
-
virtual const char *getCurrentModeName();
virtual void calculateDisplaySize(int &width, int &height);
virtual void refreshDisplaySize();
- bool _aspectRatioCorrection;
-
/**
* Returns the current target aspect ratio x 10000
*/
@@ -232,15 +257,14 @@ protected:
bool _overlayVisible;
bool _overlayNeedsRedraw;
Common::Rect _overlayDirtyRect;
-
+
virtual void refreshOverlay();
//
// Mouse
//
struct MousePos {
- // The mouse position, using either virtual (game) or real
- // (overlay) coordinates.
+ // The mouse position in hardware screen coordinates.
int16 x, y;
// The size and hotspot of the original cursor image.
@@ -273,8 +297,23 @@ protected:
virtual void refreshCursor();
virtual void refreshCursorScale();
- virtual void adjustMouseEvent(const Common::Event &event);
- virtual void setMousePos(int x, int y);
+
+ /**
+ * Set up the mouse position for the (event) system.
+ *
+ * @param x X coordinate in native coordinates.
+ * @param y Y coordinate in native coordinates.
+ */
+ virtual void setInternalMousePosition(int x, int y) = 0;
+
+ /**
+ * Adjusts hardware screen coordinates to either overlay or game screen
+ * coordinates depending on whether the overlay is visible or not.
+ *
+ * @param x X coordinate of the mouse position.
+ * @param y Y coordinate of the mouse position.
+ */
+ virtual void adjustMousePosition(int16 &x, int16 &y);
//
// Misc
@@ -282,6 +321,16 @@ protected:
virtual bool saveScreenshot(const char *filename);
#ifdef USE_OSD
+ /**
+ * The OSD contents.
+ */
+ Common::Array<Common::String> _osdLines;
+
+ /**
+ * Update the OSD texture / surface.
+ */
+ void updateOSD();
+
GLTexture *_osdTexture;
Graphics::Surface _osdSurface;
uint8 _osdAlpha;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index b10c94b03f..b9022af120 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -35,6 +35,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager()
:
_hwscreen(0),
_screenResized(false),
+ _activeFullscreenMode(-2),
_lastFullscreenModeWidth(0),
_lastFullscreenModeHeight(0),
_desktopWidth(0),
@@ -78,9 +79,6 @@ bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) {
void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
switch (f) {
- case OSystem::kFeatureFullscreenMode:
- setFullscreenMode(enable);
- break;
case OSystem::kFeatureIconifyWindow:
if (enable)
SDL_WM_IconifyWindow();
@@ -121,6 +119,7 @@ void OpenGLSdlGraphicsManager::detectSupportedFormats() {
#endif
Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), // RGB565
Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0), // RGB5551
+ Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), // RGB555
Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444
#ifndef USE_GLES
Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) // ARGB4444
@@ -191,40 +190,8 @@ void OpenGLSdlGraphicsManager::detectSupportedFormats() {
#endif
-void OpenGLSdlGraphicsManager::warpMouse(int x, int y) {
- int scaledX = x;
- int scaledY = y;
-
- if (_videoMode.mode == OpenGL::GFX_NORMAL) {
- if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
- scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth;
- if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
- scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight;
-
- if (!_overlayVisible) {
- scaledX *= _videoMode.scaleFactor;
- scaledY *= _videoMode.scaleFactor;
- }
- } else {
- if (_overlayVisible) {
- if (_displayWidth != _videoMode.overlayWidth)
- scaledX = scaledX * _displayWidth / _videoMode.overlayWidth;
- if (_displayHeight != _videoMode.overlayHeight)
- scaledY = scaledY * _displayHeight / _videoMode.overlayHeight;
- } else {
- if (_displayWidth != _videoMode.screenWidth)
- scaledX = scaledX * _displayWidth / _videoMode.screenWidth;
- if (_displayHeight != _videoMode.screenHeight)
- scaledY = scaledY * _displayHeight / _videoMode.screenHeight;
- }
-
- scaledX += _displayX;
- scaledY += _displayY;
- }
-
- SDL_WarpMouse(scaledX, scaledY);
-
- setMousePos(scaledX, scaledY);
+void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) {
+ SDL_WarpMouse(x, y);
}
void OpenGLSdlGraphicsManager::updateScreen() {
@@ -246,7 +213,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
if (availableModes == (void *)-1) {
_videoMode.hardwareWidth = _desktopWidth;
_videoMode.hardwareHeight = _desktopHeight;
- _videoMode.activeFullscreenMode = -2;
+ _activeFullscreenMode = -2;
return true;
}
@@ -254,7 +221,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
// The last used fullscreen mode will be prioritized, if there is no last fullscreen
// mode, the desktop resolution will be used, and in case the desktop resolution
// is not available as a fullscreen mode, the one with smallest metric will be selected.
- if (_videoMode.activeFullscreenMode == -2) {
+ if (_activeFullscreenMode == -2) {
// Desktop resolution
int desktopModeIndex = -1;
@@ -269,7 +236,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
if (mode->w == _lastFullscreenModeWidth && mode->h == _lastFullscreenModeHeight) {
_videoMode.hardwareWidth = _lastFullscreenModeWidth;
_videoMode.hardwareHeight = _lastFullscreenModeHeight;
- _videoMode.activeFullscreenMode = i;
+ _activeFullscreenMode = i;
return true;
}
@@ -293,32 +260,32 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
_videoMode.hardwareWidth = _desktopWidth;
_videoMode.hardwareHeight = _desktopHeight;
- _videoMode.activeFullscreenMode = desktopModeIndex;
+ _activeFullscreenMode = desktopModeIndex;
return true;
} else if (bestMode) {
_videoMode.hardwareWidth = bestMode->w;
_videoMode.hardwareHeight = bestMode->h;
- _videoMode.activeFullscreenMode = bestModeIndex;
+ _activeFullscreenMode = bestModeIndex;
return true;
}
} else {
// Use last fullscreen mode if looping backwards from the first mode
- if (_videoMode.activeFullscreenMode == -1) {
+ if (_activeFullscreenMode == -1) {
do {
- _videoMode.activeFullscreenMode++;
- } while(availableModes[_videoMode.activeFullscreenMode]);
- _videoMode.activeFullscreenMode--;
+ _activeFullscreenMode++;
+ } while(availableModes[_activeFullscreenMode]);
+ _activeFullscreenMode--;
}
// Use first fullscreen mode if looping from last mode
- if (!availableModes[_videoMode.activeFullscreenMode])
- _videoMode.activeFullscreenMode = 0;
+ if (!availableModes[_activeFullscreenMode])
+ _activeFullscreenMode = 0;
// Check if the fullscreen mode is valid
- if (availableModes[_videoMode.activeFullscreenMode]) {
- _videoMode.hardwareWidth = availableModes[_videoMode.activeFullscreenMode]->w;
- _videoMode.hardwareHeight = availableModes[_videoMode.activeFullscreenMode]->h;
+ if (availableModes[_activeFullscreenMode]) {
+ _videoMode.hardwareWidth = availableModes[_activeFullscreenMode]->w;
+ _videoMode.hardwareHeight = availableModes[_activeFullscreenMode]->h;
return true;
}
}
@@ -328,17 +295,11 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() {
}
bool OpenGLSdlGraphicsManager::loadGFXMode() {
- // Force 4/3 if feature enabled
- if (_aspectRatioCorrection)
- _videoMode.mode = OpenGL::GFX_4_3;
-
- _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
-
// If the screen was resized, do not change its size
if (!_screenResized) {
- _videoMode.hardwareWidth = _videoMode.overlayWidth;
- _videoMode.hardwareHeight = _videoMode.overlayHeight;
+ const int scaleFactor = getScale();
+ _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * scaleFactor;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * scaleFactor;
int screenAspectRatio = _videoMode.screenWidth * 10000 / _videoMode.screenHeight;
int desiredAspectRatio = getAspectRatio();
@@ -348,11 +309,6 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
_videoMode.hardwareHeight = (_videoMode.overlayWidth * 10000 + 5000) / desiredAspectRatio;
else if (screenAspectRatio < desiredAspectRatio)
_videoMode.hardwareWidth = (_videoMode.overlayHeight * desiredAspectRatio + 5000) / 10000;
-
- // Only adjust the overlay height if it is bigger than original one. If
- // the width is modified it can break the overlay.
- if (_videoMode.hardwareHeight > _videoMode.overlayHeight)
- _videoMode.overlayHeight = _videoMode.hardwareHeight;
}
_screenResized = false;
@@ -364,14 +320,24 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- if (_videoMode.fullscreen)
+ const bool isFullscreen = getFullscreenMode();
+
+ // In case we have an fullscreen mode and we are not in a rollback, detect
+ // a proper mode to use. In case we are in a rollback, we already detected
+ // a proper mode when setting up that mode, thus there is no need to run
+ // the detection again.
+ if (isFullscreen && _transactionMode != kTransactionRollback) {
if (!setupFullscreenMode())
// Failed setuping a fullscreen mode
return false;
+ }
+
+ _videoMode.overlayWidth = _videoMode.hardwareWidth;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight;
uint32 flags = SDL_OPENGL;
- if (_videoMode.fullscreen)
+ if (isFullscreen)
flags |= SDL_FULLSCREEN;
else
flags |= SDL_RESIZABLE;
@@ -397,7 +363,7 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
// Check if the screen is BGR format
_formatBGR = _hwscreen->format->Rshift != 0;
- if (_videoMode.fullscreen) {
+ if (isFullscreen) {
_lastFullscreenModeWidth = _videoMode.hardwareWidth;
_lastFullscreenModeHeight = _videoMode.hardwareHeight;
ConfMan.setInt("last_fullscreen_mode_width", _lastFullscreenModeWidth);
@@ -427,11 +393,13 @@ void OpenGLSdlGraphicsManager::internUpdateScreen() {
void OpenGLSdlGraphicsManager::displayModeChangedMsg() {
const char *newModeName = getCurrentModeName();
if (newModeName) {
+ const int scaleFactor = getScale();
+
char buffer[128];
sprintf(buffer, "Current display mode: %s\n%d x %d -> %d x %d",
newModeName,
- _videoMode.screenWidth * _videoMode.scaleFactor,
- _videoMode.screenHeight * _videoMode.scaleFactor,
+ _videoMode.screenWidth * scaleFactor,
+ _videoMode.screenHeight * scaleFactor,
_hwscreen->w, _hwscreen->h
);
displayMessageOnOSD(buffer);
@@ -439,8 +407,9 @@ void OpenGLSdlGraphicsManager::displayModeChangedMsg() {
}
void OpenGLSdlGraphicsManager::displayScaleChangedMsg() {
char buffer[128];
+ const int scaleFactor = getScale();
sprintf(buffer, "Current scale: x%d\n%d x %d -> %d x %d",
- _videoMode.scaleFactor,
+ scaleFactor,
_videoMode.screenWidth, _videoMode.screenHeight,
_videoMode.overlayWidth, _videoMode.overlayHeight
);
@@ -448,17 +417,6 @@ void OpenGLSdlGraphicsManager::displayScaleChangedMsg() {
}
#endif
-void OpenGLSdlGraphicsManager::setFullscreenMode(bool enable) {
- if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable &&
- _oldVideoMode.activeFullscreenMode == _videoMode.activeFullscreenMode)
- return;
-
- if (_transactionMode == kTransactionActive) {
- _videoMode.fullscreen = enable;
- _transactionDetails.needRefresh = true;
- }
-}
-
bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
if (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS ||
@@ -476,12 +434,14 @@ bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) {
beginGFXTransaction();
- if (_videoMode.fullscreen && loop) {
- _videoMode.activeFullscreenMode += loop;
+ const bool isFullscreen = getFullscreenMode();
+
+ if (isFullscreen && loop) {
+ _activeFullscreenMode += loop;
setFullscreenMode(true);
} else {
- _videoMode.activeFullscreenMode = -2;
- setFullscreenMode(!_videoMode.fullscreen);
+ _activeFullscreenMode = -2;
+ setFullscreenMode(!isFullscreen);
}
endGFXTransaction();
@@ -490,7 +450,7 @@ void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) {
#ifdef USE_OSD
char buffer[128];
- if (_videoMode.fullscreen)
+ if (getFullscreenMode())
sprintf(buffer, "Fullscreen mode\n%d x %d",
_hwscreen->w, _hwscreen->h
);
@@ -545,10 +505,19 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl-Alt-a switch between display modes
if (event.kbd.keycode == 'a') {
beginGFXTransaction();
- switchDisplayMode(-1);
+ setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
endGFXTransaction();
#ifdef USE_OSD
- displayModeChangedMsg();
+ char buffer[128];
+ if (getFeatureState(OSystem::kFeatureAspectRatioCorrection))
+ sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d",
+ _videoMode.screenWidth, _videoMode.screenHeight,
+ _hwscreen->w, _hwscreen->h);
+ else
+ sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d",
+ _videoMode.screenWidth, _videoMode.screenHeight,
+ _hwscreen->w, _hwscreen->h);
+ displayMessageOnOSD(buffer);
#endif
internUpdateScreen();
return true;
@@ -557,11 +526,14 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl-Alt-f toggles antialiasing
if (event.kbd.keycode == 'f') {
beginGFXTransaction();
- _videoMode.antialiasing = !_videoMode.antialiasing;
- _transactionDetails.filterChanged = true;
+ toggleAntialiasing();
endGFXTransaction();
+
#ifdef USE_OSD
- if (_videoMode.antialiasing)
+ // TODO: This makes guesses about what internal antialiasing
+ // modes we use, we might want to consider a better way of
+ // displaying information to the user.
+ if (getAntialiasingState())
displayMessageOnOSD("Active filter mode: Linear");
else
displayMessageOnOSD("Active filter mode: Nearest");
@@ -574,7 +546,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl+Alt+Plus/Minus Increase/decrease the scale factor
if ((sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS ||
sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS)) {
- int factor = _videoMode.scaleFactor;
+ int factor = getScale();
factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1;
if (0 < factor && factor < 4) {
// Check if the desktop resolution has been detected
@@ -594,17 +566,21 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
}
- const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_4);
- const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP4);
+ const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_3);
+ const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP3);
// Ctrl-Alt-<number key> will change the GFX mode
if (isNormalNumber || isKeypadNumber) {
- if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 4) {
+ if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 3) {
+#ifdef USE_OSD
int lastMode = _videoMode.mode;
+#endif
+ // We need to query the scale and set it up, because
+ // setGraphicsMode sets the default scale to 2
+ int oldScale = getScale();
beginGFXTransaction();
- _videoMode.mode = sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1);
- _transactionDetails.needRefresh = true;
- _aspectRatioCorrection = false;
+ setGraphicsMode(sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1));
+ setScale(oldScale);
endGFXTransaction();
#ifdef USE_OSD
if (lastMode != _videoMode.mode)
@@ -622,18 +598,6 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
toggleFullScreen(-1);
return true;
}
-
- // Ctrl-Shift-a switch backwards between display modes
- if (event.kbd.keycode == 'a') {
- beginGFXTransaction();
- switchDisplayMode(-2);
- endGFXTransaction();
-#ifdef USE_OSD
- displayModeChangedMsg();
-#endif
- internUpdateScreen();
- return true;
- }
}
break;
case Common::EVENT_KEYUP:
@@ -643,7 +607,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// there is no common resize event.
case OSystem_SDL::kSdlEventResize:
// Do not resize if ignoring resize events.
- if (!_ignoreResizeFrames && !_videoMode.fullscreen) {
+ if (!_ignoreResizeFrames && !getFullscreenMode()) {
bool scaleChanged = false;
beginGFXTransaction();
_videoMode.hardwareWidth = event.mouse.x;
@@ -655,10 +619,11 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
int scale = MIN(_videoMode.hardwareWidth / _videoMode.screenWidth,
- _videoMode.hardwareHeight / _videoMode.screenHeight);
- if (_videoMode.scaleFactor != scale) {
+ _videoMode.hardwareHeight / _videoMode.screenHeight);
+
+ if (getScale() != scale) {
scaleChanged = true;
- _videoMode.scaleFactor = MAX(MIN(scale, 3), 1);
+ setScale(MAX(MIN(scale, 3), 1));
}
if (_videoMode.mode == OpenGL::GFX_ORIGINAL) {
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index d39c0814de..e9e5ed882d 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -48,8 +48,6 @@ public:
virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
- virtual void warpMouse(int x, int y);
-
virtual bool notifyEvent(const Common::Event &event);
virtual void updateScreen();
@@ -59,9 +57,6 @@ protected:
virtual bool loadGFXMode();
virtual void unloadGFXMode();
-
- virtual void setFullscreenMode(bool enable);
-
virtual bool isHotkey(const Common::Event &event);
#ifdef USE_RGB_COLOR
@@ -80,12 +75,16 @@ protected:
*/
virtual void toggleFullScreen(int loop);
+ int _activeFullscreenMode;
+
/**
* Setup the fullscreen mode.
* @return false if failed finding a mode, true otherwise.
*/
virtual bool setupFullscreenMode();
+ virtual void setInternalMousePosition(int x, int y);
+
int _lastFullscreenModeWidth;
int _lastFullscreenModeHeight;
int _desktopWidth;
diff --git a/backends/platform/openpandora/op-graphics.cpp b/backends/graphics/openpandora/op-graphics.cpp
index ef95f52e99..ab6974ba5f 100644
--- a/backends/platform/openpandora/op-graphics.cpp
+++ b/backends/graphics/openpandora/op-graphics.cpp
@@ -18,11 +18,14 @@
* 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$
- *
*/
+#include "common/scummsys.h"
+
+#if defined(OPENPANDORA)
+
+#include "backends/graphics/openpandora/op-graphics.h"
+#include "backends/events/openpandora/op-events.h"
#include "backends/platform/openpandora/op-sdl.h"
#include "common/mutex.h"
#include "common/translation.h"
@@ -31,7 +34,11 @@
#include "graphics/scaler/aspect.h"
#include "graphics/surface.h"
-bool OSystem_OP::loadGFXMode() {
+OPGraphicsManager::OPGraphicsManager(SdlEventSource *boss)
+ : SdlGraphicsManager(boss) {
+}
+
+bool OPGraphicsManager::loadGFXMode() {
/* FIXME: For now we just cheat and set the overlay to 640*480 not 800*480 and let SDL
deal with the boarders (it saves cleaning up the overlay when the game screen is
smaller than the overlay ;)
@@ -43,8 +50,7 @@ bool OSystem_OP::loadGFXMode() {
if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
_videoMode.aspectRatioCorrection = false;
- OSystem_SDL::loadGFXMode();
-
- return true;
-
+ return SdlGraphicsManager::loadGFXMode();
}
+
+#endif
diff --git a/backends/graphics/openpandora/op-graphics.h b/backends/graphics/openpandora/op-graphics.h
new file mode 100644
index 0000000000..b0d4298620
--- /dev/null
+++ b/backends/graphics/openpandora/op-graphics.h
@@ -0,0 +1,62 @@
+/* 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.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_OP_H
+#define BACKENDS_GRAPHICS_OP_H
+
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "graphics/scaler/aspect.h" // for aspect2Real
+#include "graphics/scaler/downscaler.h"
+
+enum {
+ GFX_HALF = 12
+};
+
+class OPGraphicsManager : public SdlGraphicsManager {
+public:
+ OPGraphicsManager(SdlEventSource *boss);
+
+ bool hasFeature(OSystem::Feature f);
+ void setFeatureState(OSystem::Feature f, bool enable);
+ bool getFeatureState(OSystem::Feature f);
+ int getDefaultGraphicsMode() const;
+
+ void initSize(uint w, uint h);
+ const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ bool setGraphicsMode(const char *name);
+ bool setGraphicsMode(int mode);
+ void setGraphicsModeIntern();
+ void internUpdateScreen();
+ void showOverlay();
+ void hideOverlay();
+ bool loadGFXMode();
+ void drawMouse();
+ void undrawMouse();
+ virtual void warpMouse(int x, int y);
+
+ SdlGraphicsManager::MousePos *getMouseCurState();
+ SdlGraphicsManager::VideoState *getVideoMode();
+
+ virtual void adjustMouseEvent(const Common::Event &event);
+};
+
+#endif /* BACKENDS_GRAPHICS_OP_H */
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 480cf2e795..67b979a830 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -141,7 +141,11 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource)
_currentShakePos(0), _newShakePos(0),
_paletteDirtyStart(0), _paletteDirtyEnd(0),
_screenIsLocked(false),
- _graphicsMutex(0), _transactionMode(kTransactionNone) {
+ _graphicsMutex(0),
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ _enableFocusRectDebugCode(false), _enableFocusRect(false), _focusRect(),
+#endif
+ _transactionMode(kTransactionNone) {
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
error("Could not initialize SDL: %s", SDL_GetError());
@@ -161,11 +165,9 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource)
_graphicsMutex = g_system->createMutex();
-#ifdef _WIN32_WCE
- if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) {
- SDL_VideoInit("windib", 0);
- sdlFlags ^= SDL_INIT_VIDEO;
- }
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ if (ConfMan.hasKey("use_sdl_debug_focusrect"))
+ _enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect");
#endif
SDL_ShowCursor(SDL_DISABLE);
@@ -1103,6 +1105,79 @@ void SdlGraphicsManager::internUpdateScreen() {
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
}
#endif
+
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ // We draw the focus rectangle on top of everything, to assure it's easily visible.
+ // Of course when the overlay is visible we do not show it, since it is only for game
+ // specific focus.
+ if (_enableFocusRect && !_overlayVisible) {
+ int y = _focusRect.top + _currentShakePos;
+ int h = 0;
+ int x = _focusRect.left * scale1;
+ int w = _focusRect.width() * scale1;
+
+ if (y < height) {
+ h = _focusRect.height();
+ if (h > height - y)
+ h = height - y;
+
+ y *= scale1;
+
+ if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+ y = real2Aspect(y);
+
+ if (h > 0 && w > 0) {
+ SDL_LockSurface(_hwscreen);
+
+ // Use white as color for now.
+ Uint32 rectColor = SDL_MapRGB(_hwscreen->format, 0xFF, 0xFF, 0xFF);
+
+ // First draw the top and bottom lines
+ // then draw the left and right lines
+ if (_hwscreen->format->BytesPerPixel == 2) {
+ uint16 *top = (uint16 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2);
+ uint16 *bottom = (uint16 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 2);
+ byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2);
+ byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 2);
+
+ while (w--) {
+ *top++ = rectColor;
+ *bottom++ = rectColor;
+ }
+
+ while (h--) {
+ *(uint16 *)left = rectColor;
+ *(uint16 *)right = rectColor;
+
+ left += _hwscreen->pitch;
+ right += _hwscreen->pitch;
+ }
+ } else if (_hwscreen->format->BytesPerPixel == 4) {
+ uint32 *top = (uint32 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4);
+ uint32 *bottom = (uint32 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 4);
+ byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4);
+ byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 4);
+
+ while (w--) {
+ *top++ = rectColor;
+ *bottom++ = rectColor;
+ }
+
+ while (h--) {
+ *(uint32 *)left = rectColor;
+ *(uint32 *)right = rectColor;
+
+ left += _hwscreen->pitch;
+ right += _hwscreen->pitch;
+ }
+ }
+
+ SDL_UnlockSurface(_hwscreen);
+ }
+ }
+ }
+#endif
+
// Finally, blit all our changes to the screen
SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
}
@@ -1166,25 +1241,25 @@ void SdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int
error("SDL_LockSurface failed: %s", SDL_GetError());
#ifdef USE_RGB_COLOR
- byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth * _screenFormat.bytesPerPixel + x * _screenFormat.bytesPerPixel;
- if (_videoMode.screenWidth == w && pitch == w * _screenFormat.bytesPerPixel) {
- memcpy(dst, src, h*w*_screenFormat.bytesPerPixel);
+ byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x * _screenFormat.bytesPerPixel;
+ if (_videoMode.screenWidth == w && pitch == _screen->pitch) {
+ memcpy(dst, src, h*pitch);
} else {
do {
memcpy(dst, src, w * _screenFormat.bytesPerPixel);
src += pitch;
- dst += _videoMode.screenWidth * _screenFormat.bytesPerPixel;
+ dst += _screen->pitch;
} while (--h);
}
#else
- byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
- if (_videoMode.screenWidth == pitch && pitch == w) {
+ byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x;
+ if (_screen->pitch == pitch && pitch == w) {
memcpy(dst, src, h*w);
} else {
do {
memcpy(dst, src, w);
src += pitch;
- dst += _videoMode.screenWidth;
+ dst += _screen->pitch;
} while (--h);
}
#endif
@@ -1337,11 +1412,10 @@ void SdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
const byte *b = colors;
uint i;
SDL_Color *base = _currentPalette + start;
- for (i = 0; i < num; i++) {
+ for (i = 0; i < num; i++, b += 3) {
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
- b += 4;
}
if (start < _paletteDirtyStart)
@@ -1365,10 +1439,9 @@ void SdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
const SDL_Color *base = _currentPalette + start;
for (uint i = 0; i < num; ++i) {
- colors[i * 4] = base[i].r;
- colors[i * 4 + 1] = base[i].g;
- colors[i * 4 + 2] = base[i].b;
- colors[i * 4 + 3] = 0xFF;
+ colors[i * 3] = base[i].r;
+ colors[i * 3 + 1] = base[i].g;
+ colors[i * 3 + 2] = base[i].b;
}
}
@@ -1377,11 +1450,10 @@ void SdlGraphicsManager::setCursorPalette(const byte *colors, uint start, uint n
const byte *b = colors;
uint i;
SDL_Color *base = _cursorPalette + start;
- for (i = 0; i < num; i++) {
+ for (i = 0; i < num; i++, b += 3) {
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
- b += 4;
}
_cursorPaletteDisabled = false;
@@ -1399,6 +1471,41 @@ void SdlGraphicsManager::setShakePos(int shake_pos) {
_newShakePos = shake_pos;
}
+void SdlGraphicsManager::setFocusRectangle(const Common::Rect &rect) {
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ // Only enable focus rectangle debug code, when the user wants it
+ if (!_enableFocusRectDebugCode)
+ return;
+
+ _enableFocusRect = true;
+ _focusRect = rect;
+
+ if (rect.left < 0 || rect.top < 0 || rect.right > _videoMode.screenWidth || rect.bottom > _videoMode.screenHeight)
+ warning("SdlGraphicsManager::setFocusRectangle: Got a rect which does not fit inside the screen bounds: %d,%d,%d,%d", rect.left, rect.top, rect.right, rect.bottom);
+
+ // It's gross but we actually sometimes get rects, which are not inside the screen bounds,
+ // thus we need to clip the rect here...
+ _focusRect.clip(_videoMode.screenWidth, _videoMode.screenHeight);
+
+ // We just fake this as a dirty rect for now, to easily force an screen update whenever
+ // the rect changes.
+ addDirtyRect(_focusRect.left, _focusRect.top, _focusRect.width(), _focusRect.height());
+#endif
+}
+
+void SdlGraphicsManager::clearFocusRectangle() {
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ // Only enable focus rectangle debug code, when the user wants it
+ if (!_enableFocusRectDebugCode)
+ return;
+
+ _enableFocusRect = false;
+
+ // We just fake this as a dirty rect for now, to easily force an screen update whenever
+ // the rect changes.
+ addDirtyRect(_focusRect.left, _focusRect.top, _focusRect.width(), _focusRect.height());
+#endif
+}
#pragma mark -
#pragma mark --- Overlays ---
@@ -1871,7 +1978,6 @@ void SdlGraphicsManager::drawMouse() {
SDL_Rect dst;
int scale;
- int width, height;
int hotX, hotY;
dst.x = _mouseCurState.x;
@@ -1879,16 +1985,12 @@ void SdlGraphicsManager::drawMouse() {
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
- width = _videoMode.screenWidth;
- height = _videoMode.screenHeight;
dst.w = _mouseCurState.vW;
dst.h = _mouseCurState.vH;
hotX = _mouseCurState.vHotX;
hotY = _mouseCurState.vHotY;
} else {
scale = 1;
- width = _videoMode.overlayWidth;
- height = _videoMode.overlayHeight;
dst.w = _mouseCurState.rW;
dst.h = _mouseCurState.rH;
hotX = _mouseCurState.rHotX;
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index 0daaab104c..f467c38d5f 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -35,6 +35,10 @@
#include "backends/platform/sdl/sdl-sys.h"
+#ifndef RELEASE_BUILD
+// Define this to allow for focus rectangle debugging
+#define USE_SDL_DEBUG_FOCUSRECT
+#endif
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
// Uncomment this to enable the 'on screen display' code.
@@ -114,8 +118,8 @@ public:
virtual void fillScreen(uint32 col);
virtual void updateScreen();
virtual void setShakePos(int shakeOffset);
- virtual void setFocusRectangle(const Common::Rect& rect) {}
- virtual void clearFocusRectangle() {}
+ virtual void setFocusRectangle(const Common::Rect& rect);
+ virtual void clearFocusRectangle();
virtual void showOverlay();
virtual void hideOverlay();
@@ -301,6 +305,12 @@ protected:
*/
OSystem::MutexRef _graphicsMutex;
+#ifdef USE_SDL_DEBUG_FOCUSRECT
+ bool _enableFocusRectDebugCode;
+ bool _enableFocusRect;
+ Common::Rect _focusRect;
+#endif
+
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false);
virtual void drawMouse();
diff --git a/backends/graphics/wincesdl/wincesdl-graphics.cpp b/backends/graphics/wincesdl/wincesdl-graphics.cpp
new file mode 100644
index 0000000000..37c6624560
--- /dev/null
+++ b/backends/graphics/wincesdl/wincesdl-graphics.cpp
@@ -0,0 +1,1639 @@
+/* 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$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#ifdef _WIN32_WCE
+
+#include "common/system.h"
+#include "common/translation.h"
+#include "common/mutex.h"
+
+#include "graphics/scaler/downscaler.h"
+#include "graphics/scaler/aspect.h"
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/platform/wince/wince-sdl.h"
+
+#include "backends/platform/wince/resource.h"
+#include "backends/platform/wince/CEActionsPocket.h"
+#include "backends/platform/wince/CEActionsSmartphone.h"
+#include "backends/platform/wince/CEDevice.h"
+#include "backends/platform/wince/CEScaler.h"
+#include "backends/platform/wince/CEgui/ItemAction.h"
+
+WINCESdlGraphicsManager::WINCESdlGraphicsManager(SdlEventSource *sdlEventSource)
+ : SdlGraphicsManager(sdlEventSource),
+ _panelInitialized(false), _noDoubleTapRMB(false),
+ _toolbarHighDrawn(false), _newOrientation(0), _orientationLandscape(0),
+ _panelVisible(true), _saveActiveToolbar(NAME_MAIN_PANEL), _panelStateForced(false),
+ _canBeAspectScaled(false), _scalersChanged(false), _saveToolbarState(false),
+ _mouseBackupOld(NULL), _mouseBackupDim(0), _mouseBackupToolbar(NULL),
+ _usesEmulatedMouse(false), _forceHideMouse(false), _hasfocus(true),
+ _zoomUp(false), _zoomDown(false) {
+ memset(&_mouseCurState, 0, sizeof(_mouseCurState));
+ if (_isSmartphone) {
+ _mouseCurState.x = 20;
+ _mouseCurState.y = 20;
+ }
+
+ loadDeviceConfigurationElement("repeatTrigger", _keyRepeatTrigger, 200);
+ loadDeviceConfigurationElement("repeatX", _repeatX, 4);
+ loadDeviceConfigurationElement("repeatY", _repeatY, 4);
+ loadDeviceConfigurationElement("stepX1", _stepX1, 2);
+ loadDeviceConfigurationElement("stepX2", _stepX2, 10);
+ loadDeviceConfigurationElement("stepX3", _stepX3, 40);
+ loadDeviceConfigurationElement("stepY1", _stepY1, 2);
+ loadDeviceConfigurationElement("stepY2", _stepY2, 10);
+ loadDeviceConfigurationElement("stepY3", _stepY3, 20);
+ ConfMan.flushToDisk();
+
+ _isSmartphone = CEDevice::isSmartphone();
+
+ // Query SDL for screen size and init screen dependent stuff
+ OSystem_WINCE3::initScreenInfos();
+ create_toolbar();
+ _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone();
+ if (_hasSmartphoneResolution)
+ _panelVisible = false; // init correctly in smartphones
+
+ _screen = NULL;
+}
+
+// Graphics mode consts
+
+// Low end devices 240x320
+
+static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = {
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
+ {0, 0, 0}
+};
+
+// High end device 480x640
+
+static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = {
+ {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
+ {"2x", "2x", GFX_DOUBLESIZE},
+#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :)
+ {"2xsai", "2xSAI", GFX_2XSAI},
+ {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI},
+ {"supereagle", "SuperEagle", GFX_SUPEREAGLE},
+#endif
+ {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X},
+#ifndef _MSC_VER
+ {"hq2x", "HQ2x", GFX_HQ2X},
+ {"tv2x", "TV2x", GFX_TV2X},
+#endif
+ {"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
+ {0, 0, 0}
+};
+
+const OSystem::GraphicsMode *WINCESdlGraphicsManager::getSupportedGraphicsModes() const {
+ if (CEDevice::hasWideResolution())
+ return s_supportedGraphicsModesHigh;
+ else
+ return s_supportedGraphicsModesLow;
+}
+
+bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) {
+ return (f == OSystem::kFeatureVirtualKeyboard);
+}
+
+void WINCESdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return;
+
+ case OSystem::kFeatureVirtualKeyboard:
+ if (_hasSmartphoneResolution)
+ return;
+ _toolbarHighDrawn = false;
+ if (enable) {
+ _panelStateForced = true;
+ if (!_toolbarHandler.visible()) swap_panel_visibility();
+ //_saveToolbarState = _toolbarHandler.visible();
+ _saveActiveToolbar = _toolbarHandler.activeName();
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ _toolbarHandler.setVisible(true);
+ } else if (_panelStateForced) {
+ _panelStateForced = false;
+ _toolbarHandler.setActive(_saveActiveToolbar);
+ //_toolbarHandler.setVisible(_saveToolbarState);
+ }
+ return;
+
+ case OSystem::kFeatureDisableKeyFiltering:
+ if (_hasSmartphoneResolution) {
+ GUI::Actions::Instance()->beginMapping(enable);
+ }
+ return;
+
+ default:
+ SdlGraphicsManager::setFeatureState(f, enable);
+ }
+}
+
+bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) {
+ switch (f) {
+ case OSystem::kFeatureFullscreenMode:
+ return false;
+ case OSystem::kFeatureVirtualKeyboard:
+ return (_panelStateForced);
+ default:
+ return SdlGraphicsManager::getFeatureState(f);
+ }
+}
+
+int WINCESdlGraphicsManager::getDefaultGraphicsMode() const {
+ return GFX_NORMAL;
+}
+
+void WINCESdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
+ if (_hasSmartphoneResolution && h == 240)
+ h = 200; // mainly for the launcher
+
+ if (_isSmartphone && !ConfMan.hasKey("landscape")) {
+ ConfMan.setInt("landscape", 1);
+ ConfMan.flushToDisk();
+ }
+
+ _canBeAspectScaled = false;
+ if (w == 320 && h == 200 && !_hasSmartphoneResolution) {
+ _canBeAspectScaled = true;
+ h = 240; // use the extra 40 pixels height for the toolbar
+ }
+
+ if (h == 400) // touche engine fixup
+ h += 80;
+
+ if (!_hasSmartphoneResolution) {
+ if (h == 240)
+ _toolbarHandler.setOffset(200);
+ else
+ _toolbarHandler.setOffset(400);
+ } else {
+ if (h == 240)
+ _toolbarHandler.setOffset(200);
+ else // 176x220
+ _toolbarHandler.setOffset(0);
+ }
+
+ if (w != (uint) _videoMode.screenWidth || h != (uint) _videoMode.screenHeight)
+ _scalersChanged = false;
+
+ _videoMode.overlayWidth = w;
+ _videoMode.overlayHeight = h;
+
+ SdlGraphicsManager::initSize(w, h, format);
+
+ if (_scalersChanged) {
+ unloadGFXMode();
+ loadGFXMode();
+ _scalersChanged = false;
+ }
+
+ update_game_settings();
+}
+
+void WINCESdlGraphicsManager::loadDeviceConfigurationElement(Common::String element, int &value, int defaultValue) {
+ value = ConfMan.getInt(element, ConfMan.kApplicationDomain);
+ if (!value) {
+ value = defaultValue;
+ ConfMan.setInt(element, value, ConfMan.kApplicationDomain);
+ }
+}
+
+void WINCESdlGraphicsManager::move_cursor_up() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatY)
+ y -= _stepY3;
+ else if (_keyRepeat)
+ y -= _stepY2;
+ else
+ y -= _stepY1;
+
+ if (y < 0)
+ y = 0;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::move_cursor_down() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatY)
+ y += _stepY3;
+ else if (_keyRepeat)
+ y += _stepY2;
+ else
+ y += _stepY1;
+
+ if (y > _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd)
+ y = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::move_cursor_left() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatX)
+ x -= _stepX3;
+ else if (_keyRepeat)
+ x -= _stepX2;
+ else
+ x -= _stepX1;
+
+ if (x < 0)
+ x = 0;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::move_cursor_right() {
+ int x, y;
+ _usesEmulatedMouse = true;
+ retrieve_mouse_location(x, y);
+ if (_keyRepeat > _repeatX)
+ x += _stepX3;
+ else if (_keyRepeat)
+ x += _stepX2;
+ else
+ x += _stepX1;
+
+ if (x > _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd)
+ x = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
+
+ EventsBuffer::simulateMouseMove(x, y);
+}
+
+void WINCESdlGraphicsManager::retrieve_mouse_location(int &x, int &y) {
+ x = _mouseCurState.x;
+ y = _mouseCurState.y;
+
+ x = x * _scaleFactorXm / _scaleFactorXd;
+ y = y * _scaleFactorYm / _scaleFactorYd;
+
+ if (_zoomDown)
+ y -= 240;
+}
+
+void WINCESdlGraphicsManager::switch_zone() {
+ int x, y;
+ int i;
+ retrieve_mouse_location(x, y);
+
+ for (i = 0; i < TOTAL_ZONES; i++)
+ if (x >= _zones[i].x && y >= _zones[i].y &&
+ x <= _zones[i].x + _zones[i].width && y <= _zones[i].y + _zones[i].height) {
+ _mouseXZone[i] = x;
+ _mouseYZone[i] = y;
+ break;
+ }
+ _currentZone = i + 1;
+ if (_currentZone >= TOTAL_ZONES)
+ _currentZone = 0;
+
+ EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]);
+}
+
+void WINCESdlGraphicsManager::add_right_click(bool pushed) {
+ int x, y;
+ retrieve_mouse_location(x, y);
+ EventsBuffer::simulateMouseRightClick(x, y, pushed);
+}
+
+void WINCESdlGraphicsManager::add_left_click(bool pushed) {
+ int x, y;
+ retrieve_mouse_location(x, y);
+ EventsBuffer::simulateMouseLeftClick(x, y, pushed);
+}
+
+bool WINCESdlGraphicsManager::update_scalers() {
+ _videoMode.aspectRatioCorrection = false;
+
+ if (CEDevice::hasPocketPCResolution()) {
+ if (_videoMode.mode != GFX_NORMAL)
+ return false;
+
+ if ((!_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth))
+ || CEDevice::hasSquareQVGAResolution()) {
+ if (OSystem_WINCE3::getScreenWidth() != 320) {
+ _scaleFactorXm = 3;
+ _scaleFactorXd = 4;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = DownscaleHorizByThreeQuarters;
+ } else {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ }
+ } else if (_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
+ if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 6;
+ _scaleFactorYd = 5;
+ _scalerProc = Normal1xAspect;
+ _videoMode.aspectRatioCorrection = true;
+ } else {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ }
+ } else if (_videoMode.screenWidth == 640 && !(OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640))) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 2;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 2;
+ _scalerProc = DownscaleAllByHalf;
+ } else if (_videoMode.screenWidth == 640 && (OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640))) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ }
+
+ return true;
+ } else if (CEDevice::hasWideResolution()) {
+#ifdef USE_ARM_SCALER_ASM
+ if (_videoMode.mode == GFX_DOUBLESIZE && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
+ if (!_panelVisible && !_overlayVisible && _canBeAspectScaled) {
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 12;
+ _scaleFactorYd = 5;
+ _scalerProc = Normal2xAspect;
+ _videoMode.aspectRatioCorrection = true;
+ } else if ((_panelVisible || _overlayVisible) && _canBeAspectScaled) {
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 2;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal2x;
+ }
+ return true;
+ }
+#endif
+ } else if (CEDevice::hasSmartphoneResolution()) {
+ if (_videoMode.mode != GFX_NORMAL)
+ return false;
+
+ if (_videoMode.screenWidth > 320)
+ error("Game resolution not supported on Smartphone");
+#ifdef ARM
+ _scaleFactorXm = 11;
+ _scaleFactorXd = 16;
+#else
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 3;
+#endif
+ _scaleFactorYm = 7;
+ _scaleFactorYd = 8;
+ _scalerProc = SmartphoneLandscape;
+ initZones();
+ return true;
+ }
+
+ return false;
+}
+
+void WINCESdlGraphicsManager::update_game_settings() {
+ Common::String gameid(ConfMan.get("gameid"));
+
+ // Finish panel initialization
+ if (!_panelInitialized && !gameid.empty()) {
+ CEGUI::Panel *panel;
+ _panelInitialized = true;
+ // Add the main panel
+ panel = new CEGUI::Panel(0, 32);
+ panel->setBackground(IMAGE_PANEL);
+
+ // Save
+ panel->add(NAME_ITEM_OPTIONS, new CEGUI::ItemAction(ITEM_OPTIONS, POCKET_ACTION_SAVE));
+ // Skip
+ panel->add(NAME_ITEM_SKIP, new CEGUI::ItemAction(ITEM_SKIP, POCKET_ACTION_SKIP));
+ // sound
+//__XXX__ panel->add(NAME_ITEM_SOUND, new CEGUI::ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &_soundMaster));
+ panel->add(NAME_ITEM_SOUND, new CEGUI::ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &OSystem_WINCE3::_soundMaster));
+
+ // bind keys
+ panel->add(NAME_ITEM_BINDKEYS, new CEGUI::ItemAction(ITEM_BINDKEYS, POCKET_ACTION_BINDKEYS));
+ // portrait/landscape - screen dependent
+ // FIXME : will still display the portrait/landscape icon when using a scaler (but will be disabled)
+ if (ConfMan.hasKey("landscape")) {
+ if (ConfMan.get("landscape")[0] > 57) {
+ _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
+ //ConfMan.removeKey("landscape", "");
+ ConfMan.setInt("landscape", _orientationLandscape);
+ } else
+ _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
+ } else {
+ _newOrientation = _orientationLandscape = 0;
+ }
+ panel->add(NAME_ITEM_ORIENTATION, new CEGUI::ItemSwitch(ITEM_VIEW_LANDSCAPE, ITEM_VIEW_PORTRAIT, &_newOrientation, 2));
+ _toolbarHandler.add(NAME_MAIN_PANEL, *panel);
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ _toolbarHandler.setVisible(true);
+
+ if (_videoMode.mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) {
+ setGraphicsMode(GFX_NORMAL);
+ hotswapGFXMode();
+ }
+
+ if (_hasSmartphoneResolution)
+ panel->setVisible(false);
+
+ _saveToolbarState = true;
+ }
+
+ if (ConfMan.hasKey("no_doubletap_rightclick"))
+ _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick");
+}
+
+void WINCESdlGraphicsManager::internUpdateScreen() {
+ SDL_Surface *srcSurf, *origSurf;
+ static bool old_overlayVisible = false;
+ int numRectsOut = 0;
+ int16 routx, routy, routw, routh, stretch, shakestretch;
+
+ assert(_hwscreen != NULL);
+
+ // bail if the application is minimized, be nice to OS
+ if (!_hasfocus) {
+ Sleep(20);
+ return;
+ }
+
+ // If the shake position changed, fill the dirty area with blackness
+ if (_currentShakePos != _newShakePos) {
+ SDL_Rect blackrect = {0, 0, _videoMode.screenWidth *_scaleFactorXm / _scaleFactorXd, _newShakePos *_scaleFactorYm / _scaleFactorYd};
+ if (_videoMode.aspectRatioCorrection)
+ blackrect.h = real2Aspect(blackrect.h - 1) + 1;
+ SDL_FillRect(_hwscreen, &blackrect, 0);
+ _currentShakePos = _newShakePos;
+ _forceFull = true;
+ }
+
+ // Make sure the mouse is drawn, if it should be drawn.
+ drawMouse();
+
+ // Check whether the palette was changed in the meantime and update the
+ // screen surface accordingly.
+ if (_paletteDirtyEnd != 0) {
+ SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart);
+ _paletteDirtyEnd = 0;
+ _forceFull = true;
+ }
+
+ if (!_overlayVisible) {
+ origSurf = _screen;
+ srcSurf = _tmpscreen;
+ } else {
+ origSurf = _overlayscreen;
+ srcSurf = _tmpscreen2;
+ }
+
+ if (old_overlayVisible != _overlayVisible) {
+ old_overlayVisible = _overlayVisible;
+ update_scalers();
+ }
+
+ // Force a full redraw if requested
+ if (_forceFull) {
+ _numDirtyRects = 1;
+
+ _dirtyRectList[0].x = 0;
+ if (!_zoomDown)
+ _dirtyRectList[0].y = 0;
+ else
+ _dirtyRectList[0].y = _videoMode.screenHeight / 2;
+ _dirtyRectList[0].w = _videoMode.screenWidth;
+ if (!_zoomUp && !_zoomDown)
+ _dirtyRectList[0].h = _videoMode.screenHeight;
+ else
+ _dirtyRectList[0].h = _videoMode.screenHeight / 2;
+
+ _toolbarHandler.forceRedraw();
+ }
+
+ // Only draw anything if necessary
+ if (_numDirtyRects > 0) {
+
+ SDL_Rect *r, *rout;
+ SDL_Rect dst;
+ uint32 srcPitch, dstPitch;
+ SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects;
+ bool toolbarVisible = _toolbarHandler.visible();
+ int toolbarOffset = _toolbarHandler.getOffset();
+
+ for (r = _dirtyRectList; r != last_rect; ++r) {
+ dst = *r;
+ dst.x++; // Shift rect by one since 2xSai needs to access the data around
+ dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
+ // NOTE: This is also known as BLACK MAGIC, copied from the sdl backend
+ if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+
+ SDL_LockSurface(srcSurf);
+ SDL_LockSurface(_hwscreen);
+
+ srcPitch = srcSurf->pitch;
+ dstPitch = _hwscreen->pitch;
+
+ for (r = _dirtyRectList, rout = _dirtyRectOut; r != last_rect; ++r) {
+
+ // always clamp to enclosing, downsampled-grid-aligned rect in the downscaled image
+ if (_scaleFactorXd != 1) {
+ stretch = r->x % _scaleFactorXd;
+ r->x -= stretch;
+ r->w += stretch;
+ r->w = (r->x + r->w + _scaleFactorXd - 1) / _scaleFactorXd * _scaleFactorXd - r->x;
+ }
+ if (_scaleFactorYd != 1) {
+ stretch = r->y % _scaleFactorYd;
+ r->y -= stretch;
+ r->h += stretch;
+ r->h = (r->y + r->h + _scaleFactorYd - 1) / _scaleFactorYd * _scaleFactorYd - r->y;
+ }
+
+ // transform
+ shakestretch = _currentShakePos * _scaleFactorYm / _scaleFactorYd;
+ routx = r->x * _scaleFactorXm / _scaleFactorXd; // locate position in scaled screen
+ routy = r->y * _scaleFactorYm / _scaleFactorYd + shakestretch; // adjust for shake offset
+ routw = r->w * _scaleFactorXm / _scaleFactorXd;
+ routh = r->h * _scaleFactorYm / _scaleFactorYd - shakestretch;
+
+ // clipping destination rectangle inside device screen (more strict, also more tricky but more stable)
+ // note that all current scalers do not make dst rect exceed left/right, unless chosen badly (FIXME)
+ if (_zoomDown) routy -= 240; // adjust for zoom position
+ if (routy + routh < 0) continue;
+ if (routy < 0) {
+ routh += routy;
+ r->y -= routy * _scaleFactorYd / _scaleFactorYm;
+ routy = 0;
+ r->h = routh * _scaleFactorYd / _scaleFactorYm;
+ }
+ if (_orientationLandscape) {
+ if (routy > OSystem_WINCE3::getScreenWidth()) continue;
+ if (routy + routh > OSystem_WINCE3::getScreenWidth()) {
+ routh = OSystem_WINCE3::getScreenWidth() - routy;
+ r->h = routh * _scaleFactorYd / _scaleFactorYm;
+ }
+ } else {
+ if (routy > OSystem_WINCE3::getScreenHeight()) continue;
+ if (routy + routh > OSystem_WINCE3::getScreenHeight()) {
+ routh = OSystem_WINCE3::getScreenHeight() - routy;
+ r->h = routh * _scaleFactorYd / _scaleFactorYm;
+ }
+ }
+
+ // check if the toolbar is overwritten
+ if (toolbarVisible && r->y + r->h >= toolbarOffset)
+ _toolbarHandler.forceRedraw();
+
+ // blit it (with added voodoo from the sdl backend, shifting the source rect again)
+ _scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
+ (byte *)_hwscreen->pixels + routx * 2 + routy * dstPitch, dstPitch,
+ r->w, r->h - _currentShakePos);
+
+ // add this rect to output
+ rout->x = routx;
+ rout->y = routy - shakestretch;
+ rout->w = routw;
+ rout->h = routh + shakestretch;
+ numRectsOut++;
+ rout++;
+
+ }
+ SDL_UnlockSurface(srcSurf);
+ SDL_UnlockSurface(_hwscreen);
+ }
+ // Add the toolbar if needed
+ SDL_Rect toolbar_rect[1];
+ if (_panelVisible && _toolbarHandler.draw(_toolbarLow, &toolbar_rect[0])) {
+ // It can be drawn, scale it
+ uint32 srcPitch, dstPitch;
+ SDL_Surface *toolbarSurface;
+ ScalerProc *toolbarScaler;
+
+ if (_videoMode.screenHeight > 240) {
+ if (!_toolbarHighDrawn) {
+ // Resize the toolbar
+ SDL_LockSurface(_toolbarLow);
+ SDL_LockSurface(_toolbarHigh);
+ Normal2x((byte *)_toolbarLow->pixels, _toolbarLow->pitch, (byte *)_toolbarHigh->pixels, _toolbarHigh->pitch, toolbar_rect[0].w, toolbar_rect[0].h);
+ SDL_UnlockSurface(_toolbarHigh);
+ SDL_UnlockSurface(_toolbarLow);
+ _toolbarHighDrawn = true;
+ }
+ toolbar_rect[0].w *= 2;
+ toolbar_rect[0].h *= 2;
+ toolbarSurface = _toolbarHigh;
+ } else
+ toolbarSurface = _toolbarLow;
+
+ drawToolbarMouse(toolbarSurface, true); // draw toolbar mouse if applicable
+
+ // Apply the appropriate scaler
+ SDL_LockSurface(toolbarSurface);
+ SDL_LockSurface(_hwscreen);
+ srcPitch = toolbarSurface->pitch;
+ dstPitch = _hwscreen->pitch;
+
+ toolbarScaler = _scalerProc;
+ if (_videoMode.scaleFactor == 2)
+ toolbarScaler = Normal2x;
+ else if (_videoMode.scaleFactor == 3)
+ toolbarScaler = Normal3x;
+ toolbarScaler((byte *)toolbarSurface->pixels, srcPitch,
+ (byte *)_hwscreen->pixels + (_toolbarHandler.getOffset() * _scaleFactorYm / _scaleFactorYd * dstPitch),
+ dstPitch, toolbar_rect[0].w, toolbar_rect[0].h);
+ SDL_UnlockSurface(toolbarSurface);
+ SDL_UnlockSurface(_hwscreen);
+
+ // And blit it
+ toolbar_rect[0].y = _toolbarHandler.getOffset();
+ toolbar_rect[0].x = toolbar_rect[0].x * _scaleFactorXm / _scaleFactorXd;
+ toolbar_rect[0].y = toolbar_rect[0].y * _scaleFactorYm / _scaleFactorYd;
+ toolbar_rect[0].w = toolbar_rect[0].w * _scaleFactorXm / _scaleFactorXd;
+ toolbar_rect[0].h = toolbar_rect[0].h * _scaleFactorYm / _scaleFactorYd;
+
+ SDL_UpdateRects(_hwscreen, 1, toolbar_rect);
+
+ drawToolbarMouse(toolbarSurface, false); // undraw toolbar mouse
+ }
+
+ // Finally, blit all our changes to the screen
+ if (numRectsOut > 0)
+ SDL_UpdateRects(_hwscreen, numRectsOut, _dirtyRectOut);
+
+ _numDirtyRects = 0;
+ _forceFull = false;
+}
+
+bool WINCESdlGraphicsManager::setGraphicsMode(int mode) {
+
+ Common::StackLock lock(_graphicsMutex);
+ int oldScaleFactorXm = _scaleFactorXm;
+ int oldScaleFactorXd = _scaleFactorXd;
+ int oldScaleFactorYm = _scaleFactorYm;
+ int oldScaleFactorYd = _scaleFactorYd;
+
+ _scaleFactorXm = -1;
+ _scaleFactorXd = -1;
+ _scaleFactorYm = -1;
+ _scaleFactorYd = -1;
+
+ if (ConfMan.hasKey("landscape"))
+ if (ConfMan.get("landscape")[0] > 57) {
+ _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
+ ConfMan.setInt("landscape", _orientationLandscape);
+ } else
+ _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
+ else
+ _newOrientation = _orientationLandscape = 0;
+
+ if (OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640) && mode)
+ _scaleFactorXm = -1;
+
+ if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape)
+ _videoMode.mode = GFX_NORMAL;
+ else
+ _videoMode.mode = mode;
+
+ if (_scaleFactorXm < 0) {
+ /* Standard scalers, from the SDL backend */
+ switch (_videoMode.mode) {
+ case GFX_NORMAL:
+ _videoMode.scaleFactor = 1;
+ _scalerProc = Normal1x;
+ break;
+ case GFX_DOUBLESIZE:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = Normal2x;
+ break;
+ case GFX_TRIPLESIZE:
+ _videoMode.scaleFactor = 3;
+ _scalerProc = Normal3x;
+ break;
+ case GFX_2XSAI:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = _2xSaI;
+ break;
+ case GFX_SUPER2XSAI:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = Super2xSaI;
+ break;
+ case GFX_SUPEREAGLE:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = SuperEagle;
+ break;
+ case GFX_ADVMAME2X:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = AdvMame2x;
+ break;
+ case GFX_ADVMAME3X:
+ _videoMode.scaleFactor = 3;
+ _scalerProc = AdvMame3x;
+ break;
+#ifdef USE_HQ_SCALERS
+ case GFX_HQ2X:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = HQ2x;
+ break;
+ case GFX_HQ3X:
+ _videoMode.scaleFactor = 3;
+ _scalerProc = HQ3x;
+ break;
+#endif
+ case GFX_TV2X:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = TV2x;
+ break;
+ case GFX_DOTMATRIX:
+ _videoMode.scaleFactor = 2;
+ _scalerProc = DotMatrix;
+ break;
+
+ default:
+ error("unknown gfx mode %d", mode);
+ }
+ }
+
+ // Check if the scaler can be accepted, if not get back to normal scaler
+ if (_videoMode.scaleFactor && ((_videoMode.scaleFactor * _videoMode.screenWidth > OSystem_WINCE3::getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenWidth > OSystem_WINCE3::getScreenHeight())
+ || (_videoMode.scaleFactor * _videoMode.screenHeight > OSystem_WINCE3::getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenHeight > OSystem_WINCE3::getScreenHeight()))) {
+ _videoMode.scaleFactor = 1;
+ _scalerProc = Normal1x;
+ }
+
+ // Common scaler system was used
+ if (_scaleFactorXm < 0) {
+ _scaleFactorXm = _videoMode.scaleFactor;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = _videoMode.scaleFactor;
+ _scaleFactorYd = 1;
+ }
+
+ _forceFull = true;
+
+ if (oldScaleFactorXm != _scaleFactorXm ||
+ oldScaleFactorXd != _scaleFactorXd ||
+ oldScaleFactorYm != _scaleFactorYm ||
+ oldScaleFactorYd != _scaleFactorYd) {
+ _scalersChanged = true;
+ } else
+ _scalersChanged = false;
+
+
+ return true;
+
+}
+
+bool WINCESdlGraphicsManager::loadGFXMode() {
+ int displayWidth;
+ int displayHeight;
+ unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE;
+
+ _videoMode.fullscreen = true; // forced
+ _forceFull = true;
+
+ _tmpscreen = NULL;
+
+ // Recompute scalers if necessary
+ update_scalers();
+
+ // Create the surface that contains the 8 bit game data
+ _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
+ if (_screen == NULL)
+ error("_screen failed (%s)", SDL_GetError());
+
+ // Create the surface that contains the scaled graphics in 16 bit mode
+ // Always use full screen mode to have a "clean screen"
+ if (!_videoMode.aspectRatioCorrection) {
+ displayWidth = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
+ displayHeight = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
+ } else {
+ displayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ displayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+ }
+
+ switch (_orientationLandscape) {
+ case 1:
+ flags |= SDL_LANDSCVIDEO;
+ break;
+ case 2:
+ flags |= SDL_INVLNDVIDEO;
+ break;
+ default:
+ flags |= SDL_PORTRTVIDEO;
+ }
+ _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags);
+
+ if (_hwscreen == NULL) {
+ warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
+ g_system->quit();
+ }
+
+ // see what orientation sdl finally accepted
+ if (_hwscreen->flags & SDL_PORTRTVIDEO)
+ _orientationLandscape = _newOrientation = 0;
+ else if (_hwscreen->flags & SDL_LANDSCVIDEO)
+ _orientationLandscape = _newOrientation = 1;
+ else
+ _orientationLandscape = _newOrientation = 2;
+
+ // Create the surface used for the graphics in 16 bit before scaling, and also the overlay
+ // Distinguish 555 and 565 mode
+ if (_hwscreen->format->Rmask == 0x7C00)
+ InitScalers(555);
+ else
+ InitScalers(565);
+ _overlayFormat.bytesPerPixel = _hwscreen->format->BytesPerPixel;
+ _overlayFormat.rLoss = _hwscreen->format->Rloss;
+ _overlayFormat.gLoss = _hwscreen->format->Gloss;
+ _overlayFormat.bLoss = _hwscreen->format->Bloss;
+ _overlayFormat.aLoss = _hwscreen->format->Aloss;
+ _overlayFormat.rShift = _hwscreen->format->Rshift;
+ _overlayFormat.gShift = _hwscreen->format->Gshift;
+ _overlayFormat.bShift = _hwscreen->format->Bshift;
+ _overlayFormat.aShift = _hwscreen->format->Ashift;
+
+ // Need some extra bytes around when using 2xSaI
+ _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
+
+ if (_tmpscreen == NULL)
+ error("_tmpscreen creation failed (%s)", SDL_GetError());
+
+ // Overlay
+ if (CEDevice::hasDesktopResolution()) {
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0);
+ if (_overlayscreen == NULL)
+ error("_overlayscreen failed (%s)", SDL_GetError());
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0);
+ if (_tmpscreen2 == NULL)
+ error("_tmpscreen2 failed (%s)", SDL_GetError());
+ } else {
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, 0, 0, 0, 0);
+ if (_overlayscreen == NULL)
+ error("_overlayscreen failed (%s)", SDL_GetError());
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, 0, 0, 0, 0);
+ if (_tmpscreen2 == NULL)
+ error("_tmpscreen2 failed (%s)", SDL_GetError());
+ }
+
+ // Toolbar
+ _toolbarHighDrawn = false;
+ uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16)); // *not* leaking memory here
+ _toolbarLow = SDL_CreateRGBSurfaceFrom(toolbar_screen, 320, 40, 16, 320 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
+
+ if (_toolbarLow == NULL)
+ error("_toolbarLow failed (%s)", SDL_GetError());
+
+ if (_videoMode.screenHeight > 240) {
+ uint16 *toolbar_screen_high = (uint16 *)calloc(640 * 80, sizeof(uint16));
+ _toolbarHigh = SDL_CreateRGBSurfaceFrom(toolbar_screen_high, 640, 80, 16, 640 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
+
+ if (_toolbarHigh == NULL)
+ error("_toolbarHigh failed (%s)", SDL_GetError());
+ } else
+ _toolbarHigh = NULL;
+
+ // keyboard cursor control, some other better place for it?
+ _sdlEventSource->resetKeyboadEmulation(_videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd - 1, _videoMode.screenHeight * _scaleFactorXm / _scaleFactorXd - 1);
+
+ return true;
+}
+
+void WINCESdlGraphicsManager::unloadGFXMode() {
+ if (_screen) {
+ SDL_FreeSurface(_screen);
+ _screen = NULL;
+ }
+
+ if (_hwscreen) {
+ SDL_FreeSurface(_hwscreen);
+ _hwscreen = NULL;
+ }
+
+ if (_tmpscreen) {
+ SDL_FreeSurface(_tmpscreen);
+ _tmpscreen = NULL;
+ }
+}
+
+bool WINCESdlGraphicsManager::hotswapGFXMode() {
+ if (!_screen)
+ return false;
+
+ // Keep around the old _screen & _tmpscreen so we can restore the screen data
+ // after the mode switch. (also for the overlay)
+ SDL_Surface *old_screen = _screen;
+ SDL_Surface *old_tmpscreen = _tmpscreen;
+ SDL_Surface *old_overlayscreen = _overlayscreen;
+ SDL_Surface *old_tmpscreen2 = _tmpscreen2;
+
+ // Release the HW screen surface
+ SDL_FreeSurface(_hwscreen);
+
+ // Release toolbars
+ free(_toolbarLow->pixels);
+ SDL_FreeSurface(_toolbarLow);
+ if (_toolbarHigh) {
+ free(_toolbarHigh->pixels);
+ SDL_FreeSurface(_toolbarHigh);
+ }
+
+ // Setup the new GFX mode
+ if (!loadGFXMode()) {
+ unloadGFXMode();
+
+ _screen = old_screen;
+ _overlayscreen = old_overlayscreen;
+
+ return false;
+ }
+
+ // reset palette
+ SDL_SetColors(_screen, _currentPalette, 0, 256);
+
+ // Restore old screen content
+ SDL_BlitSurface(old_screen, NULL, _screen, NULL);
+ SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
+ if (_overlayVisible) {
+ SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
+ SDL_BlitSurface(old_tmpscreen2, NULL, _tmpscreen2, NULL);
+ }
+
+ // Free the old surfaces
+ SDL_FreeSurface(old_screen);
+ SDL_FreeSurface(old_tmpscreen);
+ SDL_FreeSurface(old_overlayscreen);
+ SDL_FreeSurface(old_tmpscreen2);
+
+ // Blit everything back to the screen
+ _toolbarHighDrawn = false;
+ internUpdateScreen();
+
+ // Make sure that a Common::EVENT_SCREEN_CHANGED gets sent later -> FIXME this crashes when no game has been loaded.
+// _modeChanged = true;
+
+ return true;
+}
+
+bool WINCESdlGraphicsManager::saveScreenshot(const char *filename) {
+ assert(_hwscreen != NULL);
+
+ Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+ SDL_SaveBMP(_hwscreen, filename);
+ return true;
+}
+
+void WINCESdlGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
+ assert(_transactionMode == kTransactionNone);
+
+ if (_overlayscreen == NULL)
+ return;
+
+ // Clip the coordinates
+ if (x < 0) {
+ w += x;
+ buf -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ buf -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _videoMode.overlayWidth - x) {
+ w = _videoMode.overlayWidth - x;
+ }
+
+ if (h > _videoMode.overlayHeight - y) {
+ h = _videoMode.overlayHeight - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Mark the modified region as dirty
+ addDirtyRect(x, y, w, h);
+
+ undrawMouse();
+
+ if (SDL_LockSurface(_overlayscreen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
+ do {
+ memcpy(dst, buf, w * 2);
+ dst += _overlayscreen->pitch;
+ buf += pitch;
+ } while (--h);
+
+ SDL_UnlockSurface(_overlayscreen);
+}
+
+void WINCESdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
+ assert(_transactionMode == kTransactionNone);
+ assert(src);
+
+ if (_screen == NULL)
+ return;
+
+ Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+
+ /* Clip the coordinates */
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ src -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _videoMode.screenWidth - x) {
+ w = _videoMode.screenWidth - x;
+ }
+
+ if (h > _videoMode.screenHeight - y) {
+ h = _videoMode.screenHeight - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ addDirtyRect(x, y, w, h);
+
+ undrawMouse();
+
+ // Try to lock the screen surface
+ if (SDL_LockSurface(_screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
+
+ if (_videoMode.screenWidth == pitch && pitch == w) {
+ memcpy(dst, src, h * w);
+ } else {
+ do {
+ memcpy(dst, src, w);
+ src += pitch;
+ dst += _videoMode.screenWidth;
+ } while (--h);
+ }
+
+ // Unlock the screen surface
+ SDL_UnlockSurface(_screen);
+}
+
+void WINCESdlGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
+
+ undrawMouse();
+ if (w == 0 || h == 0)
+ return;
+
+ _mouseCurState.w = w;
+ _mouseCurState.h = h;
+
+ _mouseHotspotX = hotspot_x;
+ _mouseHotspotY = hotspot_y;
+
+ _mouseKeyColor = keycolor;
+
+ free(_mouseData);
+
+ _mouseData = (byte *) malloc(w * h);
+ memcpy(_mouseData, buf, w * h);
+
+ if (w > _mouseBackupDim || h > _mouseBackupDim) {
+ // mouse has been undrawn, adjust sprite backup area
+ free(_mouseBackupOld);
+ free(_mouseBackupToolbar);
+ uint16 tmp = (w > h) ? w : h;
+ _mouseBackupOld = (byte *) malloc(tmp * tmp * 2); // can hold 8bpp (playfield) or 16bpp (overlay) data
+ _mouseBackupToolbar = (uint16 *) malloc(tmp * tmp * 2); // 16 bpp
+ _mouseBackupDim = tmp;
+ }
+}
+
+void WINCESdlGraphicsManager::adjustMouseEvent(const Common::Event &event) {
+ if (!event.synthetic) {
+ Common::Event newEvent(event);
+ newEvent.synthetic = true;
+ if (!_overlayVisible) {
+ /*
+ newEvent.mouse.x = newEvent.mouse.x * _scaleFactorXd / _scaleFactorXm;
+ newEvent.mouse.y = newEvent.mouse.y * _scaleFactorYd / _scaleFactorYm;
+ newEvent.mouse.x /= _videoMode.scaleFactor;
+ newEvent.mouse.y /= _videoMode.scaleFactor;
+ */
+ if (_videoMode.aspectRatioCorrection)
+ newEvent.mouse.y = aspect2Real(newEvent.mouse.y);
+ }
+ g_system->getEventManager()->pushEvent(newEvent);
+ }
+}
+
+void WINCESdlGraphicsManager::setMousePos(int x, int y) {
+ if (x != _mouseCurState.x || y != _mouseCurState.y) {
+ undrawMouse();
+ _mouseCurState.x = x;
+ _mouseCurState.y = y;
+ updateScreen();
+ }
+}
+
+Graphics::Surface *WINCESdlGraphicsManager::lockScreen() {
+ // Make sure mouse pointer is not painted over the playfield at the time of locking
+ undrawMouse();
+ return SdlGraphicsManager::lockScreen();
+}
+
+void WINCESdlGraphicsManager::showOverlay() {
+ assert(_transactionMode == kTransactionNone);
+
+ if (_overlayVisible)
+ return;
+
+ undrawMouse();
+ _overlayVisible = true;
+ update_scalers();
+ clearOverlay();
+}
+
+void WINCESdlGraphicsManager::hideOverlay() {
+ assert(_transactionMode == kTransactionNone);
+
+ if (!_overlayVisible)
+ return;
+
+ undrawMouse();
+ _overlayVisible = false;
+ clearOverlay();
+ _forceFull = true;
+}
+
+void WINCESdlGraphicsManager::blitCursor() {
+}
+
+void WINCESdlGraphicsManager::drawToolbarMouse(SDL_Surface *surf, bool draw) {
+
+ if (!_mouseData || !_usesEmulatedMouse)
+ return;
+
+ int x = _mouseCurState.x - _mouseHotspotX;
+ int y = _mouseCurState.y - _mouseHotspotY - _toolbarHandler.getOffset();
+ int w = _mouseCurState.w;
+ int h = _mouseCurState.h;
+ byte color;
+ const byte *src = _mouseData;
+ int width;
+
+ // clip
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ src -= y * _mouseCurState.w;
+ y = 0;
+ }
+ if (w > surf->w - x)
+ w = surf->w - x;
+ if (h > surf->h - y)
+ h = surf->h - y;
+ if (w <= 0 || h <= 0)
+ return;
+
+ if (SDL_LockSurface(surf) == -1)
+ error("SDL_LockSurface failed at internDrawToolbarMouse: %s", SDL_GetError());
+
+ uint16 *bak = _mouseBackupToolbar; // toolbar surfaces are 16bpp
+ uint16 *dst;
+ dst = (uint16 *)surf->pixels + y * surf->w + x;
+
+ if (draw) { // blit it
+ while (h > 0) {
+ width = w;
+ while (width > 0) {
+ *bak++ = *dst;
+ color = *src++;
+ if (color != _mouseKeyColor) // transparent color
+ *dst = 0xFFFF;
+ dst++;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += _mouseBackupDim - w;
+ dst += surf->w - w;
+ h--;
+ }
+ } else { // restore bg
+ for (y = 0; y < h; ++y, bak += _mouseBackupDim, dst += surf->w)
+ memcpy(dst, bak, w << 1);
+ }
+
+ SDL_UnlockSurface(surf);
+}
+
+void WINCESdlGraphicsManager::warpMouse(int x, int y) {
+ if (_mouseCurState.x != x || _mouseCurState.y != y) {
+ SDL_WarpMouse(x * _scaleFactorXm / _scaleFactorXd, y * _scaleFactorYm / _scaleFactorYd);
+
+ // SDL_WarpMouse() generates a mouse movement event, so
+ // set_mouse_pos() would be called eventually. However, the
+ // cannon script in CoMI calls this function twice each time
+ // the cannon is reloaded. Unless we update the mouse position
+ // immediately the second call is ignored, causing the cannon
+ // to change its aim.
+
+ setMousePos(x, y);
+ }
+}
+
+void WINCESdlGraphicsManager::unlockScreen() {
+ SdlGraphicsManager::unlockScreen();
+}
+
+void WINCESdlGraphicsManager::internDrawMouse() {
+ if (!_mouseNeedsRedraw || !_mouseVisible || !_mouseData)
+ return;
+
+ int x = _mouseCurState.x - _mouseHotspotX;
+ int y = _mouseCurState.y - _mouseHotspotY;
+ int w = _mouseCurState.w;
+ int h = _mouseCurState.h;
+ byte color;
+ const byte *src = _mouseData; // Image representing the mouse
+ int width;
+
+ // clip the mouse rect, and adjust the src pointer accordingly
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+ if (y < 0) {
+ h += y;
+ src -= y * _mouseCurState.w;
+ y = 0;
+ }
+
+ if (w > _videoMode.screenWidth - x)
+ w = _videoMode.screenWidth - x;
+ if (h > _videoMode.screenHeight - y)
+ h = _videoMode.screenHeight - y;
+
+ // Quick check to see if anything has to be drawn at all
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Draw the mouse cursor; backup the covered area in "bak"
+ if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ // Mark as dirty
+ addDirtyRect(x, y, w, h);
+
+ if (!_overlayVisible) {
+ byte *bak = _mouseBackupOld; // Surface used to backup the area obscured by the mouse
+ byte *dst; // Surface we are drawing into
+
+ dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
+ while (h > 0) {
+ width = w;
+ while (width > 0) {
+ *bak++ = *dst;
+ color = *src++;
+ if (color != _mouseKeyColor) // transparent, don't draw
+ *dst = color;
+ dst++;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += _mouseBackupDim - w;
+ dst += _videoMode.screenWidth - w;
+ h--;
+ }
+
+ } else {
+ uint16 *bak = (uint16 *)_mouseBackupOld; // Surface used to backup the area obscured by the mouse
+ byte *dst; // Surface we are drawing into
+
+ dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2;
+ while (h > 0) {
+ width = w;
+ while (width > 0) {
+ *bak++ = *(uint16 *)dst;
+ color = *src++;
+ if (color != 0xFF) // 0xFF = transparent, don't draw
+ *(uint16 *)dst = SDL_MapRGB(_overlayscreen->format, _currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
+ dst += 2;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += _mouseBackupDim - w;
+ dst += _overlayscreen->pitch - w * 2;
+ h--;
+ }
+ }
+
+ SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
+
+ // Finally, set the flag to indicate the mouse has been drawn
+ _mouseNeedsRedraw = false;
+}
+
+void WINCESdlGraphicsManager::undrawMouse() {
+ assert(_transactionMode == kTransactionNone);
+
+ if (_mouseNeedsRedraw)
+ return;
+
+ int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
+ int old_mouse_y = _mouseCurState.y - _mouseHotspotY;
+ int old_mouse_w = _mouseCurState.w;
+ int old_mouse_h = _mouseCurState.h;
+
+ // clip the mouse rect, and adjust the src pointer accordingly
+ if (old_mouse_x < 0) {
+ old_mouse_w += old_mouse_x;
+ old_mouse_x = 0;
+ }
+ if (old_mouse_y < 0) {
+ old_mouse_h += old_mouse_y;
+ old_mouse_y = 0;
+ }
+
+ if (old_mouse_w > _videoMode.screenWidth - old_mouse_x)
+ old_mouse_w = _videoMode.screenWidth - old_mouse_x;
+ if (old_mouse_h > _videoMode.screenHeight - old_mouse_y)
+ old_mouse_h = _videoMode.screenHeight - old_mouse_y;
+
+ // Quick check to see if anything has to be drawn at all
+ if (old_mouse_w <= 0 || old_mouse_h <= 0)
+ return;
+
+
+ if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
+ error("SDL_LockSurface failed: %s", SDL_GetError());
+
+ int y;
+ if (!_overlayVisible) {
+ byte *dst, *bak = _mouseBackupOld;
+
+ // No need to do clipping here, since drawMouse() did that already
+ dst = (byte *)_screen->pixels + old_mouse_y * _videoMode.screenWidth + old_mouse_x;
+ for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _videoMode.screenWidth)
+ memcpy(dst, bak, old_mouse_w);
+ } else {
+ byte *dst;
+ uint16 *bak = (uint16 *)_mouseBackupOld;
+
+ // No need to do clipping here, since drawMouse() did that already
+ dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2;
+ for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _overlayscreen->pitch)
+ memcpy(dst, bak, old_mouse_w << 1);
+ }
+
+ addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
+
+ SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
+
+ _mouseNeedsRedraw = true;
+}
+
+void WINCESdlGraphicsManager::drawMouse() {
+ if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset() && !_usesEmulatedMouse) && !_forceHideMouse)
+ internDrawMouse();
+}
+
+bool WINCESdlGraphicsManager::showMouse(bool visible) {
+ if (_mouseVisible == visible)
+ return visible;
+
+ if (visible == false)
+ undrawMouse();
+
+ bool last = _mouseVisible;
+ _mouseVisible = visible;
+ _mouseNeedsRedraw = true;
+
+ return last;
+}
+
+void WINCESdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
+
+ if (_forceFull || _paletteDirtyEnd)
+ return;
+
+ SdlGraphicsManager::addDirtyRect(x, y, w, h, false);
+}
+
+void WINCESdlGraphicsManager::swap_panel_visibility() {
+ //if (!_forcePanelInvisible && !_panelStateForced) {
+ if (_zoomDown || _zoomUp)
+ return;
+
+ if (_panelVisible) {
+ if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD)
+ _panelVisible = !_panelVisible;
+ else
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ } else {
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ _panelVisible = !_panelVisible;
+ }
+ _toolbarHandler.setVisible(_panelVisible);
+ _toolbarHighDrawn = false;
+
+ if (_videoMode.screenHeight > 240)
+ addDirtyRect(0, 400, 640, 80);
+ else
+ addDirtyRect(0, 200, 320, 40);
+
+ if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
+ internUpdateScreen();
+ else {
+ update_scalers();
+ hotswapGFXMode();
+ }
+ //}
+}
+
+void WINCESdlGraphicsManager::swap_panel() {
+ _toolbarHighDrawn = false;
+ //if (!_panelStateForced) {
+ if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ else
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+
+ if (_videoMode.screenHeight > 240)
+ addDirtyRect(0, 400, 640, 80);
+ else
+ addDirtyRect(0, 200, 320, 40);
+
+ _toolbarHandler.setVisible(true);
+ if (!_panelVisible) {
+ _panelVisible = true;
+ update_scalers();
+ hotswapGFXMode();
+ }
+ //}
+}
+
+void WINCESdlGraphicsManager::swap_smartphone_keyboard() {
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ _panelVisible = !_panelVisible;
+ _toolbarHandler.setVisible(_panelVisible);
+ if (_videoMode.screenHeight > 240)
+ addDirtyRect(0, 0, 640, 80);
+ else
+ addDirtyRect(0, 0, 320, 40);
+ internUpdateScreen();
+}
+
+void WINCESdlGraphicsManager::swap_zoom_up() {
+ if (_zoomUp) {
+ // restore visibility
+ _toolbarHandler.setVisible(_saveToolbarZoom);
+ // restore scaler
+ _scaleFactorYd = 2;
+ _scalerProc = DownscaleAllByHalf;
+ _zoomUp = false;
+ _zoomDown = false;
+ } else {
+ // only active if running on a PocketPC
+ if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
+ return;
+ if (_scalerProc == DownscaleAllByHalf) {
+ _saveToolbarZoom = _toolbarHandler.visible();
+ _toolbarHandler.setVisible(false);
+ // set zoom scaler
+ _scaleFactorYd = 1;
+ _scalerProc = DownscaleHorizByHalf;
+ }
+
+ _zoomDown = false;
+ _zoomUp = true;
+ }
+ // redraw whole screen
+ addDirtyRect(0, 0, 640, 480);
+ internUpdateScreen();
+}
+
+void WINCESdlGraphicsManager::swap_zoom_down() {
+ if (_zoomDown) {
+ // restore visibility
+ _toolbarHandler.setVisible(_saveToolbarZoom);
+ // restore scaler
+ _scaleFactorYd = 2;
+ _scalerProc = DownscaleAllByHalf;
+ _zoomDown = false;
+ _zoomUp = false;
+ } else {
+ // only active if running on a PocketPC
+ if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
+ return;
+ if (_scalerProc == DownscaleAllByHalf) {
+ _saveToolbarZoom = _toolbarHandler.visible();
+ _toolbarHandler.setVisible(false);
+ // set zoom scaler
+ _scaleFactorYd = 1;
+ _scalerProc = DownscaleHorizByHalf;
+ }
+
+ _zoomUp = false;
+ _zoomDown = true;
+ }
+ // redraw whole screen
+ addDirtyRect(0, 0, 640, 480);
+ internUpdateScreen();
+}
+
+void WINCESdlGraphicsManager::swap_mouse_visibility() {
+ _forceHideMouse = !_forceHideMouse;
+ if (_forceHideMouse)
+ undrawMouse();
+}
+
+// Smartphone actions
+void WINCESdlGraphicsManager::initZones() {
+ int i;
+
+ _currentZone = 0;
+ for (i = 0; i < TOTAL_ZONES; i++) {
+ _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)) * _scaleFactorXm / _scaleFactorXd;
+ _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)) * _scaleFactorYm / _scaleFactorYd;
+ }
+}
+
+void WINCESdlGraphicsManager::smartphone_rotate_display() {
+ _orientationLandscape = _newOrientation = _orientationLandscape == 1 ? 2 : 1;
+ ConfMan.setInt("landscape", _orientationLandscape);
+ ConfMan.flushToDisk();
+ hotswapGFXMode();
+}
+
+void WINCESdlGraphicsManager::create_toolbar() {
+ CEGUI::PanelKeyboard *keyboard;
+
+ // Add the keyboard
+ keyboard = new CEGUI::PanelKeyboard(PANEL_KEYBOARD);
+ _toolbarHandler.add(NAME_PANEL_KEYBOARD, *keyboard);
+ _toolbarHandler.setVisible(false);
+}
+
+WINCESdlGraphicsManager::zoneDesc WINCESdlGraphicsManager::_zones[TOTAL_ZONES] = {
+ { 0, 0, 320, 145 },
+ { 0, 145, 150, 55 },
+ { 150, 145, 170, 55 }
+};
+
+#endif /* _WIN32_WCE */
+
diff --git a/backends/graphics/wincesdl/wincesdl-graphics.h b/backends/graphics/wincesdl/wincesdl-graphics.h
new file mode 100644
index 0000000000..c8d683b158
--- /dev/null
+++ b/backends/graphics/wincesdl/wincesdl-graphics.h
@@ -0,0 +1,206 @@
+/* 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 BACKENDS_GRAPHICS_WINCE_SDL_H
+#define BACKENDS_GRAPHICS_WINCE_SDL_H
+
+#include "backends/graphics/sdl/sdl-graphics.h"
+#include "backends/platform/wince/CEgui/CEGUI.h"
+
+// Internal GUI names
+#define NAME_MAIN_PANEL "MainPanel"
+#define NAME_PANEL_KEYBOARD "Keyboard"
+#define NAME_ITEM_OPTIONS "Options"
+#define NAME_ITEM_SKIP "Skip"
+#define NAME_ITEM_SOUND "Sound"
+#define NAME_ITEM_ORIENTATION "Orientation"
+#define NAME_ITEM_BINDKEYS "Bindkeys"
+
+#define TOTAL_ZONES 3
+
+extern bool _hasSmartphoneResolution;
+
+class WINCESdlGraphicsManager : public SdlGraphicsManager {
+public:
+ WINCESdlGraphicsManager(SdlEventSource *sdlEventSource);
+
+ const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
+ void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL);
+
+ bool hasFeature(OSystem::Feature f);
+ void setFeatureState(OSystem::Feature f, bool enable);
+ bool getFeatureState(OSystem::Feature f);
+
+ int getDefaultGraphicsMode() const;
+ bool setGraphicsMode(int mode);
+ bool loadGFXMode();
+ void unloadGFXMode();
+ bool hotswapGFXMode();
+
+ // Overloaded from SDL backend (toolbar handling)
+ void drawMouse();
+ // Overloaded from SDL backend (new scaler handling)
+ void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false);
+ // Overloaded from SDL backend (new scaler handling)
+ void warpMouse(int x, int y);
+
+ // Update the dirty areas of the screen
+ void internUpdateScreen();
+ bool saveScreenshot(const char *filename);
+
+ // Overloaded from SDL_Common (FIXME)
+ void internDrawMouse();
+ void undrawMouse();
+ bool showMouse(bool visible);
+ void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend
+ void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
+ void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)
+ Graphics::Surface *lockScreen();
+ void unlockScreen();
+ void blitCursor();
+ void showOverlay();
+ void hideOverlay();
+ void setMousePos(int x, int y);
+
+ // GUI and action stuff
+ void swap_panel_visibility();
+ void swap_panel();
+ void swap_smartphone_keyboard();
+ void swap_zoom_up();
+ void swap_zoom_down();
+ void swap_mouse_visibility();
+
+
+//#ifdef WIN32_PLATFORM_WFSP
+ void move_cursor_up();
+ void move_cursor_down();
+ void move_cursor_left();
+ void move_cursor_right();
+
+ void retrieve_mouse_location(int &x, int &y);
+ void switch_zone();
+
+ void add_right_click(bool pushed);
+ void add_left_click(bool pushed);
+
+ void initZones();
+ void smartphone_rotate_display();
+//#endif
+
+ bool _panelInitialized; // only initialize the toolbar once
+ bool _noDoubleTapRMB; // disable double tap -> rmb click
+
+ CEGUI::ToolbarHandler _toolbarHandler;
+
+ bool _toolbarHighDrawn; // cache toolbar 640x80
+ int _newOrientation; // new orientation
+ int _orientationLandscape; // current orientation
+
+ int _scaleFactorXm; // scaler X *
+ int _scaleFactorXd; // scaler X /
+ int _scaleFactorYm; // scaler Y *
+ int _scaleFactorYd; // scaler Y /
+
+ bool _hasfocus; // scummvm has the top window
+
+ bool hasPocketPCResolution();
+ bool hasDesktopResolution();
+ bool hasSquareQVGAResolution();
+ bool hasWideResolution() const;
+
+ MousePos _mouseCurState;
+
+ bool _zoomUp; // zooming up mode
+ bool _zoomDown; // zooming down mode
+
+ bool _usesEmulatedMouse; // emulated mousemove ever been used in this session
+
+ int _mouseXZone[TOTAL_ZONES];
+ int _mouseYZone[TOTAL_ZONES];
+ int _currentZone;
+
+ // Smartphone specific variables
+ int _lastKeyPressed; // last key pressed
+ int _keyRepeat; // number of time the last key was repeated
+ int _keyRepeatTime; // elapsed time since the key was pressed
+ int _keyRepeatTrigger; // minimum time to consider the key was repeated
+
+ struct zoneDesc {
+ int x;
+ int y;
+ int width;
+ int height;
+ };
+
+ static zoneDesc _zones[TOTAL_ZONES];
+
+protected:
+ virtual void adjustMouseEvent(const Common::Event &event);
+
+private:
+ bool update_scalers();
+ void update_game_settings();
+ void drawToolbarMouse(SDL_Surface *surf, bool draw);
+
+ void create_toolbar();
+ bool _panelVisible; // panel visibility
+ bool _panelStateForced; // panel visibility forced by external call
+ String _saveActiveToolbar; // save active toolbar when forced
+
+ bool _canBeAspectScaled; // game screen size allows for aspect scaling
+
+ SDL_Rect _dirtyRectOut[NUM_DIRTY_RECT];
+ bool _scalersChanged;
+
+ bool isOzone();
+
+ bool _saveToolbarState; // save visibility when forced
+ bool _saveToolbarZoom; // save visibility when zooming
+
+ SDL_Surface *_toolbarLow; // toolbar 320x40
+ SDL_Surface *_toolbarHigh; // toolbar 640x80
+
+ // Mouse
+ int _mouseHotspotX, _mouseHotspotY;
+ byte *_mouseBackupOld;
+ uint16 *_mouseBackupToolbar;
+ uint16 _mouseBackupDim;
+
+ bool _forceHideMouse; // force invisible mouse cursor
+
+ // Smartphone specific variables
+ void loadDeviceConfigurationElement(Common::String element, int &value, int defaultValue);
+ int _repeatX; // repeat trigger for left and right cursor moves
+ int _repeatY; // repeat trigger for up and down cursor moves
+ int _stepX1; // offset for left and right cursor moves (slowest)
+ int _stepX2; // offset for left and right cursor moves (faster)
+ int _stepX3; // offset for left and right cursor moves (fastest)
+ int _stepY1; // offset for up and down cursor moves (slowest)
+ int _stepY2; // offset for up and down cursor moves (faster)
+ int _stepY3; // offset for up and down cursor moves (fastest)
+};
+
+#endif /* BACKENDS_GRAPHICS_WINCE_SDL_H */
+
diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp
index 953b088958..2257f60e27 100644
--- a/backends/midi/alsa.cpp
+++ b/backends/midi/alsa.cpp
@@ -44,7 +44,7 @@
#if SND_LIB_MAJOR >= 1 || SND_LIB_MINOR >= 6
#define snd_seq_flush_output(x) snd_seq_drain_output(x)
-#define snd_seq_set_client_group(x,name) /*nop */
+#define snd_seq_set_client_group(x,name) /*nop */
#define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0)
#else
/* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */
@@ -53,9 +53,8 @@
#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
-static int check_permission(snd_seq_port_info_t *pinfo)
-{
- if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
+static int check_permission(snd_seq_port_info_t *pinfo) {
+ if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) {
if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
return 1;
}
@@ -68,10 +67,11 @@ static int check_permission(snd_seq_port_info_t *pinfo)
#define ADDR_DELIM ".:"
-class MidiDriver_ALSA:public MidiDriver_MPU401 {
+class MidiDriver_ALSA : public MidiDriver_MPU401 {
public:
MidiDriver_ALSA(int client, int port);
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -83,11 +83,12 @@ private:
snd_seq_t *seq_handle;
int seq_client, seq_port;
int my_client, my_port;
+ // The volume controller value of the first MIDI channel
+ int8 _channel0Volume;
};
MidiDriver_ALSA::MidiDriver_ALSA(int client, int port)
- : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0)
-{
+ : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0), _channel0Volume(127) {
memset(&ev, 0, sizeof(ev));
}
@@ -114,7 +115,7 @@ int MidiDriver_ALSA::open() {
// with those capabilities.
my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM port 0", 0,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
if (my_port < 0) {
snd_seq_close(seq_handle);
@@ -208,24 +209,41 @@ void MidiDriver_ALSA::send(uint32 b) {
case 0xB0:
/* is it this simple ? Wow... */
snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]);
+
+ // We save the volume of the first MIDI channel here to utilize it in
+ // our workaround for broken USB-MIDI cables.
+ if (chanID == 0 && midiCmd[1] == 0x07)
+ _channel0Volume = midiCmd[2];
+
send_event(1);
break;
case 0xC0:
snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]);
send_event(0);
+
+ // Send a volume change command to work around a firmware bug in common
+ // USB-MIDI cables. If the first MIDI command in a USB packet is a
+ // Cx or Dx command, the second command in the packet is dropped
+ // somewhere.
+ send(0x07B0 | (_channel0Volume << 16));
break;
case 0xD0:
snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]);
send_event(1);
+
+ // Send a volume change command to work around a firmware bug in common
+ // USB-MIDI cables. If the first MIDI command in a USB packet is a
+ // Cx or Dx command, the second command in the packet is dropped
+ // somewhere.
+ send(0x07B0 | (_channel0Volume << 16));
break;
- case 0xE0:{
- // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
- // snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
- long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
- snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
- send_event(1);
- }
- break;
+ case 0xE0: {
+ // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
+ // snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
+ long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
+ snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
+ send_event(1);
+ } break;
default:
warning("Unknown MIDI Command: %08x", (int)b);
@@ -280,6 +298,9 @@ typedef Common::List<AlsaDevice> AlsaDevices;
AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client)
: _name(name), _type(mt), _client(client) {
+ // Make sure we do not get any trailing spaces to avoid problems when
+ // storing the name in the configuration file.
+ _name.trim();
}
Common::String AlsaDevice::getName() {
diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp
index 57251b45e1..ee3baaadd2 100644
--- a/backends/midi/camd.cpp
+++ b/backends/midi/camd.cpp
@@ -46,6 +46,7 @@ class MidiDriver_CAMD : public MidiDriver_MPU401 {
public:
MidiDriver_CAMD();
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp
index 75c512cad7..0158cc4a1d 100644
--- a/backends/midi/coreaudio.cpp
+++ b/backends/midi/coreaudio.cpp
@@ -72,7 +72,9 @@ do { \
class MidiDriver_CORE : public MidiDriver_MPU401 {
public:
MidiDriver_CORE();
+ ~MidiDriver_CORE();
int open();
+ bool isOpen() const { return _auGraph != 0; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -86,10 +88,18 @@ MidiDriver_CORE::MidiDriver_CORE()
: _auGraph(0) {
}
+MidiDriver_CORE::~MidiDriver_CORE() {
+ if (_auGraph) {
+ AUGraphStop(_auGraph);
+ DisposeAUGraph(_auGraph);
+ _auGraph = 0;
+ }
+}
+
int MidiDriver_CORE::open() {
OSStatus err = 0;
- if (_auGraph)
+ if (isOpen())
return MERR_ALREADY_OPEN;
// Open the Music Device.
@@ -176,7 +186,6 @@ bail:
void MidiDriver_CORE::close() {
MidiDriver_MPU401::close();
-
if (_auGraph) {
AUGraphStop(_auGraph);
DisposeAUGraph(_auGraph);
@@ -185,7 +194,7 @@ void MidiDriver_CORE::close() {
}
void MidiDriver_CORE::send(uint32 b) {
- assert(_auGraph != NULL);
+ assert(isOpen());
byte status_byte = (b & 0x000000FF);
byte first_byte = (b & 0x0000FF00) >> 8;
@@ -198,7 +207,7 @@ void MidiDriver_CORE::sysEx(const byte *msg, uint16 length) {
unsigned char buf[266];
assert(length + 2 <= ARRAYSIZE(buf));
- assert(_auGraph != NULL);
+ assert(isOpen());
// Add SysEx frame
buf[0] = 0xF0;
diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp
index c0663352cb..9123c9bc8c 100644
--- a/backends/midi/coremidi.cpp
+++ b/backends/midi/coremidi.cpp
@@ -56,6 +56,7 @@ public:
MidiDriver_CoreMIDI();
~MidiDriver_CoreMIDI();
int open();
+ bool isOpen() const { return mOutPort != 0 && mDest != 0; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -80,7 +81,7 @@ MidiDriver_CoreMIDI::~MidiDriver_CoreMIDI() {
}
int MidiDriver_CoreMIDI::open() {
- if (mDest)
+ if (isOpen())
return MERR_ALREADY_OPEN;
OSStatus err = noErr;
@@ -106,7 +107,7 @@ int MidiDriver_CoreMIDI::open() {
void MidiDriver_CoreMIDI::close() {
MidiDriver_MPU401::close();
- if (mOutPort && mDest) {
+ if (isOpen()) {
MIDIPortDispose(mOutPort);
mOutPort = 0;
mDest = 0;
@@ -114,8 +115,7 @@ void MidiDriver_CoreMIDI::close() {
}
void MidiDriver_CoreMIDI::send(uint32 b) {
- assert(mOutPort != 0);
- assert(mDest != 0);
+ assert(isOpen());
// Extract the MIDI data
byte status_byte = (b & 0x000000FF);
@@ -158,8 +158,7 @@ void MidiDriver_CoreMIDI::send(uint32 b) {
}
void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) {
- assert(mOutPort != 0);
- assert(mDest != 0);
+ assert(isOpen());
byte buf[384];
MIDIPacketList *packetList = (MIDIPacketList *)buf;
diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp
index f0ab84c934..c4c1968354 100644
--- a/backends/midi/dmedia.cpp
+++ b/backends/midi/dmedia.cpp
@@ -57,6 +57,7 @@ class MidiDriver_DMEDIA : public MidiDriver_MPU401 {
public:
MidiDriver_DMEDIA();
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -179,7 +180,7 @@ void MidiDriver_DMEDIA::sysEx (const byte *msg, uint16 length) {
memcpy(buf, msg, length);
buf[length] = MD_EOX;
event.sysexmsg = buf;
- event.msglen = length;
+ event.msglen = length;
event.msg[0] = MD_SYSEX;
event.msg[1] = 0;
event.msg[2] = 0;
diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 064129b74a..7cd7f0a38e 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -55,6 +55,7 @@ class MidiDriver_SEQ : public MidiDriver_MPU401 {
public:
MidiDriver_SEQ();
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp
index 562c3c7ece..42f829a7a3 100644
--- a/backends/midi/stmidi.cpp
+++ b/backends/midi/stmidi.cpp
@@ -48,8 +48,9 @@
class MidiDriver_STMIDI : public MidiDriver_MPU401 {
public:
- MidiDriver_STMIDI() : _isOpen (false) { }
+ MidiDriver_STMIDI() : _isOpen (false) { }
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -59,7 +60,7 @@ private:
};
int MidiDriver_STMIDI::open() {
- if ((_isOpen) && (!Bcostat(4)))
+ if (_isOpen && (!Bcostat(4)))
return MERR_ALREADY_OPEN;
warning("ST Midi Port Open");
_isOpen = true;
@@ -123,36 +124,36 @@ void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
class StMidiMusicPlugin : public MusicPluginObject {
public:
- const char *getName() const {
- return "STMIDI";
- }
+ const char *getName() const {
+ return "STMIDI";
+ }
- const char *getId() const {
- return "stmidi";
- }
+ const char *getId() const {
+ return "stmidi";
+ }
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices StMidiMusicPlugin::getDevices() const {
- MusicDevices devices;
- // TODO: Return a different music type depending on the configuration
- // TODO: List the available devices
- devices.push_back(MusicDevice(this, "", MT_GM));
- return devices;
+ MusicDevices devices;
+ // TODO: Return a different music type depending on the configuration
+ // TODO: List the available devices
+ devices.push_back(MusicDevice(this, "", MT_GM));
+ return devices;
}
Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_STMIDI();
+ *mididriver = new MidiDriver_STMIDI();
- return Common::kNoError;
+ return Common::kNoError;
}
//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
- //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+ //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#else
- REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+ REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#endif
#endif
diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp
index eeaf872747..c01b9bbef7 100644
--- a/backends/midi/timidity.cpp
+++ b/backends/midi/timidity.cpp
@@ -92,49 +92,50 @@ class MidiDriver_TIMIDITY : public MidiDriver_MPU401 {
public:
MidiDriver_TIMIDITY();
- int open();
- void close();
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
+ int open();
+ bool isOpen() const { return _isOpen; }
+ void close();
+ void send(uint32 b);
+ void sysEx(const byte *msg, uint16 length);
private:
/* standart routine to extract ip address from a string */
- in_addr_t host_to_addr(const char* address);
+ in_addr_t host_to_addr(const char* address);
/* creates a tcp connection to TiMidity server, returns filedesc (like open()) */
- int connect_to_server(const char* hostname, unsigned short tcp_port);
+ int connect_to_server(const char* hostname, unsigned short tcp_port);
/* send command to the server; printf-like; returns reply string */
- char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3);
+ char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3);
/* timidity data socket-related stuff */
- void timidity_meta_seq(int p1, int p2, int p3);
- int timidity_sync(int centsec);
- int timidity_eot();
+ void timidity_meta_seq(int p1, int p2, int p3);
+ int timidity_sync(int centsec);
+ int timidity_eot();
/* write() analogue for any midi data */
- void timidity_write_data(const void *buf, size_t nbytes);
+ void timidity_write_data(const void *buf, size_t nbytes);
/* get single line of server reply on control connection */
- int fdgets(char *buff, size_t buff_size);
+ int fdgets(char *buff, size_t buff_size);
/* teardown connection to server */
- void teardown();
+ void teardown();
/* close (if needed) and nullify both control and data filedescs */
- void close_all();
+ void close_all();
private:
- bool _isOpen;
- int _device_num;
+ bool _isOpen;
+ int _device_num;
- int _control_fd;
- int _data_fd;
+ int _control_fd;
+ int _data_fd;
/* buffer for partial data read from _control_fd - from timidity-io.c, see fdgets() */
- char _controlbuffer[BUFSIZ];
- int _controlbuffer_count; /* beginning of read pointer */
- int _controlbuffer_size; /* end of read pointer */
+ char _controlbuffer[BUFSIZ];
+ int _controlbuffer_count; /* beginning of read pointer */
+ int _controlbuffer_size; /* end of read pointer */
};
MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
@@ -149,9 +150,9 @@ MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
}
int MidiDriver_TIMIDITY::open() {
- char *res;
- char timidity_host[MAXHOSTNAMELEN];
- int timidity_port, data_port, i;
+ char *res;
+ char timidity_host[MAXHOSTNAMELEN];
+ int timidity_port, data_port, i;
/* count ourselves open */
if (_isOpen)
@@ -427,10 +428,9 @@ void MidiDriver_TIMIDITY::timidity_write_data(const void *buf, size_t nbytes) {
}
int MidiDriver_TIMIDITY::fdgets(char *buff, size_t buff_size) {
- int n, len, count, size;
+ int n, count, size;
char *buff_endp = buff + buff_size - 1, *pbuff, *beg;
- len = 0;
count = _controlbuffer_count;
size = _controlbuffer_size;
pbuff = _controlbuffer;
diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp
index b585b71fbe..aad7f48d94 100644
--- a/backends/midi/windows.cpp
+++ b/backends/midi/windows.cpp
@@ -61,6 +61,7 @@ private:
public:
MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { }
int open();
+ bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@@ -93,6 +94,8 @@ void MidiDriver_WIN::close() {
}
void MidiDriver_WIN::send(uint32 b) {
+ assert(_isOpen);
+
union {
DWORD dwData;
BYTE bData[4];
diff --git a/backends/mixer/wincesdl/wincesdl-mixer.cpp b/backends/mixer/wincesdl/wincesdl-mixer.cpp
new file mode 100644
index 0000000000..fb8a7d10c7
--- /dev/null
+++ b/backends/mixer/wincesdl/wincesdl-mixer.cpp
@@ -0,0 +1,183 @@
+/* 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$
+ *
+ */
+
+#ifdef _WIN32_WCE
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "common/config-manager.h"
+#include "backends/platform/wince/wince-sdl.h"
+#include "backends/mixer/wincesdl/wincesdl-mixer.h"
+#include "common/system.h"
+
+#ifdef USE_VORBIS
+#ifndef USE_TREMOR
+#include <vorbis/vorbisfile.h>
+#else
+#include <tremor/ivorbisfile.h>
+#endif
+#endif
+
+#define SAMPLES_PER_SEC_OLD 11025
+#define SAMPLES_PER_SEC_NEW 22050
+
+WINCESdlMixerManager::WINCESdlMixerManager() {
+
+}
+
+WINCESdlMixerManager::~WINCESdlMixerManager() {
+
+}
+
+void WINCESdlMixerManager::init() {
+ SDL_AudioSpec desired;
+ int thread_priority;
+
+ uint32 sampleRate = compute_sample_rate();
+ if (sampleRate == 0)
+ warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work");
+ else if (_mixer && _mixer->getOutputRate() == sampleRate) {
+ debug(1, "Skipping sound mixer re-init: samplerate is good");
+ return;
+ }
+
+ memset(&desired, 0, sizeof(desired));
+ desired.freq = sampleRate;
+ desired.format = AUDIO_S16SYS;
+ desired.channels = 2;
+ desired.samples = 128;
+ desired.callback = private_sound_proc;
+ desired.userdata = this;
+
+ // Create the mixer instance
+ if (_mixer == 0)
+ _mixer = new Audio::MixerImpl(g_system, sampleRate);
+
+ // Add sound thread priority
+ if (!ConfMan.hasKey("sound_thread_priority"))
+ thread_priority = THREAD_PRIORITY_NORMAL;
+ else
+ thread_priority = ConfMan.getInt("sound_thread_priority");
+
+ desired.thread_priority = thread_priority;
+
+ SDL_CloseAudio();
+ if (SDL_OpenAudio(&desired, NULL) != 0) {
+ warning("Could not open audio device: %s", SDL_GetError());
+ _mixer->setReady(false);
+
+ } else {
+ debug(1, "Sound opened OK, mixing at %d Hz", sampleRate);
+
+ // Re-create mixer to match the output rate
+ int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
+ int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
+ int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
+ int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
+ delete _mixer;
+ _mixer = new Audio::MixerImpl(g_system, sampleRate);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4);
+ _mixer->setReady(true);
+ SDL_PauseAudio(0);
+ }
+}
+
+void WINCESdlMixerManager::private_sound_proc(void *param, byte *buf, int len) {
+ WINCESdlMixerManager *this_ = (WINCESdlMixerManager *)param;
+ assert(this_);
+
+ if (this_->_mixer)
+ this_->_mixer->mixCallback(buf, len);
+ if (!OSystem_WINCE3::_soundMaster)
+ memset(buf, 0, len);
+}
+
+uint32 WINCESdlMixerManager::compute_sample_rate() {
+ uint32 sampleRate;
+
+ // Force at least medium quality FM synthesis for FOTAQ
+ Common::String gameid(ConfMan.get("gameid"));
+ if (gameid == "queen") {
+ if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) ||
+ (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) {
+ ConfMan.setBool("FM_medium_quality", true);
+ ConfMan.flushToDisk();
+ }
+ }
+ // See if the output frequency is forced by the game
+ if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi")
+ sampleRate = SAMPLES_PER_SEC_NEW;
+ else {
+ if (ConfMan.hasKey("high_sample_rate") && ConfMan.getBool("high_sample_rate"))
+ sampleRate = SAMPLES_PER_SEC_NEW;
+ else
+ sampleRate = SAMPLES_PER_SEC_OLD;
+ }
+
+#ifdef USE_VORBIS
+ // Modify the sample rate on the fly if OGG is involved
+ if (sampleRate == SAMPLES_PER_SEC_OLD)
+ if (checkOggHighSampleRate())
+ sampleRate = SAMPLES_PER_SEC_NEW;
+#endif
+
+ return sampleRate;
+}
+
+#ifdef USE_VORBIS
+bool WINCESdlMixerManager::checkOggHighSampleRate() {
+ char trackFile[255];
+ FILE *testFile;
+ OggVorbis_File *test_ov_file = new OggVorbis_File;
+
+ // FIXME: The following sprintf assumes that "path" is always
+ // terminated by a path separator. This is *not* true in general.
+ // This code really should check for the path separator, or even
+ // better, use the FSNode API.
+ sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str());
+ // Check if we have an OGG audio track
+ testFile = fopen(trackFile, "rb");
+ if (testFile) {
+ if (!ov_open(testFile, test_ov_file, NULL, 0)) {
+ bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050);
+ ov_clear(test_ov_file);
+ delete test_ov_file;
+ return highSampleRate;
+ }
+ }
+
+ // Do not test for OGG samples - too big and too slow anyway :)
+
+ delete test_ov_file;
+ return false;
+}
+#endif
+
+#endif
+
diff --git a/backends/mixer/wincesdl/wincesdl-mixer.h b/backends/mixer/wincesdl/wincesdl-mixer.h
new file mode 100644
index 0000000000..6c2f1efeee
--- /dev/null
+++ b/backends/mixer/wincesdl/wincesdl-mixer.h
@@ -0,0 +1,53 @@
+/* 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 BACKENDS_MIXER_WINCE_SDL_H
+#define BACKENDS_MIXER_WINCE_SDL_H
+
+#include "backends/mixer/sdl/sdl-mixer.h"
+
+/**
+ * SDL mixer manager for WinCE
+ */
+class WINCESdlMixerManager : public SdlMixerManager {
+public:
+ WINCESdlMixerManager();
+ virtual ~WINCESdlMixerManager();
+
+ virtual void init();
+
+private:
+
+#ifdef USE_VORBIS
+ bool checkOggHighSampleRate();
+#endif
+
+ static void private_sound_proc(void *param, byte *buf, int len);
+ uint32 compute_sample_rate();
+
+};
+
+#endif
+
diff --git a/backends/module.mk b/backends/module.mk
index 5a8a63c2a2..426409ab73 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -8,10 +8,14 @@ MODULE_OBJS := \
events/default/default-events.o \
events/dinguxsdl/dinguxsdl-events.o \
events/gp2xsdl/gp2xsdl-events.o \
+ events/gph/gph-events.o \
events/linuxmotosdl/linuxmotosdl-events.o \
+ events/openpandora/op-events.o \
events/samsungtvsdl/samsungtvsdl-events.o \
events/sdl/sdl-events.o \
events/symbiansdl/symbiansdl-events.o \
+ events/webossdl/webossdl-events.o \
+ events/wincesdl/wincesdl-events.o \
fs/abstract-fs.o \
fs/stdiostream.o \
fs/amigaos4/amigaos4-fs-factory.o \
@@ -20,13 +24,16 @@ MODULE_OBJS := \
fs/windows/windows-fs-factory.o \
graphics/dinguxsdl/dinguxsdl-graphics.o \
graphics/gp2xsdl/gp2xsdl-graphics.o \
+ graphics/gph/gph-graphics.o \
graphics/linuxmotosdl/linuxmotosdl-graphics.o \
graphics/opengl/glerrorcheck.o \
graphics/opengl/gltexture.o \
graphics/opengl/opengl-graphics.o \
graphics/openglsdl/openglsdl-graphics.o \
+ graphics/openpandora/op-graphics.o \
graphics/sdl/sdl-graphics.o \
graphics/symbiansdl/symbiansdl-graphics.o \
+ graphics/wincesdl/wincesdl-graphics.o \
keymapper/action.o \
keymapper/keymap.o \
keymapper/keymapper.o \
@@ -44,6 +51,7 @@ MODULE_OBJS := \
mixer/doublebuffersdl/doublebuffersdl-mixer.o \
mixer/sdl/sdl-mixer.o \
mixer/symbiansdl/symbiansdl-mixer.o \
+ mixer/wincesdl/wincesdl-mixer.o \
mutex/sdl/sdl-mutex.o \
plugins/elf/elf-loader.o \
plugins/elf/mips-loader.o \
diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build
deleted file mode 100644
index a4253112da..0000000000
--- a/backends/platform/android/README.build
+++ /dev/null
@@ -1,90 +0,0 @@
-Building the ScummVM Android port
-=================================
-
-You will need these things to build:
-1. Android SDK
-2. An arm-oe-linux-androideabi GCC toolchain(*)
-
-In the example commands, we are going to build against the Android 1.5
-native ABI (but using the Android 1.6 SDK tools). Other version
-combinations might/should be possible with a bit of tweaking.
-
-(*) Any other sane Android toolchain should be easy to use, but this
-is the toolchain prefix that is used by default. You can trivially
-find and modify the single location where it appears in ./configure if
-you have some other prefix variation.
-
-
-In detail:
-
-1. Android SDK
-
-Download the SDK from http://developer.android.com/ and install
-somewhere. You will need both the API level 8 (aka Android 2.2) and
-API level 3 (aka Android 1.5) platforms.
-
-2. arm-*-linux-androideabi GCC toolchain
-
-You have several choices for toolchains:
-
- - Use Google arm-eabi prebuilt toolchain.
-
-This is shipped with both the Android source release and Android NDK.
-The problem is that "arm-eabi-gcc" can't actually link anything
-successfully without extra command line flags. To use this with the
-ScummVM configure/build environment you will need to create a family
-of shell wrapper scripts that convert "arm-oe-linux-androideabi-foo" to
-"arm-eabi-foo -mandroid".
-
-For example, I use this script:
- #!/bin/sh
- exec arm-eabi-${0##*-} -mandroid -DANDROID "$@"
-
-... and create a family of symlinks/hardlinks pointing to it called
-arm-oe-android-linuxeabi-gcc, arm-oe-android-linuxeabi-g++, etc. For
-tools that don't take a "-mandroid" argument - like arm-eabi-strip - I
-bypass the shell wrapper and just create an arm-oe-android-linuxeabi-strip
-symlink to the tool directly.
-
-In practice you will probably need significant linker command line
-massaging in order to get the crtbegin/end and libraries all linked in
-the right way. It's not hard to do manually, but it is annoying to
-script in a general purpose way.
-
- - Build your own arm-*-linux-androideabi toolchain from GCC source.
-
-This is lots of fun, but will become significantly easier once gcc-4.6
-is released. In the interim, I suggest using my precompiled Android
-openembedded-based toolchain:
- wget http://commondatastorage.googleapis.com/anr/sdk/android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2
- sudo tar jxf android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2 -C /
- . /usr/local/android/arm/environment-setup
-
-Alternatively, do a websearch - there are several other cross-compile
-toolchains around.
-
-
-Building ScummVM
-================
-
-(Optionally) compress scummmodern.zip:
-(ScummVM usually ships it uncompressed, but Android can read it more
-efficiently if it is compressed *before* adding it to the apk)
-
- ( cd gui/themes/scummmodern && zip -f ../scummmodern.zip )
-
-Then build ScummVM:
-
- export ANDROID_SDK=<root of Android SDK>
-
- PATH=$ANDROID_SDK/platforms/android-1.6/tools:$ANDROID_SDK/tools:$PATH
- # You also want to ensure your arm-oe-linux-androideabi toolchain is in $PATH
-
- ./configure --backend=android --host=android --enable-zlib --disable-timidity
- # ... and any other configure flags you want
- make scummvm.apk
-
-This will build a "monolithic" ScummVM package, with the engines
-statically linked in. If you want to build separate engine packages,
-like on the market, add "--enable-plugins --default-dynamic" to
-configure and also make scummvm-engine-scumm.apk, etc.
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index efcee488a5..bbfdb06b8d 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -23,27 +23,14 @@
*
*/
-#include "backends/base-backend.h"
-#include "base/main.h"
-#include "graphics/surface.h"
+#if defined(__ANDROID__)
-#include "backends/platform/android/video.h"
-
-#if defined(ANDROID_BACKEND)
-
-#include <jni.h>
-
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/system_properties.h>
#include <time.h>
+#include <unistd.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <android/log.h>
-
-#include "common/archive.h"
#include "common/util.h"
#include "common/rect.h"
#include "common/queue.h"
@@ -51,1087 +38,397 @@
#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/asset-archive.h"
-
-#undef LOG_TAG
-#define LOG_TAG "ScummVM"
-#if 0
-#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args)
-#else
-#define ENTER(args...) /**/
-#endif
+#include "backends/platform/android/jni.h"
+#include "backends/platform/android/android.h"
-// Fix JNIEXPORT declaration to actually do something useful
-#undef JNIEXPORT
-#define JNIEXPORT __attribute__ ((visibility("default")))
+const char *android_log_tag = "ScummVM";
-// This replaces the bionic libc assert message with something that
+// This replaces the bionic libc assert functions with something that
// actually prints the assertion failure before aborting.
-extern "C"
-void __assert(const char *file, int line, const char *expr) {
- __android_log_assert(expr, LOG_TAG, "%s:%d: Assertion failure: %s",
- file, line, expr);
-}
-
-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;
- bool version_unsupported =
- cached_jvm->GetEnv((void**)&env, JNI_VERSION_1_2);
- assert(! version_unsupported);
- return env;
-}
-
-static void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) {
- jclass cls = env->FindClass(name);
- // if cls is NULL, an exception has already been thrown
- if (cls != NULL)
- 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;
-}
+extern "C" {
+ void __assert(const char *file, int line, const char *expr) {
+ __android_log_assert(expr, android_log_tag,
+ "Assertion failure: '%s' in %s:%d",
+ expr, file, line);
+ }
-static inline GLfixed xdiv(int numerator, int denominator) {
- assert(numerator < (1<<16));
- return (numerator << 16) / denominator;
+ void __assert2(const char *file, int line, const char *func,
+ const char *expr) {
+ __android_log_assert(expr, android_log_tag,
+ "Assertion failure: '%s' in %s:%d (%s)",
+ expr, file, line, func);
+ }
}
-#ifdef DYNAMIC_MODULES
-class AndroidPluginProvider : public POSIXPluginProvider {
-protected:
- virtual void addCustomDirectories(Common::FSList &dirs) const;
-};
-#endif
-
-
-#if 0
-#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
-static const char* getGlErrStr(GLenum error) {
+#ifdef ANDROID_DEBUG_GL
+static const char *getGlErrStr(GLenum error) {
switch (error) {
- case GL_NO_ERROR: return "GL_NO_ERROR";
- case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
- case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
- case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
- case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
- case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
+ case GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
}
static char buf[40];
snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
+
return buf;
}
-static void checkGlError(const char* file, int line) {
+
+void checkGlError(const char *expr, const char *file, int line) {
GLenum error = glGetError();
+
if (error != GL_NO_ERROR)
- warning("%s:%d: GL error: %s", file, line, getGlErrStr(error));
+ LOGE("GL ERROR: %s on %s (%s:%d)", getGlErrStr(error), expr, file, line);
}
-#else
-#define CHECK_GL_ERROR() do {} while (false)
#endif
-class OSystem_Android : public BaseBackend, public PaletteManager {
-private:
- jobject _back_ptr; // back pointer to (java) peer instance
- 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();
- virtual Graphics::PixelFormat getOverlayFormat() const {
- // RGBA 4444
- 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::OSystem_Android(jobject am)
- : _back_ptr(0),
- _screen_changeid(0),
- _force_redraw(false),
- _game_texture(NULL),
- _overlay_texture(NULL),
- _mouse_texture(NULL),
- _use_mouse_palette(false),
- _show_mouse(false),
- _show_overlay(false),
- _enable_zoning(false),
- _savefile(0),
- _mixer(0),
- _timer(0),
- _fsFactory(new POSIXFilesystemFactory()),
- _asset_archive(new AndroidAssetArchive(am)),
- _shake_offset(0),
- _event_queue_lock(createMutex()) {
+OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
+ _audio_sample_rate(audio_sample_rate),
+ _audio_buffer_size(audio_buffer_size),
+ _screen_changeid(0),
+ _egl_surface_width(0),
+ _egl_surface_height(0),
+ _htc_fail(false),
+ _force_redraw(false),
+ _game_texture(0),
+ _overlay_texture(0),
+ _mouse_texture(0),
+ _mouse_texture_palette(0),
+ _mouse_texture_rgb(0),
+ _mouse_hotspot(),
+ _mouse_keycolor(0),
+ _use_mouse_palette(false),
+ _graphicsMode(0),
+ _fullscreen(true),
+ _ar_correction(true),
+ _show_mouse(false),
+ _show_overlay(false),
+ _enable_zoning(false),
+ _savefile(0),
+ _mixer(0),
+ _timer(0),
+ _fsFactory(new POSIXFilesystemFactory()),
+ _shake_offset(0),
+ _event_queue_lock(createMutex()),
+ _touch_pt_down(),
+ _touch_pt_scroll(),
+ _touch_pt_dt(),
+ _eventScaleX(100),
+ _eventScaleY(100),
+ // TODO put these values in some option dlg?
+ _touchpad_mode(true),
+ _touchpad_scale(66),
+ _dpad_scale(4),
+ _fingersDown(0),
+ _trackball_scale(2) {
+ Common::String mf = getSystemProperty("ro.product.manufacturer");
+
+ LOGI("Running on: [%s] [%s] [%s] [%s] [%s] SDK:%s ABI:%s",
+ mf.c_str(),
+ getSystemProperty("ro.product.model").c_str(),
+ getSystemProperty("ro.product.brand").c_str(),
+ getSystemProperty("ro.build.fingerprint").c_str(),
+ getSystemProperty("ro.build.display.id").c_str(),
+ getSystemProperty("ro.build.version.sdk").c_str(),
+ getSystemProperty("ro.product.cpu.abi").c_str());
+
+ mf.toLowercase();
+ _htc_fail = mf.contains("htc");
+
+ if (_htc_fail)
+ LOGI("Enabling HTC workaround");
}
OSystem_Android::~OSystem_Android() {
- ENTER("~OSystem_Android()");
- delete _game_texture;
- delete _overlay_texture;
- delete _mouse_texture;
- destroyScummVMSurface();
- JNIEnv* env = JNU_GetEnv();
- //env->DeleteWeakGlobalRef(_back_ptr);
- env->DeleteGlobalRef(_back_ptr);
+ ENTER();
+
delete _savefile;
- delete _mixer;
delete _timer;
+ delete _mixer;
delete _fsFactory;
- delete _asset_archive;
- 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)
- //_back_ptr = env->NewWeakGlobalRef(self);
- _back_ptr = env->NewGlobalRef(self);
-
- jclass cls = env->GetObjectClass(_back_ptr);
-
-#define FIND_METHOD(name, signature) do { \
- MID_ ## name = env->GetMethodID(cls, #name, signature); \
- if (MID_ ## name == NULL) \
- 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;
-}
-
-static void ScummVM_create(JNIEnv* env, jobject self, jobject am) {
- OSystem_Android* cpp_obj = new OSystem_Android(am);
- if (!cpp_obj->initJavaHooks(env, self))
- // Exception already thrown by initJavaHooks
- 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, NULL);
- if (buf == NULL) {
- 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);
+ deleteMutex(_event_queue_lock);
}
-static void ScummVM_setConfManInt(JNIEnv* env, jclass cls,
- jstring key_obj, jint value) {
- ENTER("setConfManInt(%p, %d)", key_obj, (int)value);
- const char* key = env->GetStringUTFChars(key_obj, NULL);
- if (key == NULL)
- return;
- ConfMan.setInt(key, value);
- env->ReleaseStringUTFChars(key_obj, key);
-}
+void *OSystem_Android::timerThreadFunc(void *arg) {
+ OSystem_Android *system = (OSystem_Android *)arg;
+ DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
-static void ScummVM_setConfManString(JNIEnv* env, jclass cls, jstring key_obj,
- jstring value_obj) {
- ENTER("setConfManStr(%p, %p)", key_obj, value_obj);
- const char* key = env->GetStringUTFChars(key_obj, NULL);
- if (key == NULL)
- return;
- const char* value = env->GetStringUTFChars(value_obj, NULL);
- if (value == NULL) {
- env->ReleaseStringUTFChars(key_obj, key);
- return;
- }
- ConfMan.set(key, value);
- env->ReleaseStringUTFChars(value_obj, value);
- env->ReleaseStringUTFChars(key_obj, key);
-}
+ // renice this thread to boost the audio thread
+ if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+ LOGW("couldn't renice the timer thread");
-void* OSystem_Android::timerThreadFunc(void* arg) {
- OSystem_Android* system = (OSystem_Android*)arg;
- DefaultTimerManager* timer = (DefaultTimerManager*)(system->_timer);
+ JNI::attachThread();
struct timespec tv;
tv.tv_sec = 0;
- tv.tv_nsec = 100 * 1000 * 1000; // 100ms
+ tv.tv_nsec = 10 * 1000 * 1000; // 10ms
while (!system->_timer_thread_exit) {
- timer->handler();
- nanosleep(&tv, NULL);
- }
-
- return NULL;
-}
-
-void OSystem_Android::initBackend() {
- ENTER("initBackend()");
- JNIEnv* env = JNU_GetEnv();
-
- ConfMan.setInt("autosave_period", 0);
- ConfMan.setInt("FM_medium_quality", true);
-
- // must happen before creating TimerManager to avoid race in
- // creating EventManager
- setupKeymapper();
-
- // BUG: "transient" ConfMan settings get nuked by the options
- // screen. Passing the savepath in this way makes it stick
- // (via ConfMan.registerDefault)
- _savefile = new DefaultSaveFileManager(ConfMan.get("savepath"));
- _timer = new DefaultTimerManager();
-
- gettimeofday(&_startTime, NULL);
-
- 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->setReady(true);
-
- env->CallVoidMethod(_back_ptr, MID_initBackend);
- if (env->ExceptionCheck()) {
- error("Error in Java initBackend");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
-
- _timer_thread_exit = false;
- pthread_create(&_timer_thread, NULL, timerThreadFunc, this);
-
- OSystem::initBackend();
-
- setupScummVMSurface();
-}
-
-void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
- ENTER("OSystem_Android::addPluginDirectories()");
- JNIEnv* env = JNU_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 == NULL)
- continue;
- const char* path = env->GetStringUTFChars(path_obj, NULL);
- if (path == NULL) {
- warning("Error getting string characters from plugin directory");
- env->ExceptionClear();
- env->DeleteLocalRef(path_obj);
- continue;
+ if (JNI::pause) {
+ LOGD("timer thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("timer thread woke up");
}
- dirs.push_back(Common::FSNode(path));
- env->ReleaseStringUTFChars(path_obj, path);
- env->DeleteLocalRef(path_obj);
- }
-}
-
-bool OSystem_Android::hasFeature(Feature f) {
- return (f == kFeatureCursorHasPalette ||
- f == kFeatureVirtualKeyboard ||
- f == kFeatureOverlaySupportsAlpha);
-}
-
-void OSystem_Android::setFeatureState(Feature f, bool enable) {
- ENTER("setFeatureState(%d, %d)", f, enable);
- switch (f) {
- case kFeatureVirtualKeyboard:
- _virtkeybd_on = enable;
- showVirtualKeyboard(enable);
- break;
- default:
- break;
- }
-}
-bool OSystem_Android::getFeatureState(Feature f) {
- switch (f) {
- case kFeatureVirtualKeyboard:
- return _virtkeybd_on;
- default:
- return false;
+ timer->handler();
+ nanosleep(&tv, 0);
}
-}
-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;
-}
+ JNI::detachThread();
-bool OSystem_Android::setGraphicsMode(const char *mode) {
- ENTER("setGraphicsMode(%s)", mode);
- return true;
+ return 0;
}
-bool OSystem_Android::setGraphicsMode(int mode) {
- ENTER("setGraphicsMode(%d)", mode);
- return true;
-}
-
-int OSystem_Android::getGraphicsMode() const {
- return 1;
-}
+void *OSystem_Android::audioThreadFunc(void *arg) {
+ JNI::attachThread();
-void OSystem_Android::setupScummVMSurface() {
- ENTER("setupScummVMSurface");
- JNIEnv* env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
- if (env->ExceptionCheck())
- return;
+ OSystem_Android *system = (OSystem_Android *)arg;
+ Audio::MixerImpl *mixer = system->_mixer;
- // EGL set up with a new surface. Initialise OpenGLES context.
+ uint buf_size = system->_audio_buffer_size;
- GLESTexture::initGLExtensions();
+ JNIEnv *env = JNI::getEnv();
- // Turn off anything that looks like 3D ;)
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_LIGHTING);
- glDisable(GL_FOG);
- glDisable(GL_DITHER);
- glShadeModel(GL_FLAT);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+ jbyteArray bufa = env->NewByteArray(buf_size);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ bool paused = true;
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ byte *buf;
+ int offset, left, written;
+ int samples, i;
- glEnable(GL_TEXTURE_2D);
+ struct timespec tv_delay;
+ tv_delay.tv_sec = 0;
+ tv_delay.tv_nsec = 20 * 1000 * 1000;
- if (!_game_texture)
- _game_texture = new GLESPaletteTexture();
- else
- _game_texture->reinitGL();
+ uint msecs_full = buf_size * 1000 / (mixer->getOutputRate() * 2 * 2);
- if (!_overlay_texture)
- _overlay_texture = new GLES4444Texture();
- else
- _overlay_texture->reinitGL();
-
- if (!_mouse_texture)
- _mouse_texture = new GLESPaletteATexture();
- else
- _mouse_texture->reinitGL();
-
- glViewport(0, 0, _egl_surface_width, _egl_surface_height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- clearFocusRectangle();
- CHECK_GL_ERROR();
-}
+ struct timespec tv_full;
+ tv_full.tv_sec = 0;
+ tv_full.tv_nsec = msecs_full * 1000 * 1000;
-void OSystem_Android::destroyScummVMSurface() {
- JNIEnv* env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
- // Can't use OpenGLES functions after this
-}
+ bool silence;
+ uint silence_count = 33;
-void OSystem_Android::initSize(uint width, uint height,
- const Graphics::PixelFormat *format) {
- ENTER("initSize(%d,%d,%p)", width, height, format);
+ while (!system->_audio_thread_exit) {
+ if (JNI::pause) {
+ JNI::setAudioStop();
- _game_texture->allocBuffer(width, height);
+ paused = true;
+ silence_count = 33;
- // 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);
+ LOGD("audio thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("audio thread woke up");
+ }
- // 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);
-}
+ buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0);
+ assert(buf);
-int16 OSystem_Android::getHeight() {
- return _game_texture->height();
-}
+ samples = mixer->mixCallback(buf, buf_size);
-int16 OSystem_Android::getWidth() {
- return _game_texture->width();
-}
+ silence = samples < 1;
-void OSystem_Android::setPalette(const byte* colors, uint start, uint num) {
- ENTER("setPalette(%p, %u, %u)", colors, start, num);
+ // looks stupid, and it is, but currently there's no way to detect
+ // silence-only buffers from the mixer
+ if (!silence) {
+ silence = true;
- if (!_use_mouse_palette)
- _setCursorPalette(colors, start, num);
+ for (i = 0; i < samples; i += 2)
+ // SID streams constant crap
+ if (READ_UINT16(buf + i) > 32) {
+ silence = false;
+ break;
+ }
+ }
- byte* palette = _game_texture->palette() + start*3;
- do {
- for (int i = 0; i < 3; ++i)
- palette[i] = colors[i];
- palette += 3;
- colors += 4;
- } while (--num);
-}
+ env->ReleasePrimitiveArrayCritical(bufa, buf, 0);
-void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
- ENTER("grabPalette(%p, %u, %u)", colors, start, num);
- const byte* palette = _game_texture->palette_const() + start*3;
- do {
- for (int i = 0; i < 3; ++i)
- colors[i] = palette[i];
- colors[3] = 0xff; // alpha
-
- palette += 3;
- colors += 4;
- } while (--num);
-}
+ if (silence) {
+ if (!paused)
+ silence_count++;
-void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
- int x, int y, int w, int h) {
- ENTER("copyRectToScreen(%p, %d, %d, %d, %d, %d)",
- buf, pitch, x, y, w, h);
+ // only pause after a while to prevent toggle mania
+ if (silence_count > 32) {
+ if (!paused) {
+ LOGD("AudioTrack pause");
- _game_texture->updateBuffer(x, y, w, h, buf, pitch);
-}
+ JNI::setAudioPause();
+ paused = true;
+ }
-void OSystem_Android::updateScreen() {
- //ENTER("updateScreen()");
+ nanosleep(&tv_full, 0);
- if (!_force_redraw &&
- !_game_texture->dirty() &&
- !_overlay_texture->dirty() &&
- !_mouse_texture->dirty())
- return;
+ continue;
+ }
+ }
- _force_redraw = false;
+ if (paused) {
+ LOGD("AudioTrack play");
- glPushMatrix();
+ JNI::setAudioPlay();
+ paused = false;
- 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.
- glClearColorx(0, 0, 0, 1 << 16);
- glClear(GL_COLOR_BUFFER_BIT);
+ silence_count = 0;
+ }
- // Move everything up by _shake_offset (game) pixels
- glTranslatex(0, -_shake_offset << 16, 0);
- }
+ offset = 0;
+ left = buf_size;
+ written = 0;
- if (_focus_rect.isEmpty()) {
- _game_texture->drawTexture(0, 0,
- _egl_surface_width, _egl_surface_height);
- } else {
- glPushMatrix();
- glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
- xdiv(_egl_surface_height, _focus_rect.height()),
- 1 << 16);
- glTranslatex(-_focus_rect.left << 16, -_focus_rect.top << 16, 0);
- 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);
- glPopMatrix();
- }
+ while (left > 0) {
+ written = JNI::writeAudio(env, bufa, offset, left);
- CHECK_GL_ERROR();
+ if (written < 0) {
+ LOGE("AudioTrack error: %d", written);
+ break;
+ }
- if (_show_overlay) {
- _overlay_texture->drawTexture(0, 0,
- _egl_surface_width,
- _egl_surface_height);
- CHECK_GL_ERROR();
- }
+ // buffer full
+ if (written < left)
+ nanosleep(&tv_delay, 0);
- if (_show_mouse) {
- glPushMatrix();
-
- glTranslatex(-_mouse_hotspot.x << 16,
- -_mouse_hotspot.y << 16,
- 0);
-
- // Scale up ScummVM -> OpenGL (pixel) coordinates
- int texwidth, texheight;
- if (_show_overlay) {
- texwidth = getOverlayWidth();
- texheight = getOverlayHeight();
- } else {
- texwidth = getWidth();
- texheight = getHeight();
+ offset += written;
+ left -= written;
}
- glScalex(xdiv(_egl_surface_width, texwidth),
- xdiv(_egl_surface_height, texheight),
- 1 << 16);
-
- // Note the extra half texel to position the mouse in
- // the middle of the x,y square:
- const Common::Point& mouse = getEventManager()->getMousePos();
- glTranslatex((mouse.x << 16) | 1 << 15,
- (mouse.y << 16) | 1 << 15, 0);
-
- // Mouse targetscale just seems to make the cursor way
- // too big :/
- //glScalex(_mouse_targetscale << 16, _mouse_targetscale << 16,
- // 1 << 16);
- _mouse_texture->drawTexture();
+ if (written < 0)
+ break;
- glPopMatrix();
+ // prepare the next buffer, and run into the blocking AudioTrack.write
}
- glPopMatrix();
+ JNI::setAudioStop();
- CHECK_GL_ERROR();
+ env->DeleteLocalRef(bufa);
- 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("lockScreen()");
- Graphics::Surface* surface = _game_texture->surface();
- assert(surface->pixels);
- return surface;
-}
+ JNI::detachThread();
-void OSystem_Android::unlockScreen() {
- ENTER("unlockScreen()");
- assert(_game_texture->dirty());
+ return 0;
}
-void OSystem_Android::setShakePos(int shake_offset) {
- ENTER("setShakePos(%d)", shake_offset);
- if (_shake_offset != shake_offset) {
- _shake_offset = shake_offset;
- _force_redraw = true;
- }
-}
-
-void OSystem_Android::fillScreen(uint32 col) {
- ENTER("fillScreen(%u)", col);
- assert(col < 256);
- _game_texture->fillBuffer(col);
-}
+void OSystem_Android::initBackend() {
+ ENTER();
-void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
- ENTER("setFocusRectangle(%d,%d,%d,%d)",
- rect.left, rect.top, rect.right, rect.bottom);
- if (_enable_zoning) {
- _focus_rect = rect;
- _force_redraw = true;
- }
-}
+ _main_thread = pthread_self();
-void OSystem_Android::clearFocusRectangle() {
- ENTER("clearFocusRectangle()");
- if (_enable_zoning) {
- _focus_rect = Common::Rect();
- _force_redraw = true;
- }
-}
+ ConfMan.registerDefault("fullscreen", true);
+ ConfMan.registerDefault("aspect_ratio", true);
-void OSystem_Android::showOverlay() {
- ENTER("showOverlay()");
- _show_overlay = true;
- _force_redraw = true;
-}
+ ConfMan.setInt("autosave_period", 0);
+ ConfMan.setBool("FM_high_quality", false);
+ ConfMan.setBool("FM_medium_quality", true);
-void OSystem_Android::hideOverlay() {
- ENTER("hideOverlay()");
- _show_overlay = false;
- _force_redraw = true;
-}
+ // TODO hackity hack
+ if (ConfMan.hasKey("multi_midi"))
+ _touchpad_mode = !ConfMan.getBool("multi_midi");
-void OSystem_Android::clearOverlay() {
- ENTER("clearOverlay()");
- _overlay_texture->fillBuffer(0);
+ // must happen before creating TimerManager to avoid race in
+ // creating EventManager
+ setupKeymapper();
- // Shouldn't need this, but works around a 'blank screen' bug on Nexus1
- updateScreen();
-}
+ // BUG: "transient" ConfMan settings get nuked by the options
+ // screen. Passing the savepath in this way makes it stick
+ // (via ConfMan.registerDefault)
+ _savefile = new DefaultSaveFileManager(ConfMan.get("savepath"));
+ _timer = new DefaultTimerManager();
-void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
- ENTER("grabOverlay(%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]));
- buf += pitch; // This 'pitch' is pixels not bytes
- } while (--h);
-}
+ gettimeofday(&_startTime, 0);
-void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
- int x, int y, int w, int h) {
- ENTER("copyRectToOverlay(%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]));
+ _mixer = new Audio::MixerImpl(this, _audio_sample_rate);
+ _mixer->setReady(true);
- // This 'pitch' is pixels not bytes
- _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
+ _timer_thread_exit = false;
+ pthread_create(&_timer_thread, 0, timerThreadFunc, this);
- // Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
- updateScreen();
-}
+ _audio_thread_exit = false;
+ pthread_create(&_audio_thread, 0, audioThreadFunc, this);
-int16 OSystem_Android::getOverlayHeight() {
- return _overlay_texture->height();
-}
+ initSurface();
+ initViewport();
-int16 OSystem_Android::getOverlayWidth() {
- return _overlay_texture->width();
-}
+ _game_texture = new GLESFakePalette565Texture();
+ _overlay_texture = new GLES4444Texture();
+ _mouse_texture_palette = new GLESFakePalette5551Texture();
+ _mouse_texture = _mouse_texture_palette;
-bool OSystem_Android::showMouse(bool visible) {
- ENTER("showMouse(%d)", visible);
- _show_mouse = visible;
- return true;
-}
+ initOverlay();
-void OSystem_Android::warpMouse(int x, int y) {
- ENTER("warpMouse(%d, %d)", x, y);
- // We use only the eventmanager's idea of the current mouse
- // position, so there is nothing extra to do here.
-}
+ // renice this thread to boost the audio thread
+ if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+ warning("couldn't renice the main thread");
-void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
- int hotspotX, int hotspotY,
- uint32 keycolor, int cursorTargetScale,
- const Graphics::PixelFormat *format) {
- ENTER("setMouseCursor(%p, %u, %u, %d, %d, %d, %d, %p)",
- buf, w, h, hotspotX, hotspotY, (int)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;
+ JNI::setReadyForEvents(true);
}
-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 += 4;
- } while (--num);
-}
+void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
+ ENTER();
-void OSystem_Android::setCursorPalette(const byte *colors,
- uint start, uint num) {
- ENTER("setCursorPalette(%p, %u, %u)", colors, start, num);
- _setCursorPalette(colors, start, num);
- _use_mouse_palette = true;
+ JNI::getPluginDirectories(dirs);
}
-void OSystem_Android::disableCursorPalette(bool disable) {
- ENTER("disableCursorPalette(%d)", disable);
- _use_mouse_palette = !disable;
+bool OSystem_Android::hasFeature(Feature f) {
+ return (f == kFeatureFullscreenMode ||
+ f == kFeatureAspectRatioCorrection ||
+ f == kFeatureCursorHasPalette ||
+ f == kFeatureVirtualKeyboard ||
+ f == kFeatureOverlaySupportsAlpha);
}
-void OSystem_Android::setupKeymapper() {
-#ifdef ENABLE_KEYMAPPER
- using namespace Common;
-
- Keymapper *mapper = getEventManager()->getKeymapper();
-
- HardwareKeySet *keySet = new HardwareKeySet();
- keySet->addHardwareKey(
- new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)",
- kTriggerLeftKeyType,
- kVirtualKeyboardActionType));
- mapper->registerHardwareKeySet(keySet);
-
- Keymap *globalMap = new Keymap("global");
- Action *act;
-
- act = new Action(globalMap, "VIRT", "Display keyboard",
- kVirtualKeyboardActionType);
- act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
-
- mapper->addGlobalKeymap(globalMap);
-
- mapper->pushKeymap("global");
-#endif
-}
+void OSystem_Android::setFeatureState(Feature f, bool enable) {
+ ENTER("%d, %d", f, enable);
-bool OSystem_Android::pollEvent(Common::Event &event) {
- //ENTER("pollEvent()");
- lockMutex(_event_queue_lock);
- if (_event_queue.empty()) {
- unlockMutex(_event_queue_lock);
- return false;
- }
- event = _event_queue.pop();
- unlockMutex(_event_queue_lock);
-
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- // TODO: only dirty/redraw move bounds
- _force_redraw = true;
- // fallthrough
- 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: {
- if (event.kbd.flags == 1) { // relative mouse hack
- // Relative (trackball) mouse hack.
- const Common::Point& mouse_pos =
- getEventManager()->getMousePos();
- event.mouse.x += mouse_pos.x;
- event.mouse.y += mouse_pos.y;
- event.mouse.x = CLIP(event.mouse.x, (int16)0, _show_overlay ?
- getOverlayWidth() : getWidth());
- event.mouse.y = CLIP(event.mouse.y, (int16)0, _show_overlay ?
- getOverlayHeight() : getHeight());
- } else {
- // Touchscreen events need to be converted
- // from device to game coords first.
- const GLESTexture* tex = _show_overlay
- ? static_cast<GLESTexture*>(_overlay_texture)
- : static_cast<GLESTexture*>(_game_texture);
- event.mouse.x = scalef(event.mouse.x, tex->width(),
- _egl_surface_width);
- event.mouse.y = scalef(event.mouse.y, tex->height(),
- _egl_surface_height);
- event.mouse.x -= _shake_offset;
- }
+ switch (f) {
+ case kFeatureFullscreenMode:
+ _fullscreen = enable;
+ updateScreenRect();
break;
- }
- case Common::EVENT_SCREEN_CHANGED:
- debug("EVENT_SCREEN_CHANGED");
- _screen_changeid++;
- destroyScummVMSurface();
- setupScummVMSurface();
+ case kFeatureAspectRatioCorrection:
+ _ar_correction = enable;
+ updateScreenRect();
+ break;
+ case kFeatureVirtualKeyboard:
+ _virtkeybd_on = enable;
+ showVirtualKeyboard(enable);
break;
default:
break;
}
-
- return true;
-}
-
-void OSystem_Android::pushEvent(const Common::Event& event) {
- lockMutex(_event_queue_lock);
-
- // Try to combine multiple queued mouse move events
- if (event.type == Common::EVENT_MOUSEMOVE &&
- !_event_queue.empty() &&
- _event_queue.back().type == Common::EVENT_MOUSEMOVE) {
- Common::Event tail = _event_queue.back();
- if (event.kbd.flags) {
- // relative movement hack
- tail.mouse.x += event.mouse.x;
- tail.mouse.y += event.mouse.y;
- } else {
- // absolute position
- tail.kbd.flags = 0; // clear relative flag
- tail.mouse.x = event.mouse.x;
- tail.mouse.y = event.mouse.y;
- }
- }
- else
- _event_queue.push(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;
+bool OSystem_Android::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureFullscreenMode:
+ return _fullscreen;
+ case kFeatureAspectRatioCorrection:
+ return _ar_correction;
+ case kFeatureVirtualKeyboard:
+ return _virtkeybd_on;
default:
- break;
+ return false;
}
-
- cpp_obj->pushEvent(event);
}
uint32 OSystem_Android::getMillis() {
timeval curTime;
- gettimeofday(&curTime, NULL);
- return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + \
+
+ gettimeofday(&curTime, 0);
+
+ return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) +
((curTime.tv_usec - _startTime.tv_usec) / 1000));
}
@@ -1141,30 +438,36 @@ 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);
pthread_mutex_t *mutex = new pthread_mutex_t;
+
if (pthread_mutex_init(mutex, &attr) != 0) {
warning("pthread_mutex_init() failed");
+
delete mutex;
- return NULL;
+
+ return 0;
}
+
return (MutexRef)mutex;
}
void OSystem_Android::lockMutex(MutexRef mutex) {
- if (pthread_mutex_lock((pthread_mutex_t*)mutex) != 0)
+ if (pthread_mutex_lock((pthread_mutex_t *)mutex) != 0)
warning("pthread_mutex_lock() failed");
}
void OSystem_Android::unlockMutex(MutexRef mutex) {
- if (pthread_mutex_unlock((pthread_mutex_t*)mutex) != 0)
+ if (pthread_mutex_unlock((pthread_mutex_t *)mutex) != 0)
warning("pthread_mutex_unlock() failed");
}
void OSystem_Android::deleteMutex(MutexRef mutex) {
- pthread_mutex_t* m = (pthread_mutex_t*)mutex;
+ pthread_mutex_t *m = (pthread_mutex_t *)mutex;
+
if (pthread_mutex_destroy(m) != 0)
warning("pthread_mutex_destroy() failed");
else
@@ -1172,47 +475,40 @@ void OSystem_Android::deleteMutex(MutexRef mutex) {
}
void OSystem_Android::quit() {
- ENTER("quit()");
+ ENTER();
+
+ JNI::setReadyForEvents(false);
+
+ _audio_thread_exit = true;
+ pthread_join(_audio_thread, 0);
_timer_thread_exit = true;
- pthread_join(_timer_thread, NULL);
+ pthread_join(_timer_thread, 0);
+
+ delete _game_texture;
+ delete _overlay_texture;
+ delete _mouse_texture_palette;
+ delete _mouse_texture_rgb;
+
+ deinitSurface();
}
void OSystem_Android::setWindowCaption(const char *caption) {
- ENTER("setWindowCaption(%s)", caption);
- JNIEnv* env = JNU_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);
+ ENTER("%s", caption);
+
+ JNI::setWindowCaption(caption);
}
void OSystem_Android::displayMessageOnOSD(const char *msg) {
- ENTER("displayMessageOnOSD(%s)", msg);
- JNIEnv* env = JNU_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);
+ ENTER("%s", msg);
+
+ JNI::displayMessageOnOSD(msg);
}
void OSystem_Android::showVirtualKeyboard(bool enable) {
- ENTER("showVirtualKeyboard(%d)", enable);
- JNIEnv* env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_showVirtualKeyboard, enable);
- if (env->ExceptionCheck()) {
- error("Error trying to show virtual keyboard");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
+ ENTER("%d", enable);
+
+ JNI::showVirtualKeyboard(enable);
}
Common::SaveFileManager *OSystem_Android::getSavefileManager() {
@@ -1232,7 +528,8 @@ Common::TimerManager *OSystem_Android::getTimerManager() {
void OSystem_Android::getTimeAndDate(TimeDate &td) const {
struct tm tm;
- const time_t curTime = time(NULL);
+ const time_t curTime = time(0);
+
localtime_r(&curTime, &tm);
td.tm_sec = tm.tm_sec;
td.tm_min = tm.tm_min;
@@ -1247,194 +544,48 @@ FilesystemFactory *OSystem_Android::getFilesystemFactory() {
}
void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s,
- int priority) {
- s.add("ASSET", _asset_archive, priority, false);
-
- JNIEnv* env = JNU_GetEnv();
-
- jobjectArray array =
- (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getSysArchives);
- if (env->ExceptionCheck()) {
- warning("Error finding system archive path");
- env->ExceptionDescribe();
- env->ExceptionClear();
- return;
- }
+ int priority) {
+ ENTER("");
- 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, NULL);
- if (path != NULL) {
- 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) {
+void OSystem_Android::logMessage(LogMessageType::Type type,
+ const char *message) {
switch (type) {
case LogMessageType::kDebug:
- BaseBackend::logMessage(type, message);
+ __android_log_write(ANDROID_LOG_DEBUG, android_log_tag, message);
break;
case LogMessageType::kWarning:
- __android_log_write(ANDROID_LOG_WARN, "ScummVM", message);
+ __android_log_write(ANDROID_LOG_WARN, android_log_tag, message);
break;
case LogMessageType::kError:
- // FIXME: From the name it looks like this will also quit the program.
- // This shouldn't do that though.
- __android_log_assert("Fatal error", "ScummVM", "%s", message);
+ __android_log_write(ANDROID_LOG_ERROR, android_log_tag, message);
break;
}
}
-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;
- }
+Common::String OSystem_Android::getSystemLanguage() const {
+ return Common::String::format("%s_%s",
+ getSystemProperty("persist.sys.language").c_str(),
+ getSystemProperty("persist.sys.country").c_str());
+}
- char* argv[MAX_NARGS];
- int nargs; // note use in cleanup loop below
- for (nargs = 0; nargs < argc; ++nargs) {
- jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
- if (arg == NULL) {
- argv[nargs] = NULL;
- } else {
- const char* cstr = env->GetStringUTFChars(arg, NULL);
- argv[nargs] = const_cast<char*>(cstr);
- if (cstr == NULL)
- goto cleanup; // exception already thrown
- }
- env->DeleteLocalRef(arg);
- }
+Common::String OSystem_Android::getSystemProperty(const char *name) const {
+ char value[PROP_VALUE_MAX];
- g_system = cpp_obj;
- assert(g_system);
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "Entering scummvm_main with %d args", argc);
- res = scummvm_main(argc, argv);
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Exiting scummvm_main");
- g_system->quit();
-
-cleanup:
- nargs--;
- for (int i = 0; i < nargs; ++i) {
- if (argv[i] == NULL)
- continue;
- jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
- if (arg == NULL)
- // Exception already thrown
- return res;
- env->ReleaseStringUTFChars(arg, argv[i]);
- env->DeleteLocalRef(arg);
- }
+ int len = __system_property_get(name, value);
- return res;
+ return Common::String(value, len);
}
#ifdef DYNAMIC_MODULES
void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
- OSystem_Android* g_system_android = (OSystem_Android*)g_system;
- g_system_android->addPluginDirectories(dirs);
+ ((OSystem_Android *)g_system)->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 == NULL)
- 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 == NULL)
- return JNI_ERR;
-
- jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
- if (event == NULL)
- return JNI_ERR;
- FID_Event_type = env->GetFieldID(event, "type", "I");
- if (FID_Event_type == NULL)
- return JNI_ERR;
- FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
- if (FID_Event_synthetic == NULL)
- return JNI_ERR;
- FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
- if (FID_Event_kbd_keycode == NULL)
- return JNI_ERR;
- FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
- if (FID_Event_kbd_ascii == NULL)
- return JNI_ERR;
- FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
- if (FID_Event_kbd_flags == NULL)
- return JNI_ERR;
- FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
- if (FID_Event_mouse_x == NULL)
- return JNI_ERR;
- FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
- if (FID_Event_mouse_y == NULL)
- return JNI_ERR;
- FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
- if (FID_Event_mouse_relative == NULL)
- return JNI_ERR;
-
- cls = env->FindClass("java/lang/Object");
- if (cls == NULL)
- return JNI_ERR;
- MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
- if (MID_Object_wait == NULL)
- return JNI_ERR;
-
- return JNI_VERSION_1_2;
-}
-
#endif
+
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
new file mode 100644
index 0000000000..6eebdb97d9
--- /dev/null
+++ b/backends/platform/android/android.h
@@ -0,0 +1,307 @@
+/* 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_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 <android/log.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+// toggles start
+//#define ANDROID_DEBUG_ENTER
+//#define ANDROID_DEBUG_GL
+//#define ANDROID_DEBUG_GL_CALLS
+// toggles end
+
+extern const char *android_log_tag;
+
+#define _ANDROID_LOG(prio, fmt, args...) __android_log_print(prio, android_log_tag, fmt, ## args)
+#define LOGD(fmt, args...) _ANDROID_LOG(ANDROID_LOG_DEBUG, fmt, ##args)
+#define LOGI(fmt, args...) _ANDROID_LOG(ANDROID_LOG_INFO, fmt, ##args)
+#define LOGW(fmt, args...) _ANDROID_LOG(ANDROID_LOG_WARN, fmt, ##args)
+#define LOGE(fmt, args...) _ANDROID_LOG(ANDROID_LOG_ERROR, fmt, ##args)
+
+#ifdef ANDROID_DEBUG_ENTER
+#define ENTER(fmt, args...) LOGD("%s(" fmt ")", __FUNCTION__, ##args)
+#else
+#define ENTER(fmt, args...) do { } while (false)
+#endif
+
+#ifdef ANDROID_DEBUG_GL
+extern void checkGlError(const char *expr, const char *file, int line);
+
+#ifdef ANDROID_DEBUG_GL_CALLS
+#define GLCALLLOG(x, before) \
+ do { \
+ if (before) \
+ LOGD("calling '%s' (%s:%d)", x, __FILE__, __LINE__); \
+ else \
+ LOGD("returned from '%s' (%s:%d)", x, __FILE__, __LINE__); \
+ } while (false)
+#else
+#define GLCALLLOG(x, before) do { } while (false)
+#endif
+
+#define GLCALL(x) \
+ do { \
+ GLCALLLOG(#x, true); \
+ (x); \
+ GLCALLLOG(#x, false); \
+ 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
+class AndroidPluginProvider : public POSIXPluginProvider {
+protected:
+ virtual void addCustomDirectories(Common::FSList &dirs) const;
+};
+#endif
+
+class OSystem_Android : public BaseBackend, public PaletteManager {
+private:
+ // passed from the dark side
+ int _audio_sample_rate;
+ int _audio_buffer_size;
+
+ int _screen_changeid;
+ int _egl_surface_width;
+ int _egl_surface_height;
+ bool _htc_fail;
+
+ bool _force_redraw;
+
+ // Game layer
+ GLESBaseTexture *_game_texture;
+ int _shake_offset;
+ Common::Rect _focus_rect;
+
+ // Overlay layer
+ GLES4444Texture *_overlay_texture;
+ bool _show_overlay;
+
+ // Mouse layer
+ GLESBaseTexture *_mouse_texture;
+ GLESBaseTexture *_mouse_texture_palette;
+ GLES5551Texture *_mouse_texture_rgb;
+ Common::Point _mouse_hotspot;
+ uint32 _mouse_keycolor;
+ int _mouse_targetscale;
+ bool _show_mouse;
+ bool _use_mouse_palette;
+
+ int _graphicsMode;
+ bool _fullscreen;
+ bool _ar_correction;
+
+ pthread_t _main_thread;
+
+ bool _timer_thread_exit;
+ pthread_t _timer_thread;
+ static void *timerThreadFunc(void *arg);
+
+ bool _audio_thread_exit;
+ pthread_t _audio_thread;
+ static void *audioThreadFunc(void *arg);
+
+ bool _enable_zoning;
+ bool _virtkeybd_on;
+
+ Common::SaveFileManager *_savefile;
+ Audio::MixerImpl *_mixer;
+ Common::TimerManager *_timer;
+ FilesystemFactory *_fsFactory;
+ timeval _startTime;
+
+ Common::String getSystemProperty(const char *name) const;
+
+ void initSurface();
+ void deinitSurface();
+ void initViewport();
+
+ void initOverlay();
+
+#ifdef USE_RGB_COLOR
+ Common::String getPixelFormatName(const Graphics::PixelFormat &format) const;
+ void initTexture(GLESBaseTexture **texture, uint width, uint height,
+ const Graphics::PixelFormat *format);
+#endif
+
+ void setupKeymapper();
+ void setCursorPaletteInternal(const byte *colors, uint start, uint num);
+
+public:
+ OSystem_Android(int audio_sample_rate, int audio_buffer_size);
+ virtual ~OSystem_Android();
+
+ virtual void initBackend();
+ void addPluginDirectories(Common::FSList &dirs) const;
+ void enableZoning(bool enable) { _enable_zoning = enable; }
+
+ 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;
+ virtual bool setGraphicsMode(int mode);
+ virtual int getGraphicsMode() const;
+
+#ifdef USE_RGB_COLOR
+ virtual Graphics::PixelFormat getScreenFormat() const;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+#endif
+
+ virtual void initSize(uint width, uint height,
+ const Graphics::PixelFormat *format);
+
+ enum FixupType {
+ kClear = 0, // glClear
+ kClearSwap, // glClear + swapBuffers
+ kClearUpdate // glClear + updateScreen
+ };
+
+ void clearScreen(FixupType type, byte count = 1);
+
+ void updateScreenRect();
+ virtual int getScreenChangeID() const;
+
+ virtual int16 getHeight();
+ virtual int16 getWidth();
+
+ virtual PaletteManager *getPaletteManager() {
+ return this;
+ }
+
+public:
+ void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5);
+
+private:
+ Common::Queue<Common::Event> _event_queue;
+ MutexRef _event_queue_lock;
+
+ Common::Point _touch_pt_down, _touch_pt_scroll, _touch_pt_dt;
+ int _eventScaleX;
+ int _eventScaleY;
+ bool _touchpad_mode;
+ int _touchpad_scale;
+ int _trackball_scale;
+ int _dpad_scale;
+ int _fingersDown;
+
+ void clipMouse(Common::Point &p);
+ void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true);
+ void updateEventScale();
+
+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();
+ virtual Graphics::PixelFormat getOverlayFormat() const;
+
+ 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);
+ 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);
+ virtual Common::String getSystemLanguage() const;
+};
+
+#endif
+#endif
+
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 95e848e0d9..77fdb139d8 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -1,59 +1,192 @@
# Android specific build targets
-AAPT = aapt
-DX = dx
-APKBUILDER = apkbuilder
-ADB = adb -e
-JAVAC ?= javac
-JAVACFLAGS = -source 1.5 -target 1.5
+# These must be incremented for each market upload
+ANDROID_VERSIONCODE = 6
+ANDROID_PLUGIN_VERSIONCODE = 6
+
+JAVA_FILES = \
+ ScummVM.java \
+ ScummVMEvents.java \
+ ScummVMApplication.java \
+ ScummVMActivity.java \
+ EditableSurfaceView.java \
+ Unpacker.java
+
+JAVA_FILES_PLUGIN = \
+ PluginProvider.java
+
+JAVA_FILES_GEN = \
+ Manifest.java \
+ R.java
+
+PATH_DIST = $(srcdir)/dists/android
+PATH_RESOURCES = $(PATH_DIST)/res
+
+PORT_DISTFILES = $(PATH_DIST)/README.Android
+
+RESOURCES = \
+ $(PATH_RESOURCES)/values/strings.xml \
+ $(PATH_RESOURCES)/layout/main.xml \
+ $(PATH_RESOURCES)/layout/splash.xml \
+ $(PATH_RESOURCES)/drawable/gradient.xml \
+ $(PATH_RESOURCES)/drawable/scummvm.png \
+ $(PATH_RESOURCES)/drawable/scummvm_big.png
+
+PLUGIN_RESOURCES = \
+ $(PATH_RESOURCES)/values/strings.xml \
+ $(PATH_RESOURCES)/drawable/scummvm.png
# FIXME: find/mark plugin entry points and add all this back again:
#LDFLAGS += -Wl,--gc-sections
#CXXFLAGS += -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden
-resources.ap_: $(srcdir)/dists/android/AndroidManifest.xml $(RESOURCES) $(ASSETS) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
- $(INSTALL) -d build.tmp/assets/
- $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) build.tmp/assets/
- $(AAPT) package -f -M $< -S $(srcdir)/dists/android/res -A build.tmp/assets -I $(ANDROID_JAR8) -F $@
-
-build.tmp/%/resources.ap_: build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml build.stage/%/res/drawable/scummvm.png $(ANDROID_JAR8)
- $(AAPT) package -f -M $< -S build.stage/$*/res -I $(ANDROID_JAR8) -F $@
-
-scummvm.apk: build.tmp/libscummvm.so resources.ap_ classes.dex
- # Package installer won't delete old libscummvm.so on upgrade so
- # replace it with a zero size file
- $(INSTALL) -d build.stage/common/lib/armeabi
- touch build.stage/common/lib/armeabi/libscummvm.so
- # We now handle the library unpacking ourselves from mylib/
- $(INSTALL) -d build.stage/common/mylib/armeabi
- $(INSTALL) -c -m 644 build.tmp/libscummvm.so build.stage/common/mylib/armeabi/
- $(STRIP) build.stage/common/mylib/armeabi/libscummvm.so
- # "-nf lib/armeabi/libscummvm.so" builds bogus paths?
- $(APKBUILDER) $@ -z resources.ap_ -f classes.dex -rf build.stage/common || { $(RM) $@; exit 1; }
-
-scummvm-engine-%.apk: plugins/lib%.so build.tmp/%/resources.ap_ build.tmp/plugins/classes.dex
- $(INSTALL) -d build.stage/$*/apk/mylib/armeabi/
- $(INSTALL) -c -m 644 plugins/lib$*.so build.stage/$*/apk/mylib/armeabi/
- $(STRIP) build.stage/$*/apk/mylib/armeabi/lib$*.so
- $(APKBUILDER) $@ -z build.tmp/$*/resources.ap_ -f build.tmp/plugins/classes.dex -rf build.stage/$*/apk || { $(RM) $@; exit 1; }
+AAPT = $(ANDROID_SDK)/platform-tools/aapt
+ADB = $(ANDROID_SDK)/platform-tools/adb
+DX = $(ANDROID_SDK)/platform-tools/dx
+APKBUILDER = $(ANDROID_SDK)/tools/apkbuilder
+JAVAC ?= javac
+JAVACFLAGS = -source 1.5 -target 1.5
+
+# This is a bit silly. I want to compile against the 1.6 android.jar,
+# to make the compiler check that I don't use something that requires
+# a newer Android. However, in order to use android:installLocation,
+# we need to give aapt a version >=8 android.jar - even though the
+# result will work ok on 1.5+.
+ANDROID_JAR = $(ANDROID_SDK)/platforms/android-4/android.jar
+ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
+
+PATH_BUILD = build.tmp
+PATH_BUILD_ASSETS = $(PATH_BUILD)/assets
+PATH_BUILD_CLASSES_MAIN_TOP = $(PATH_BUILD)/classes.main
+PATH_BUILD_CLASSES_PLUGIN_TOP = $(PATH_BUILD)/classes.plugin
+
+PATH_STAGE_PREFIX = build.stage
+PATH_STAGE_MAIN = $(PATH_STAGE_PREFIX).main
+
+PATH_REL = org/inodes/gus/scummvm
+PATH_SRC_TOP = $(srcdir)/backends/platform/android
+PATH_SRC = $(PATH_SRC_TOP)/$(PATH_REL)
+
+PATH_GEN_TOP = $(PATH_BUILD)/java
+PATH_GEN = $(PATH_GEN_TOP)/$(PATH_REL)
+PATH_CLASSES_MAIN = $(PATH_BUILD_CLASSES_MAIN_TOP)/$(PATH_REL)
+PATH_CLASSES_PLUGIN = $(PATH_BUILD_CLASSES_PLUGIN_TOP)/$(PATH_REL)
+
+FILE_MANIFEST_SRC = $(srcdir)/dists/android/AndroidManifest.xml
+FILE_MANIFEST = $(PATH_BUILD)/AndroidManifest.xml
+FILE_DEX = $(PATH_BUILD)/classes.dex
+FILE_DEX_PLUGIN = $(PATH_BUILD)/plugins/classes.dex
+FILE_RESOURCES = resources.ap_
+FILE_RESOURCES_MAIN = $(PATH_BUILD)/$(FILE_RESOURCES)
+
+SRC_GEN = $(addprefix $(PATH_GEN)/, $(JAVA_FILES_GEN))
+
+CLASSES_MAIN = $(addprefix $(PATH_CLASSES_MAIN)/, $(JAVA_FILES:%.java=%.class))
+CLASSES_GEN = $(addprefix $(PATH_CLASSES_MAIN)/, $(JAVA_FILES_GEN:%.java=%.class))
+CLASSES_PLUGIN = $(addprefix $(PATH_CLASSES_PLUGIN)/, $(JAVA_FILES_PLUGIN:%.java=%.class))
+
+APK_MAIN = scummvm.apk
+APK_PLUGINS = $(patsubst plugins/lib%.so, scummvm-engine-%.apk, $(PLUGINS))
+
+$(FILE_MANIFEST): $(FILE_MANIFEST_SRC)
+ @$(MKDIR) -p $(@D)
+ sed "s/@ANDROID_VERSIONCODE@/$(ANDROID_VERSIONCODE)/" < $< > $@
+
+$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
+ @$(MKDIR) -p $(PATH_GEN_TOP)
+ $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR8)
+
+$(PATH_CLASSES_MAIN)/%.class: $(PATH_GEN)/%.java $(SRC_GEN)
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(PATH_SRC_TOP) -d $(PATH_BUILD_CLASSES_MAIN_TOP) -bootclasspath $(ANDROID_JAR) $<
+
+$(PATH_CLASSES_MAIN)/%.class: $(PATH_SRC)/%.java $(SRC_GEN)
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(PATH_SRC_TOP):$(PATH_GEN_TOP) -d $(PATH_BUILD_CLASSES_MAIN_TOP) -bootclasspath $(ANDROID_JAR) $<
+
+$(PATH_CLASSES_PLUGIN)/%.class: $(PATH_SRC)/%.java
+ @$(MKDIR) -p $(@D)
+ $(JAVAC) $(JAVACFLAGS) -cp $(PATH_SRC_TOP) -d $(PATH_BUILD_CLASSES_PLUGIN_TOP) -bootclasspath $(ANDROID_JAR) $<
+
+$(FILE_DEX): $(CLASSES_MAIN) $(CLASSES_GEN)
+ $(DX) --dex --output=$@ $(PATH_BUILD_CLASSES_MAIN_TOP)
+
+$(FILE_DEX_PLUGIN): $(CLASSES_PLUGIN)
+ @$(MKDIR) -p $(@D)
+ $(DX) --dex --output=$@ $(PATH_BUILD_CLASSES_PLUGIN_TOP)
+
+$(PATH_BUILD)/%/AndroidManifest.xml: $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $(PATH_DIST)/plugin-manifest.xml
+ @$(MKDIR) -p $(@D)
+ $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $* $(PATH_DIST)/plugin-manifest.xml $(ANDROID_PLUGIN_VERSIONCODE) $@
+
+$(PATH_STAGE_PREFIX).%/res/values/strings.xml: $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $(PATH_DIST)/plugin-manifest.xml
+ @$(MKDIR) -p $(@D)
+ $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $* $(PATH_DIST)/plugin-strings.xml $(ANDROID_PLUGIN_VERSIONCODE) $@
+
+$(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png: $(PATH_RESOURCES)/drawable/scummvm.png
+ @$(MKDIR) -p $(@D)
+ $(CP) $< $@
+$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(PATH_BUILD_ASSETS)/
+ $(AAPT) package -f -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR8) -F $@
+
+$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png plugins/lib%.so $(ANDROID_JAR8)
+ $(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR8) -F $@
+
+# Package installer won't delete old libscummvm.so on upgrade so
+# replace it with a zero size file
+$(APK_MAIN): $(EXECUTABLE) $(FILE_RESOURCES_MAIN) $(FILE_DEX)
+ $(INSTALL) -d $(PATH_STAGE_MAIN)/common/lib/armeabi
+ touch $(PATH_STAGE_MAIN)/common/lib/armeabi/libscummvm.so
+ $(INSTALL) -d $(PATH_STAGE_MAIN)/common/mylib/armeabi
+ $(INSTALL) -c -m 644 libscummvm.so $(PATH_STAGE_MAIN)/common/mylib/armeabi/
+ $(STRIP) $(PATH_STAGE_MAIN)/common/mylib/armeabi/libscummvm.so
+ $(APKBUILDER) $@ -z $(FILE_RESOURCES_MAIN) -f $(FILE_DEX) -rf $(PATH_STAGE_MAIN)/common || { $(RM) $@; exit 1; }
+
+scummvm-engine-%.apk: plugins/lib%.so $(PATH_BUILD)/%/$(FILE_RESOURCES) $(FILE_DEX_PLUGIN)
+ $(INSTALL) -d $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/
+ $(INSTALL) -c -m 644 plugins/lib$*.so $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/
+ $(STRIP) $(PATH_STAGE_PREFIX).$*/apk/mylib/armeabi/lib$*.so
+ $(APKBUILDER) $@ -z $(PATH_BUILD)/$*/$(FILE_RESOURCES) -f $(FILE_DEX_PLUGIN) -rf $(PATH_STAGE_PREFIX).$*/apk || { $(RM) $@; exit 1; }
+
+all: $(APK_MAIN) $(APK_PLUGINS)
+
+clean: androidclean
+
+androidclean:
+ @$(RM) -rf $(PATH_BUILD) $(PATH_STAGE_PREFIX).* *.apk release
+
+# remove debugging signature
release/%.apk: %.apk
@$(MKDIR) -p $(@D)
@$(RM) $@
$(CP) $< $@.tmp
- # remove debugging signature
zip -d $@.tmp META-INF/\*
jarsigner $(JARSIGNER_FLAGS) $@.tmp release
zipalign 4 $@.tmp $@
$(RM) $@.tmp
-androidrelease: release/scummvm.apk $(patsubst plugins/lib%.so,release/scummvm-engine-%.apk,$(PLUGINS))
+androidrelease: $(addprefix release/, $(APK_MAIN) $(APK_PLUGINS))
+
+androidtestmain: $(APK_MAIN)
+ $(ADB) install -r $(APK_MAIN)
+ $(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker
-androidtest: scummvm.apk scummvm-engine-scumm.apk scummvm-engine-kyra.apk
+androidtest: $(APK_MAIN) $(APK_PLUGINS)
@set -e; for apk in $^; do \
- echo $(ADB) install -r $$apk; \
- $(ADB) install -r $$apk; \
+ $(ADB) install -r $$apk; \
done
$(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker
+# used by buildbot!
+androiddistdebug: all
+ $(MKDIR) debug
+ $(CP) $(APK_MAIN) $(APK_PLUGINS) debug/
+ for i in $(DIST_FILES_DOCS) $(PORT_DISTFILES); do \
+ sed 's/$$/\r/' < $$i > debug/`basename $$i`.txt; \
+ done
+
.PHONY: androidrelease androidtest
+
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index 20c6a653c0..8e95029894 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -23,7 +23,7 @@
*
*/
-#if defined(ANDROID)
+#if defined(__ANDROID__)
#include <jni.h>
@@ -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;
@@ -47,23 +46,43 @@ const jint ACCESS_RANDOM = 1;
// This might be useful to someone else. Assumes markSupported() == true.
class JavaInputStream : public Common::SeekableReadStream {
public:
- JavaInputStream(JNIEnv* env, jobject is);
+ JavaInputStream(JNIEnv *env, jobject is);
virtual ~JavaInputStream();
- virtual bool eos() const { return _eos; }
- virtual bool err() const { return _err; }
- virtual void clearErr() { _eos = _err = false; }
+
+ virtual bool eos() const {
+ return _eos;
+ }
+
+ virtual bool err() const {
+ return _err;
+ }
+
+ virtual void clearErr() {
+ _eos = _err = false;
+ }
+
virtual uint32 read(void *dataPtr, uint32 dataSize);
- virtual int32 pos() const { return _pos; }
- virtual int32 size() const { return _len; }
+
+ virtual int32 pos() const {
+ return _pos;
+ }
+
+ virtual int32 size() const {
+ return _len;
+ }
+
virtual bool seek(int32 offset, int whence = SEEK_SET);
+
private:
- void close(JNIEnv* env);
+ void close(JNIEnv *env);
+
jmethodID MID_mark;
jmethodID MID_available;
jmethodID MID_close;
jmethodID MID_read;
jmethodID MID_reset;
jmethodID MID_skip;
+
jobject _input_stream;
jsize _buflen;
jbyteArray _buf;
@@ -73,12 +92,14 @@ private:
bool _err;
};
-JavaInputStream::JavaInputStream(JNIEnv* env, jobject is) :
- _eos(false), _err(false), _pos(0)
+JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) :
+ _eos(false),
+ _err(false),
+ _pos(0)
{
_input_stream = env->NewGlobalRef(is);
_buflen = 8192;
- _buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
+ _buf = (jbyteArray)env->NewGlobalRef(env->NewByteArray(_buflen));
jclass cls = env->GetObjectClass(_input_stream);
MID_mark = env->GetMethodID(cls, "mark", "(I)V");
@@ -97,53 +118,61 @@ JavaInputStream::JavaInputStream(JNIEnv* env, jobject is) :
// Mark start of stream, so we can reset back to it.
// readlimit is set to something bigger than anything we might
// want to seek within.
- env->CallVoidMethod(_input_stream, MID_mark, 10*1024*1024);
+ env->CallVoidMethod(_input_stream, MID_mark, 10 * 1024 * 1024);
_len = env->CallIntMethod(_input_stream, MID_available);
}
JavaInputStream::~JavaInputStream() {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
close(env);
+
env->DeleteGlobalRef(_buf);
env->DeleteGlobalRef(_input_stream);
}
-void JavaInputStream::close(JNIEnv* env) {
+void JavaInputStream::close(JNIEnv *env) {
env->CallVoidMethod(_input_stream, MID_close);
+
if (env->ExceptionCheck())
env->ExceptionClear();
}
uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
- if (_buflen < dataSize) {
+ if (_buflen < jint(dataSize)) {
_buflen = dataSize;
+
env->DeleteGlobalRef(_buf);
_buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
}
jint ret = env->CallIntMethod(_input_stream, MID_read, _buf, 0, dataSize);
+
if (env->ExceptionCheck()) {
warning("Exception during JavaInputStream::read(%p, %d)",
dataPtr, dataSize);
+
env->ExceptionDescribe();
env->ExceptionClear();
+
_err = true;
ret = -1;
} else if (ret == -1) {
_eos = true;
ret = 0;
} else {
- env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte*>(dataPtr));
+ env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte *>(dataPtr));
_pos += ret;
}
+
return ret;
}
bool JavaInputStream::seek(int32 offset, int whence) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
uint32 newpos;
+
switch (whence) {
case SEEK_SET:
newpos = offset;
@@ -165,37 +194,47 @@ bool JavaInputStream::seek(int32 offset, int whence) {
} else {
// Can't skip backwards, so jump back to start and skip from there.
env->CallVoidMethod(_input_stream, MID_reset);
+
if (env->ExceptionCheck()) {
warning("Failed to rewind to start of asset stream");
+
env->ExceptionDescribe();
env->ExceptionClear();
+
return false;
}
+
_pos = 0;
skip_bytes = newpos;
}
while (skip_bytes > 0) {
jlong ret = env->CallLongMethod(_input_stream, MID_skip, skip_bytes);
+
if (env->ExceptionCheck()) {
warning("Failed to skip %ld bytes into asset stream",
static_cast<long>(skip_bytes));
+
env->ExceptionDescribe();
env->ExceptionClear();
+
return false;
} else if (ret == 0) {
warning("InputStream->skip(%ld) didn't skip any bytes. Aborting seek.",
static_cast<long>(skip_bytes));
- return false; // No point looping forever...
+
+ // No point looping forever...
+ return false;
}
+
_pos += ret;
skip_bytes -= ret;
}
+
_eos = false;
return true;
}
-
// Must match android.content.res.AssetFileDescriptor.UNKNOWN_LENGTH
const jlong UNKNOWN_LENGTH = -1;
@@ -203,17 +242,36 @@ const jlong UNKNOWN_LENGTH = -1;
// worth optimising for.
class AssetFdReadStream : public Common::SeekableReadStream {
public:
- AssetFdReadStream(JNIEnv* env, jobject assetfd);
+ AssetFdReadStream(JNIEnv *env, jobject assetfd);
virtual ~AssetFdReadStream();
- virtual bool eos() const { return _eos; }
- virtual bool err() const { return _err; }
- virtual void clearErr() { _eos = _err = false; }
+
+ virtual bool eos() const {
+ return _eos;
+ }
+
+ virtual bool err() const {
+ return _err;
+ }
+
+ virtual void clearErr() {
+ _eos = _err = false;
+ }
+
virtual uint32 read(void *dataPtr, uint32 dataSize);
- virtual int32 pos() const { return _pos; }
- virtual int32 size() const { return _declared_len; }
+
+ virtual int32 pos() const {
+ return _pos;
+ }
+
+ virtual int32 size() const {
+ return _declared_len;
+ }
+
virtual bool seek(int32 offset, int whence = SEEK_SET);
+
private:
- void close(JNIEnv* env);
+ void close(JNIEnv *env);
+
int _fd;
jmethodID MID_close;
jobject _assetfd;
@@ -224,8 +282,10 @@ private:
bool _err;
};
-AssetFdReadStream::AssetFdReadStream(JNIEnv* env, jobject assetfd) :
- _eos(false), _err(false), _pos(0)
+AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
+ _eos(false),
+ _err(false),
+ _pos(0)
{
_assetfd = env->NewGlobalRef(assetfd);
@@ -244,21 +304,26 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv* env, jobject assetfd) :
_declared_len = env->CallLongMethod(_assetfd, MID_getDeclaredLength);
jmethodID MID_getFileDescriptor =
- env->GetMethodID(cls, "getFileDescriptor", "()Ljava/io/FileDescriptor;");
+ env->GetMethodID(cls, "getFileDescriptor",
+ "()Ljava/io/FileDescriptor;");
assert(MID_getFileDescriptor);
jobject javafd = env->CallObjectMethod(_assetfd, MID_getFileDescriptor);
assert(javafd);
+
jclass fd_cls = env->GetObjectClass(javafd);
jfieldID FID_descriptor = env->GetFieldID(fd_cls, "descriptor", "I");
assert(FID_descriptor);
+
_fd = env->GetIntField(javafd, FID_descriptor);
}
AssetFdReadStream::~AssetFdReadStream() {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
env->CallVoidMethod(_assetfd, MID_close);
+
if (env->ExceptionCheck())
env->ExceptionClear();
+
env->DeleteGlobalRef(_assetfd);
}
@@ -268,13 +333,16 @@ uint32 AssetFdReadStream::read(void *dataPtr, uint32 dataSize) {
if (dataSize > cap)
dataSize = cap;
}
+
int ret = ::read(_fd, dataPtr, dataSize);
+
if (ret == 0)
_eos = true;
else if (ret == -1)
_err = true;
else
_pos += ret;
+
return ret;
}
@@ -282,42 +350,49 @@ bool AssetFdReadStream::seek(int32 offset, int whence) {
if (whence == SEEK_SET) {
if (_declared_len != UNKNOWN_LENGTH && offset > _declared_len)
offset = _declared_len;
+
offset += _start_off;
} else if (whence == SEEK_END && _declared_len != UNKNOWN_LENGTH) {
whence = SEEK_SET;
offset = _start_off + _declared_len + offset;
}
+
int ret = lseek(_fd, offset, whence);
+
if (ret == -1)
return false;
+
_pos = ret - _start_off;
_eos = false;
+
return true;
}
AndroidAssetArchive::AndroidAssetArchive(jobject am) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
_am = env->NewGlobalRef(am);
jclass cls = env->GetObjectClass(_am);
MID_open = env->GetMethodID(cls, "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
assert(MID_open);
- MID_openFd = env->GetMethodID(cls, "openFd",
- "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
+
+ MID_openFd = env->GetMethodID(cls, "openFd", "(Ljava/lang/String;)"
+ "Landroid/content/res/AssetFileDescriptor;");
assert(MID_openFd);
+
MID_list = env->GetMethodID(cls, "list",
"(Ljava/lang/String;)[Ljava/lang/String;");
assert(MID_list);
}
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()) {
@@ -326,15 +401,18 @@ bool AndroidAssetArchive::hasFile(const Common::String &name) {
//env->ExceptionDescribe();
env->ExceptionClear();
env->DeleteLocalRef(path);
+
return false;
}
+
env->DeleteLocalRef(result);
env->DeleteLocalRef(path);
+
return true;
}
int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
- JNIEnv* env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
Common::List<Common::String> dirlist;
dirlist.push_back("");
@@ -344,30 +422,41 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
dirlist.pop_back();
jstring jpath = env->NewStringUTF(dir.c_str());
- jobjectArray jpathlist = static_cast<jobjectArray>(env->CallObjectMethod(_am, MID_list, jpath));
+ jobjectArray jpathlist =
+ (jobjectArray)env->CallObjectMethod(_am, MID_list, jpath);
+
if (env->ExceptionCheck()) {
warning("Error while calling AssetManager->list(%s). Ignoring.",
dir.c_str());
env->ExceptionDescribe();
env->ExceptionClear();
- continue; // May as well keep going ...
+
+ // May as well keep going ...
+ continue;
}
+
env->DeleteLocalRef(jpath);
for (jsize i = 0; i < env->GetArrayLength(jpathlist); ++i) {
jstring elem = (jstring)env->GetObjectArrayElement(jpathlist, i);
- const char* p = env->GetStringUTFChars(elem, NULL);
- Common::String thispath = dir;
- if (!thispath.empty())
- thispath += "/";
- thispath += p;
-
- // Assume files have a . in them, and directories don't
- if (strchr(p, '.')) {
- member_list.push_back(getMember(thispath));
- ++count;
- } else
- dirlist.push_back(thispath);
+ const char *p = env->GetStringUTFChars(elem, 0);
+
+ if (strlen(p)) {
+ Common::String thispath = dir;
+
+ if (!thispath.empty())
+ thispath += "/";
+
+ thispath += p;
+
+ // Assume files have a . in them, and directories don't
+ if (strchr(p, '.')) {
+ member_list.push_back(getMember(thispath));
+ ++count;
+ } else {
+ dirlist.push_back(thispath);
+ }
+ }
env->ReleaseStringUTFChars(elem, p);
env->DeleteLocalRef(elem);
@@ -384,14 +473,15 @@ 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 ...
jobject afd = env->CallObjectMethod(_am, MID_openFd, jpath);
+
if (env->ExceptionCheck())
env->ExceptionClear();
- else if (afd != NULL) {
+ else if (afd != 0) {
// success :)
env->DeleteLocalRef(jpath);
return new AssetFdReadStream(env, afd);
@@ -399,13 +489,15 @@ Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const
// ... and fallback to normal open() if that doesn't work
jobject is = env->CallObjectMethod(_am, MID_open, jpath, ACCESS_RANDOM);
+
if (env->ExceptionCheck()) {
// Assume FileNotFoundException
//warning("Error opening %s", path.c_str());
//env->ExceptionDescribe();
env->ExceptionClear();
env->DeleteLocalRef(jpath);
- return NULL;
+
+ return 0;
}
return new JavaInputStream(env, is);
diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h
index b3f6993c50..6ec86e4cd0 100644
--- a/backends/platform/android/asset-archive.h
+++ b/backends/platform/android/asset-archive.h
@@ -23,7 +23,10 @@
*
*/
-#if defined(ANDROID)
+#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/events.cpp b/backends/platform/android/events.cpp
new file mode 100644
index 0000000000..09466b4d2f
--- /dev/null
+++ b/backends/platform/android/events.cpp
@@ -0,0 +1,805 @@
+/* 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 "common/events.h"
+
+#include "backends/platform/android/android.h"
+#include "backends/platform/android/jni.h"
+
+// $ANDROID_NDK/platforms/android-9/arch-arm/usr/include/android/keycodes.h
+// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=libs/ui/Input.cpp
+// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/KeyEvent.java
+
+// event type
+enum {
+ JE_SYS_KEY = 0,
+ JE_KEY = 1,
+ JE_DPAD = 2,
+ JE_DOWN = 3,
+ JE_SCROLL = 4,
+ JE_TAP = 5,
+ JE_DOUBLE_TAP = 6,
+ JE_MULTI = 7,
+ JE_BALL = 8,
+ JE_QUIT = 0x1000
+};
+
+// action type
+enum {
+ JACTION_DOWN = 0,
+ JACTION_UP = 1,
+ JACTION_MULTIPLE = 2,
+ JACTION_POINTER_DOWN = 5,
+ JACTION_POINTER_UP = 6
+};
+
+// system keys
+enum {
+ JKEYCODE_SOFT_RIGHT = 2,
+ JKEYCODE_HOME = 3,
+ JKEYCODE_BACK = 4,
+ JKEYCODE_CALL = 5,
+ JKEYCODE_ENDCALL = 6,
+ JKEYCODE_VOLUME_UP = 24,
+ JKEYCODE_VOLUME_DOWN = 25,
+ JKEYCODE_POWER = 26,
+ JKEYCODE_CAMERA = 27,
+ JKEYCODE_HEADSETHOOK = 79,
+ JKEYCODE_FOCUS = 80,
+ JKEYCODE_MENU = 82,
+ JKEYCODE_SEARCH = 84,
+ JKEYCODE_MUTE = 91,
+ JKEYCODE_MEDIA_PLAY_PAUSE = 85,
+ JKEYCODE_MEDIA_STOP = 86,
+ JKEYCODE_MEDIA_NEXT = 87,
+ JKEYCODE_MEDIA_PREVIOUS = 88,
+ JKEYCODE_MEDIA_REWIND = 89,
+ JKEYCODE_MEDIA_FAST_FORWARD = 90
+};
+
+// five-way navigation control
+enum {
+ JKEYCODE_DPAD_UP = 19,
+ JKEYCODE_DPAD_DOWN = 20,
+ JKEYCODE_DPAD_LEFT = 21,
+ JKEYCODE_DPAD_RIGHT = 22,
+ JKEYCODE_DPAD_CENTER = 23
+};
+
+// meta modifier
+enum {
+ JMETA_SHIFT = 0x01,
+ JMETA_ALT = 0x02,
+ JMETA_SYM = 0x04,
+ JMETA_CTRL = 0x1000
+};
+
+// map android key codes to our kbd codes
+static const Common::KeyCode jkeymap[] = {
+ Common::KEYCODE_INVALID, // KEYCODE_UNKNOWN
+ Common::KEYCODE_INVALID, // KEYCODE_SOFT_LEFT
+ Common::KEYCODE_INVALID, // KEYCODE_SOFT_RIGHT
+ Common::KEYCODE_INVALID, // KEYCODE_HOME
+ Common::KEYCODE_INVALID, // KEYCODE_BACK
+ Common::KEYCODE_INVALID, // KEYCODE_CALL
+ Common::KEYCODE_INVALID, // KEYCODE_ENDCALL
+ Common::KEYCODE_0, // KEYCODE_0
+ Common::KEYCODE_1, // KEYCODE_1
+ Common::KEYCODE_2, // KEYCODE_2
+ Common::KEYCODE_3, // KEYCODE_3
+ Common::KEYCODE_4, // KEYCODE_4
+ Common::KEYCODE_5, // KEYCODE_5
+ Common::KEYCODE_6, // KEYCODE_6
+ Common::KEYCODE_7, // KEYCODE_7
+ Common::KEYCODE_8, // KEYCODE_8
+ Common::KEYCODE_9, // KEYCODE_9
+ Common::KEYCODE_ASTERISK, // KEYCODE_STAR
+ Common::KEYCODE_HASH, // KEYCODE_POUND
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_UP
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_DOWN
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_LEFT
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_RIGHT
+ Common::KEYCODE_INVALID, // KEYCODE_DPAD_CENTER
+ Common::KEYCODE_INVALID, // KEYCODE_VOLUME_UP
+ Common::KEYCODE_INVALID, // KEYCODE_VOLUME_DOWN
+ Common::KEYCODE_INVALID, // KEYCODE_POWER
+ Common::KEYCODE_INVALID, // KEYCODE_CAMERA
+ Common::KEYCODE_INVALID, // KEYCODE_CLEAR
+ Common::KEYCODE_a, // KEYCODE_A
+ Common::KEYCODE_b, // KEYCODE_B
+ Common::KEYCODE_c, // KEYCODE_C
+ Common::KEYCODE_d, // KEYCODE_D
+ Common::KEYCODE_e, // KEYCODE_E
+ Common::KEYCODE_f, // KEYCODE_F
+ Common::KEYCODE_g, // KEYCODE_G
+ Common::KEYCODE_h, // KEYCODE_H
+ Common::KEYCODE_i, // KEYCODE_I
+ Common::KEYCODE_j, // KEYCODE_J
+ Common::KEYCODE_k, // KEYCODE_K
+ Common::KEYCODE_l, // KEYCODE_L
+ Common::KEYCODE_m, // KEYCODE_M
+ Common::KEYCODE_n, // KEYCODE_N
+ Common::KEYCODE_o, // KEYCODE_O
+ Common::KEYCODE_p, // KEYCODE_P
+ Common::KEYCODE_q, // KEYCODE_Q
+ Common::KEYCODE_r, // KEYCODE_R
+ Common::KEYCODE_s, // KEYCODE_S
+ Common::KEYCODE_t, // KEYCODE_T
+ Common::KEYCODE_u, // KEYCODE_U
+ Common::KEYCODE_v, // KEYCODE_V
+ Common::KEYCODE_w, // KEYCODE_W
+ Common::KEYCODE_x, // KEYCODE_X
+ Common::KEYCODE_y, // KEYCODE_Y
+ Common::KEYCODE_z, // KEYCODE_Z
+ Common::KEYCODE_COMMA, // KEYCODE_COMMA
+ Common::KEYCODE_PERIOD, // KEYCODE_PERIOD
+ Common::KEYCODE_LALT, // KEYCODE_ALT_LEFT
+ Common::KEYCODE_RALT, // KEYCODE_ALT_RIGHT
+ Common::KEYCODE_LSHIFT, // KEYCODE_SHIFT_LEFT
+ Common::KEYCODE_RSHIFT, // KEYCODE_SHIFT_RIGHT
+ Common::KEYCODE_TAB, // KEYCODE_TAB
+ Common::KEYCODE_SPACE, // KEYCODE_SPACE
+ Common::KEYCODE_LCTRL, // KEYCODE_SYM
+ Common::KEYCODE_INVALID, // KEYCODE_EXPLORER
+ Common::KEYCODE_INVALID, // KEYCODE_ENVELOPE
+ Common::KEYCODE_RETURN, // KEYCODE_ENTER
+ Common::KEYCODE_BACKSPACE, // KEYCODE_DEL
+ Common::KEYCODE_BACKQUOTE, // KEYCODE_GRAVE
+ Common::KEYCODE_MINUS, // KEYCODE_MINUS
+ Common::KEYCODE_EQUALS, // KEYCODE_EQUALS
+ Common::KEYCODE_LEFTPAREN, // KEYCODE_LEFT_BRACKET
+ Common::KEYCODE_RIGHTPAREN, // KEYCODE_RIGHT_BRACKET
+ Common::KEYCODE_BACKSLASH, // KEYCODE_BACKSLASH
+ Common::KEYCODE_SEMICOLON, // KEYCODE_SEMICOLON
+ Common::KEYCODE_QUOTE, // KEYCODE_APOSTROPHE
+ Common::KEYCODE_SLASH, // KEYCODE_SLASH
+ Common::KEYCODE_AT, // KEYCODE_AT
+ Common::KEYCODE_INVALID, // KEYCODE_NUM
+ Common::KEYCODE_INVALID, // KEYCODE_HEADSETHOOK
+ Common::KEYCODE_INVALID, // KEYCODE_FOCUS
+ Common::KEYCODE_PLUS, // KEYCODE_PLUS
+ Common::KEYCODE_INVALID, // KEYCODE_MENU
+ Common::KEYCODE_INVALID, // KEYCODE_NOTIFICATION
+ Common::KEYCODE_INVALID, // KEYCODE_SEARCH
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PLAY_PAUSE
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_STOP
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_NEXT
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PREVIOUS
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_REWIND
+ Common::KEYCODE_INVALID, // KEYCODE_MEDIA_FAST_FORWARD
+ Common::KEYCODE_INVALID, // KEYCODE_MUTE
+ Common::KEYCODE_PAGEUP, // KEYCODE_PAGE_UP
+ Common::KEYCODE_PAGEDOWN // KEYCODE_PAGE_DOWN
+};
+
+// floating point. use sparingly
+template <class T>
+static inline T scalef(T in, float numerator, float denominator) {
+ return static_cast<float>(in) * numerator / denominator;
+}
+
+void OSystem_Android::setupKeymapper() {
+#ifdef ENABLE_KEYMAPPER
+ using namespace Common;
+
+ Keymapper *mapper = getEventManager()->getKeymapper();
+
+ HardwareKeySet *keySet = new HardwareKeySet();
+
+ keySet->addHardwareKey(
+ new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)",
+ kTriggerLeftKeyType,
+ kVirtualKeyboardActionType));
+
+ mapper->registerHardwareKeySet(keySet);
+
+ Keymap *globalMap = new Keymap("global");
+ Action *act;
+
+ act = new Action(globalMap, "VIRT", "Display keyboard",
+ kVirtualKeyboardActionType);
+ act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
+
+ mapper->addGlobalKeymap(globalMap);
+
+ mapper->pushKeymap("global");
+#endif
+}
+
+void OSystem_Android::warpMouse(int x, int y) {
+ ENTER("%d, %d", x, y);
+
+ Common::Event e;
+
+ e.type = Common::EVENT_MOUSEMOVE;
+ e.mouse.x = x;
+ e.mouse.y = y;
+
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+}
+
+void OSystem_Android::clipMouse(Common::Point &p) {
+ const GLESBaseTexture *tex;
+
+ if (_show_overlay)
+ tex = _overlay_texture;
+ else
+ tex = _game_texture;
+
+ p.x = CLIP(p.x, int16(0), int16(tex->width() - 1));
+ p.y = CLIP(p.y, int16(0), int16(tex->height() - 1));
+}
+
+void OSystem_Android::scaleMouse(Common::Point &p, int x, int y,
+ bool deductDrawRect) {
+ const GLESBaseTexture *tex;
+
+ if (_show_overlay)
+ tex = _overlay_texture;
+ else
+ tex = _game_texture;
+
+ const Common::Rect &r = tex->getDrawRect();
+
+ if (_touchpad_mode) {
+ x = x * 100 / _touchpad_scale;
+ y = y * 100 / _touchpad_scale;
+ }
+
+ if (deductDrawRect) {
+ x -= r.left;
+ y -= r.top;
+ }
+
+ p.x = scalef(x, tex->width(), r.width());
+ p.y = scalef(y, tex->height(), r.height());
+}
+
+void OSystem_Android::updateEventScale() {
+ const GLESBaseTexture *tex;
+
+ if (_show_overlay)
+ tex = _overlay_texture;
+ else
+ tex = _game_texture;
+
+ _eventScaleY = 100 * 480 / tex->height();
+ _eventScaleX = 100 * 640 / tex->width();
+}
+
+void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
+ int arg4, int arg5) {
+ Common::Event e;
+
+ switch (type) {
+ case JE_SYS_KEY:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_KEYDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_KEYUP;
+ break;
+ default:
+ LOGE("unhandled jaction on system key: %d", arg1);
+ return;
+ }
+
+ switch (arg2) {
+ case JKEYCODE_BACK:
+ e.kbd.keycode = Common::KEYCODE_ESCAPE;
+ e.kbd.ascii = Common::ASCII_ESCAPE;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ // special case. we'll only get it's up event
+ case JKEYCODE_MENU:
+ e.type = Common::EVENT_MAINMENU;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JKEYCODE_CAMERA:
+ case JKEYCODE_SEARCH:
+ if (arg1 == JACTION_DOWN)
+ e.type = Common::EVENT_RBUTTONDOWN;
+ else
+ e.type = Common::EVENT_RBUTTONUP;
+
+ e.mouse = getEventManager()->getMousePos();
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ default:
+ LOGW("unmapped system key: %d", arg2);
+ return;
+ }
+
+ break;
+
+ case JE_KEY:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_KEYDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_KEYUP;
+ break;
+ default:
+ LOGE("unhandled jaction on key: %d", arg1);
+ return;
+ }
+
+ if (arg2 < 1 || arg2 > ARRAYSIZE(jkeymap)) {
+ if (arg3 < 1) {
+ LOGE("received invalid keycode: %d (%d)", arg2, arg3);
+ return;
+ } else {
+ // lets bet on the ascii code
+ e.kbd.keycode = Common::KEYCODE_INVALID;
+ }
+ } else {
+ e.kbd.keycode = jkeymap[arg2];
+ }
+
+ if (arg5 > 0)
+ e.synthetic = true;
+
+ // map special keys to 'our' ascii codes
+ switch (e.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ e.kbd.ascii = Common::ASCII_BACKSPACE;
+ break;
+ case Common::KEYCODE_TAB:
+ e.kbd.ascii = Common::ASCII_TAB;
+ break;
+ case Common::KEYCODE_RETURN:
+ e.kbd.ascii = Common::ASCII_RETURN;
+ break;
+ case Common::KEYCODE_ESCAPE:
+ e.kbd.ascii = Common::ASCII_ESCAPE;
+ break;
+ case Common::KEYCODE_SPACE:
+ e.kbd.ascii = Common::ASCII_SPACE;
+ break;
+ case Common::KEYCODE_F1:
+ e.kbd.ascii = Common::ASCII_F1;
+ break;
+ case Common::KEYCODE_F2:
+ e.kbd.ascii = Common::ASCII_F2;
+ break;
+ case Common::KEYCODE_F3:
+ e.kbd.ascii = Common::ASCII_F3;
+ break;
+ case Common::KEYCODE_F4:
+ e.kbd.ascii = Common::ASCII_F4;
+ break;
+ case Common::KEYCODE_F5:
+ e.kbd.ascii = Common::ASCII_F5;
+ break;
+ case Common::KEYCODE_F6:
+ e.kbd.ascii = Common::ASCII_F6;
+ break;
+ case Common::KEYCODE_F7:
+ e.kbd.ascii = Common::ASCII_F7;
+ break;
+ case Common::KEYCODE_F8:
+ e.kbd.ascii = Common::ASCII_F8;
+ break;
+ case Common::KEYCODE_F9:
+ e.kbd.ascii = Common::ASCII_F9;
+ break;
+ case Common::KEYCODE_F10:
+ e.kbd.ascii = Common::ASCII_F10;
+ break;
+ case Common::KEYCODE_F11:
+ e.kbd.ascii = Common::ASCII_F11;
+ break;
+ case Common::KEYCODE_F12:
+ e.kbd.ascii = Common::ASCII_F12;
+ break;
+ default:
+ e.kbd.ascii = arg3;
+ break;
+ }
+
+ if (arg4 & JMETA_SHIFT)
+ e.kbd.flags |= Common::KBD_SHIFT;
+ if (arg4 & JMETA_ALT)
+ e.kbd.flags |= Common::KBD_ALT;
+ if (arg4 & (JMETA_SYM | JMETA_CTRL))
+ e.kbd.flags |= Common::KBD_CTRL;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_DPAD:
+ switch (arg2) {
+ case JKEYCODE_DPAD_UP:
+ case JKEYCODE_DPAD_DOWN:
+ case JKEYCODE_DPAD_LEFT:
+ case JKEYCODE_DPAD_RIGHT:
+ if (arg1 != JACTION_DOWN)
+ return;
+
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ e.mouse = getEventManager()->getMousePos();
+
+ {
+ int16 *c;
+ int s;
+
+ if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_DOWN) {
+ c = &e.mouse.y;
+ s = _eventScaleY;
+ } else {
+ c = &e.mouse.x;
+ s = _eventScaleX;
+ }
+
+ // the longer the button held, the faster the pointer is
+ // TODO put these values in some option dlg?
+ int f = CLIP(arg4, 1, 8) * _dpad_scale * 100 / s;
+
+ if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_LEFT)
+ *c -= f;
+ else
+ *c += f;
+ }
+
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JKEYCODE_DPAD_CENTER:
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_LBUTTONDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_LBUTTONUP;
+ break;
+ default:
+ LOGE("unhandled jaction on dpad key: %d", arg1);
+ return;
+ }
+
+ e.mouse = getEventManager()->getMousePos();
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+ }
+
+ case JE_DOWN:
+ _touch_pt_down = getEventManager()->getMousePos();
+ _touch_pt_scroll.x = -1;
+ _touch_pt_scroll.y = -1;
+ break;
+
+ case JE_SCROLL:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ if (_touch_pt_scroll.x == -1 && _touch_pt_scroll.y == -1) {
+ _touch_pt_scroll.x = arg3;
+ _touch_pt_scroll.y = arg4;
+ return;
+ }
+
+ scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x,
+ arg4 - _touch_pt_scroll.y, false);
+ e.mouse += _touch_pt_down;
+ clipMouse(e.mouse);
+ } else {
+ scaleMouse(e.mouse, arg3, arg4);
+ clipMouse(e.mouse);
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_TAP:
+ if (_fingersDown > 0) {
+ _fingersDown = 0;
+ return;
+ }
+
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ e.mouse = getEventManager()->getMousePos();
+ } else {
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+ }
+
+ {
+ Common::EventType down, up;
+
+ // TODO put these values in some option dlg?
+ if (arg3 > 1000) {
+ down = Common::EVENT_MBUTTONDOWN;
+ up = Common::EVENT_MBUTTONUP;
+ } else if (arg3 > 500) {
+ down = Common::EVENT_RBUTTONDOWN;
+ up = Common::EVENT_RBUTTONUP;
+ } else {
+ down = Common::EVENT_LBUTTONDOWN;
+ up = Common::EVENT_LBUTTONUP;
+ }
+
+ lockMutex(_event_queue_lock);
+
+ if (!_touchpad_mode)
+ _event_queue.push(e);
+
+ e.type = down;
+ _event_queue.push(e);
+ e.type = up;
+ _event_queue.push(e);
+
+ unlockMutex(_event_queue_lock);
+ }
+
+ return;
+
+ case JE_DOUBLE_TAP:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ e.mouse = getEventManager()->getMousePos();
+ } else {
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+ }
+
+ {
+ Common::EventType dptype = Common::EVENT_INVALID;
+
+ switch (arg3) {
+ case JACTION_DOWN:
+ dptype = Common::EVENT_LBUTTONDOWN;
+ _touch_pt_dt.x = -1;
+ _touch_pt_dt.y = -1;
+ break;
+ case JACTION_UP:
+ dptype = Common::EVENT_LBUTTONUP;
+ break;
+ // held and moved
+ case JACTION_MULTIPLE:
+ if (_touch_pt_dt.x == -1 && _touch_pt_dt.y == -1) {
+ _touch_pt_dt.x = arg1;
+ _touch_pt_dt.y = arg2;
+ return;
+ }
+
+ dptype = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ scaleMouse(e.mouse, arg1 - _touch_pt_dt.x,
+ arg2 - _touch_pt_dt.y, false);
+ e.mouse += _touch_pt_down;
+
+ clipMouse(e.mouse);
+ }
+
+ break;
+ default:
+ LOGE("unhandled jaction on double tap: %d", arg3);
+ return;
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ e.type = dptype;
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+ }
+
+ return;
+
+ case JE_MULTI:
+ switch (arg2) {
+ case JACTION_POINTER_DOWN:
+ if (arg1 > _fingersDown)
+ _fingersDown = arg1;
+
+ return;
+
+ case JACTION_POINTER_UP:
+ if (arg1 != _fingersDown)
+ return;
+
+ {
+ Common::EventType up;
+
+ switch (_fingersDown) {
+ case 1:
+ e.type = Common::EVENT_RBUTTONDOWN;
+ up = Common::EVENT_RBUTTONUP;
+ break;
+ case 2:
+ e.type = Common::EVENT_MBUTTONDOWN;
+ up = Common::EVENT_MBUTTONUP;
+ break;
+ default:
+ LOGD("unmapped multi tap: %d", _fingersDown);
+ return;
+ }
+
+ e.mouse = getEventManager()->getMousePos();
+
+ lockMutex(_event_queue_lock);
+
+ _event_queue.push(e);
+ e.type = up;
+ _event_queue.push(e);
+
+ unlockMutex(_event_queue_lock);
+ return;
+
+ default:
+ LOGE("unhandled jaction on multi tap: %d", arg2);
+ return;
+ }
+ }
+
+ return;
+
+ case JE_BALL:
+ e.mouse = getEventManager()->getMousePos();
+
+ switch (arg1) {
+ case JACTION_DOWN:
+ e.type = Common::EVENT_LBUTTONDOWN;
+ break;
+ case JACTION_UP:
+ e.type = Common::EVENT_LBUTTONUP;
+ break;
+ case JACTION_MULTIPLE:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ // already multiplied by 100
+ e.mouse.x += arg2 * _trackball_scale / _eventScaleX;
+ e.mouse.y += arg3 * _trackball_scale / _eventScaleY;
+
+ clipMouse(e.mouse);
+
+ break;
+ default:
+ LOGE("unhandled jaction on system key: %d", arg1);
+ return;
+ }
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_QUIT:
+ e.type = Common::EVENT_QUIT;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ default:
+ LOGE("unknown jevent type: %d", type);
+
+ break;
+ }
+}
+
+bool OSystem_Android::pollEvent(Common::Event &event) {
+ //ENTER();
+
+ if (pthread_self() == _main_thread) {
+ if (_screen_changeid != JNI::surface_changeid) {
+ if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
+ // surface changed
+ JNI::deinitSurface();
+ initSurface();
+ initViewport();
+ updateScreenRect();
+ updateEventScale();
+
+ // double buffered, flip twice
+ clearScreen(kClearUpdate, 2);
+
+ event.type = Common::EVENT_SCREEN_CHANGED;
+
+ return true;
+ } else {
+ // surface lost
+ deinitSurface();
+ }
+ }
+
+ if (JNI::pause) {
+ deinitSurface();
+
+ LOGD("main thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("main thread woke up");
+ }
+ }
+
+ lockMutex(_event_queue_lock);
+
+ if (_event_queue.empty()) {
+ unlockMutex(_event_queue_lock);
+ return false;
+ }
+
+ event = _event_queue.pop();
+
+ unlockMutex(_event_queue_lock);
+
+ if (event.type == Common::EVENT_MOUSEMOVE) {
+ const Common::Point &m = getEventManager()->getMousePos();
+
+ if (m != event.mouse)
+ _force_redraw = true;
+ }
+
+ return true;
+}
+
+#endif
+
diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp
new file mode 100644
index 0000000000..86232030ff
--- /dev/null
+++ b/backends/platform/android/gfx.cpp
@@ -0,0 +1,819 @@
+/* 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 "common/endian.h"
+#include "graphics/conversion.h"
+
+#include "backends/platform/android/android.h"
+#include "backends/platform/android/jni.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", 0 },
+ { "filter", "Linear filtering", 1 },
+ { 0, 0, 0 },
+ };
+
+ return s_supportedGraphicsModes;
+}
+
+int OSystem_Android::getDefaultGraphicsMode() const {
+ return 0;
+}
+
+bool OSystem_Android::setGraphicsMode(int mode) {
+ ENTER("%d", mode);
+
+ if (_game_texture)
+ _game_texture->setLinearFilter(mode == 1);
+
+ if (_overlay_texture)
+ _overlay_texture->setLinearFilter(mode == 1);
+
+ if (_mouse_texture)
+ _mouse_texture->setLinearFilter(mode == 1);
+
+ _graphicsMode = mode;
+
+ return true;
+}
+
+int OSystem_Android::getGraphicsMode() const {
+ return _graphicsMode;
+}
+
+#ifdef USE_RGB_COLOR
+Graphics::PixelFormat OSystem_Android::getScreenFormat() const {
+ return _game_texture->getPixelFormat();
+}
+
+Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const {
+ Common::List<Graphics::PixelFormat> res;
+ res.push_back(GLES565Texture::pixelFormat());
+ res.push_back(GLES5551Texture::pixelFormat());
+ res.push_back(GLES4444Texture::pixelFormat());
+ res.push_back(Graphics::PixelFormat::createFormatCLUT8());
+
+ return res;
+}
+
+Common::String OSystem_Android::getPixelFormatName(const Graphics::PixelFormat &format) const {
+ if (format.bytesPerPixel == 1)
+ return "CLUT8";
+
+ if (format.aLoss == 8)
+ return Common::String::format("RGB%u%u%u",
+ 8 - format.rLoss,
+ 8 - format.gLoss,
+ 8 - format.bLoss);
+
+ return Common::String::format("RGBA%u%u%u%u",
+ 8 - format.rLoss,
+ 8 - format.gLoss,
+ 8 - format.bLoss,
+ 8 - format.aLoss);
+}
+
+void OSystem_Android::initTexture(GLESBaseTexture **texture,
+ uint width, uint height,
+ const Graphics::PixelFormat *format) {
+ assert(texture);
+ Graphics::PixelFormat format_clut8 =
+ Graphics::PixelFormat::createFormatCLUT8();
+ Graphics::PixelFormat format_current;
+ Graphics::PixelFormat format_new;
+
+ if (*texture)
+ format_current = (*texture)->getPixelFormat();
+ else
+ format_current = Graphics::PixelFormat();
+
+ if (format)
+ format_new = *format;
+ else
+ format_new = format_clut8;
+
+ if (format_current != format_new) {
+ if (*texture)
+ LOGD("switching pixel format from: %s",
+ getPixelFormatName((*texture)->getPixelFormat()).c_str());
+
+ delete *texture;
+
+ if (format_new == GLES565Texture::pixelFormat())
+ *texture = new GLES565Texture();
+ else if (format_new == GLES5551Texture::pixelFormat())
+ *texture = new GLES5551Texture();
+ else if (format_new == GLES4444Texture::pixelFormat())
+ *texture = new GLES4444Texture();
+ else {
+ // TODO what now?
+ if (format_new != format_clut8)
+ LOGE("unsupported pixel format: %s",
+ getPixelFormatName(format_new).c_str());
+
+ *texture = new GLESFakePalette565Texture;
+ }
+
+ LOGD("new pixel format: %s",
+ getPixelFormatName((*texture)->getPixelFormat()).c_str());
+ }
+
+ (*texture)->allocBuffer(width, height);
+}
+#endif
+
+void OSystem_Android::initSurface() {
+ LOGD("initializing surface");
+
+ assert(!JNI::haveSurface());
+
+ _screen_changeid = JNI::surface_changeid;
+ _egl_surface_width = JNI::egl_surface_width;
+ _egl_surface_height = JNI::egl_surface_height;
+
+ assert(_egl_surface_width > 0 && _egl_surface_height > 0);
+
+ JNI::initSurface();
+
+ // Initialise OpenGLES context.
+ GLESTexture::initGLExtensions();
+
+ if (_game_texture)
+ _game_texture->reinit();
+
+ if (_overlay_texture) {
+ _overlay_texture->reinit();
+ initOverlay();
+ }
+
+ if (_mouse_texture)
+ _mouse_texture->reinit();
+}
+
+void OSystem_Android::deinitSurface() {
+ if (!JNI::haveSurface())
+ return;
+
+ LOGD("deinitializing surface");
+
+ _screen_changeid = JNI::surface_changeid;
+ _egl_surface_width = 0;
+ _egl_surface_height = 0;
+
+ // release texture resources
+ if (_game_texture)
+ _game_texture->release();
+
+ if (_overlay_texture)
+ _overlay_texture->release();
+
+ if (_mouse_texture)
+ _mouse_texture->release();
+
+ JNI::deinitSurface();
+}
+
+void OSystem_Android::initViewport() {
+ LOGD("initializing viewport");
+
+ assert(JNI::haveSurface());
+
+ // 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));
+
+ 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::initOverlay() {
+ // minimum of 320x200
+ // (surface can get smaller when opening the virtual keyboard on *QVGA*)
+ int overlay_width = MAX(_egl_surface_width, 320);
+ int overlay_height = MAX(_egl_surface_height, 200);
+
+ // 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
+ while (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);
+ _overlay_texture->setDrawRect(0, 0,
+ _egl_surface_width, _egl_surface_height);
+}
+
+void OSystem_Android::initSize(uint width, uint height,
+ const Graphics::PixelFormat *format) {
+ ENTER("%d, %d, %p", width, height, format);
+
+ GLTHREADCHECK;
+
+#ifdef USE_RGB_COLOR
+ initTexture(&_game_texture, width, height, format);
+#else
+ _game_texture->allocBuffer(width, height);
+#endif
+
+ updateScreenRect();
+ updateEventScale();
+
+ // 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_palette->allocBuffer(20, 20);
+
+ clearScreen(kClear);
+}
+
+void OSystem_Android::clearScreen(FixupType type, byte count) {
+ assert(count > 0);
+
+ bool sm = _show_mouse;
+ _show_mouse = false;
+
+ GLCALL(glDisable(GL_SCISSOR_TEST));
+
+ for (byte i = 0; i < count; ++i) {
+ // clear screen
+ GLCALL(glClearColorx(0, 0, 0, 1 << 16));
+ GLCALL(glClear(GL_COLOR_BUFFER_BIT));
+
+ switch (type) {
+ case kClear:
+ break;
+
+ case kClearSwap:
+ JNI::swapBuffers();
+ break;
+
+ case kClearUpdate:
+ _force_redraw = true;
+ updateScreen();
+ break;
+ }
+ }
+
+ if (!_show_overlay)
+ GLCALL(glEnable(GL_SCISSOR_TEST));
+
+ _show_mouse = sm;
+ _force_redraw = true;
+}
+
+void OSystem_Android::updateScreenRect() {
+ Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height);
+
+ _overlay_texture->setDrawRect(rect);
+
+ uint16 w = _game_texture->width();
+ uint16 h = _game_texture->height();
+
+ if (w && h && !_fullscreen) {
+ if (_ar_correction && w == 320 && h == 200)
+ h = 240;
+
+ float dpi[2];
+ JNI::getDPI(dpi);
+
+ float screen_ar;
+ if (dpi[0] != 0.0 && dpi[1] != 0.0) {
+ // horizontal orientation
+ screen_ar = (dpi[1] * _egl_surface_width) /
+ (dpi[0] * _egl_surface_height);
+ } else {
+ screen_ar = float(_egl_surface_width) / float(_egl_surface_height);
+ }
+
+ float game_ar = float(w) / float(h);
+
+ if (screen_ar > game_ar) {
+ rect.setWidth(round(_egl_surface_height * game_ar));
+ rect.moveTo((_egl_surface_width - rect.width()) / 2, 0);
+ } else {
+ rect.setHeight(round(_egl_surface_width / game_ar));
+ rect.moveTo((_egl_surface_height - rect.height()) / 2, 0);
+ }
+ }
+
+ glScissor(rect.left, rect.top, rect.width(), rect.height());
+
+ _game_texture->setDrawRect(rect);
+}
+
+int OSystem_Android::getScreenChangeID() const {
+ return _screen_changeid;
+}
+
+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);
+
+#ifdef USE_RGB_COLOR
+ assert(_game_texture->hasPalette());
+#endif
+
+ GLTHREADCHECK;
+
+ if (!_use_mouse_palette)
+ setCursorPaletteInternal(colors, start, num);
+
+ const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
+ byte *p = _game_texture->palette() + start * 2;
+
+ for (uint i = 0; i < num; ++i, colors += 3, p += 2)
+ WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
+}
+
+void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
+ ENTER("%p, %u, %u", colors, start, num);
+
+#ifdef USE_RGB_COLOR
+ assert(_game_texture->hasPalette());
+#endif
+
+ GLTHREADCHECK;
+
+ const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat();
+ const byte *p = _game_texture->palette_const() + start * 2;
+
+ for (uint i = 0; i < num; ++i, colors += 3, p += 2)
+ pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]);
+}
+
+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 (!JNI::haveSurface())
+ return;
+
+ if (!_force_redraw &&
+ !_game_texture->dirty() &&
+ !_overlay_texture->dirty() &&
+ !_mouse_texture->dirty())
+ return;
+
+ _force_redraw = false;
+
+ // clear pointer leftovers in dead areas
+ // also, HTC's GLES drivers are made of fail and don't preserve the buffer
+ // ( http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html )
+ if ((_show_overlay || _htc_fail) && !_fullscreen)
+ clearScreen(kClear);
+
+ 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.
+ clearScreen(kClear);
+
+ // Move everything up by _shake_offset (game) pixels
+ GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
+ }
+
+// TODO this doesnt work on those sucky drivers, do it differently
+// if (_show_overlay)
+// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f));
+
+ if (_focus_rect.isEmpty()) {
+ _game_texture->drawTextureRect();
+ } 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->drawTextureRect();
+
+ GLCALL(glPopMatrix());
+ }
+
+ int cs = _mouse_targetscale;
+
+ if (_show_overlay) {
+// TODO see above
+// GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
+
+ // ugly, but the modern theme sets a wacko factor, only god knows why
+ cs = 1;
+
+ GLCALL(_overlay_texture->drawTextureRect());
+ }
+
+ if (_show_mouse && !_mouse_texture->isEmpty()) {
+ GLCALL(glPushMatrix());
+
+ const Common::Point &mouse = getEventManager()->getMousePos();
+
+ // Scale up ScummVM -> OpenGL (pixel) coordinates
+ if (_show_overlay) {
+ GLCALL(glScalex(xdiv(_egl_surface_width,
+ _overlay_texture->width()),
+ xdiv(_egl_surface_height,
+ _overlay_texture->height()),
+ 1 << 16));
+ } else {
+ const Common::Rect &r = _game_texture->getDrawRect();
+
+ GLCALL(glTranslatex(r.left << 16,
+ r.top << 16,
+ 0));
+ GLCALL(glScalex(xdiv(r.width(), _game_texture->width()),
+ xdiv(r.height(), _game_texture->height()),
+ 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:
+ GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
+ (mouse.y << 16) | 1 << 15, 0));
+
+ GLCALL(glScalex(cs << 16, cs << 16, 1 << 16));
+
+ _mouse_texture->drawTextureOrigin();
+
+ GLCALL(glPopMatrix());
+ }
+
+ GLCALL(glPopMatrix());
+
+ if (!JNI::swapBuffers())
+ LOGW("swapBuffers failed: 0x%x", glGetError());
+}
+
+Graphics::Surface *OSystem_Android::lockScreen() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ Graphics::Surface *surface = _game_texture->surface();
+ assert(surface->pixels);
+
+ return surface;
+}
+
+void OSystem_Android::unlockScreen() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ 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);
+
+ GLTHREADCHECK;
+
+ _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;
+
+ updateEventScale();
+
+ warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2);
+
+ GLCALL(glDisable(GL_SCISSOR_TEST));
+}
+
+void OSystem_Android::hideOverlay() {
+ ENTER();
+
+ _show_overlay = false;
+
+ updateEventScale();
+
+ warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
+
+ // double buffered, flip twice
+ clearScreen(kClearUpdate, 2);
+
+ GLCALL(glEnable(GL_SCISSOR_TEST));
+}
+
+void OSystem_Android::clearOverlay() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ _overlay_texture->fillBuffer(0);
+}
+
+void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
+ ENTER("%p, %d", buf, pitch);
+
+ GLTHREADCHECK;
+
+ const Graphics::Surface *surface = _overlay_texture->surface_const();
+ assert(surface->bytesPerPixel == sizeof(buf[0]));
+
+ const byte *src = (const byte *)surface->pixels;
+ uint h = surface->h;
+
+ do {
+ memcpy(buf, src, surface->w * surface->bytesPerPixel);
+ src += surface->pitch;
+ // 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);
+
+ GLTHREADCHECK;
+
+ // This 'pitch' is pixels not bytes
+ _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
+}
+
+int16 OSystem_Android::getOverlayHeight() {
+ return _overlay_texture->height();
+}
+
+int16 OSystem_Android::getOverlayWidth() {
+ return _overlay_texture->width();
+}
+
+Graphics::PixelFormat OSystem_Android::getOverlayFormat() const {
+ return _overlay_texture->getPixelFormat();
+}
+
+bool OSystem_Android::showMouse(bool visible) {
+ ENTER("%d", visible);
+
+ _show_mouse = visible;
+
+ return true;
+}
+
+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);
+
+ GLTHREADCHECK;
+
+#ifdef USE_RGB_COLOR
+ if (format && format->bytesPerPixel > 1) {
+ if (_mouse_texture != _mouse_texture_rgb) {
+ LOGD("switching to rgb mouse cursor");
+
+ assert(!_mouse_texture_rgb);
+ _mouse_texture_rgb = new GLES5551Texture();
+ _mouse_texture_rgb->setLinearFilter(_graphicsMode == 1);
+ }
+
+ _mouse_texture = _mouse_texture_rgb;
+ } else {
+ if (_mouse_texture != _mouse_texture_palette)
+ LOGD("switching to paletted mouse cursor");
+
+ _mouse_texture = _mouse_texture_palette;
+
+ delete _mouse_texture_rgb;
+ _mouse_texture_rgb = 0;
+ }
+#endif
+
+ _mouse_texture->allocBuffer(w, h);
+
+ if (_mouse_texture == _mouse_texture_palette) {
+ assert(keycolor < 256);
+
+ byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) | 1);
+
+ _mouse_keycolor = keycolor;
+
+ p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) & ~1);
+ }
+
+ if (w == 0 || h == 0)
+ return;
+
+ if (_mouse_texture == _mouse_texture_palette) {
+ _mouse_texture->updateBuffer(0, 0, w, h, buf, w);
+ } else {
+ uint16 pitch = _mouse_texture->pitch();
+
+ byte *tmp = new byte[pitch * h];
+
+ // meh, a 16bit cursor without alpha bits... this is so silly
+ if (!crossBlit(tmp, buf, pitch, w * 2, w, h,
+ _mouse_texture->getPixelFormat(),
+ *format)) {
+ LOGE("crossblit failed");
+
+ delete[] tmp;
+
+ _mouse_texture->allocBuffer(0, 0);
+
+ return;
+ }
+
+ uint16 *s = (uint16 *)buf;
+ uint16 *d = (uint16 *)tmp;
+ for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w)
+ for (uint16 x = 0; x < w; ++x, d++)
+ if (*s++ != (keycolor & 0xffff))
+ *d |= 1;
+
+ _mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch);
+
+ delete[] tmp;
+ }
+
+ _mouse_hotspot = Common::Point(hotspotX, hotspotY);
+ _mouse_targetscale = cursorTargetScale;
+}
+
+void OSystem_Android::setCursorPaletteInternal(const byte *colors,
+ uint start, uint num) {
+ const Graphics::PixelFormat &pf =
+ _mouse_texture_palette->getPalettePixelFormat();
+ byte *p = _mouse_texture_palette->palette() + start * 2;
+
+ for (uint i = 0; i < num; ++i, colors += 3, p += 2)
+ WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2]));
+
+ p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) & ~1);
+}
+
+void OSystem_Android::setCursorPalette(const byte *colors,
+ uint start, uint num) {
+ ENTER("%p, %u, %u", colors, start, num);
+
+ GLTHREADCHECK;
+
+ if (!_mouse_texture->hasPalette()) {
+ LOGD("switching to paletted mouse cursor");
+
+ _mouse_texture = _mouse_texture_palette;
+
+ delete _mouse_texture_rgb;
+ _mouse_texture_rgb = 0;
+ }
+
+ setCursorPaletteInternal(colors, start, num);
+ _use_mouse_palette = true;
+}
+
+void OSystem_Android::disableCursorPalette(bool disable) {
+ ENTER("%d", disable);
+
+ // when disabling the cursor palette, and we're running a clut8 game,
+ // it expects the game palette to be used for the cursor
+ if (disable && _game_texture->hasPalette()) {
+ const byte *src = _game_texture->palette_const();
+ byte *dst = _mouse_texture_palette->palette();
+
+ const Graphics::PixelFormat &pf_src =
+ _game_texture->getPalettePixelFormat();
+ const Graphics::PixelFormat &pf_dst =
+ _mouse_texture_palette->getPalettePixelFormat();
+
+ uint8 r, g, b;
+
+ for (uint i = 0; i < 256; ++i, src += 2, dst += 2) {
+ pf_src.colorToRGB(READ_UINT16(src), r, g, b);
+ WRITE_UINT16(dst, pf_dst.RGBToColor(r, g, b));
+ }
+
+ byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2;
+ WRITE_UINT16(p, READ_UINT16(p) & ~1);
+ }
+
+ _use_mouse_palette = !disable;
+}
+
+#endif
+
diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp
new file mode 100644
index 0000000000..08a1491998
--- /dev/null
+++ b/backends/platform/android/jni.cpp
@@ -0,0 +1,605 @@
+/* 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 "base/version.h"
+#include "common/config-manager.h"
+#include "engines/engine.h"
+
+#include "backends/platform/android/android.h"
+#include "backends/platform/android/asset-archive.h"
+#include "backends/platform/android/jni.h"
+
+__attribute__ ((visibility("default")))
+jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
+ return JNI::onLoad(vm);
+}
+
+JavaVM *JNI::_vm = 0;
+jobject JNI::_jobj = 0;
+jobject JNI::_jobj_audio_track = 0;
+jobject JNI::_jobj_egl = 0;
+jobject JNI::_jobj_egl_display = 0;
+jobject JNI::_jobj_egl_surface = 0;
+
+Common::Archive *JNI::_asset_archive = 0;
+OSystem_Android *JNI::_system = 0;
+
+bool JNI::pause = false;
+sem_t JNI::pause_sem = { 0 };
+
+int JNI::surface_changeid = 0;
+int JNI::egl_surface_width = 0;
+int JNI::egl_surface_height = 0;
+bool JNI::_ready_for_events = 0;
+
+jmethodID JNI::_MID_getDPI = 0;
+jmethodID JNI::_MID_displayMessageOnOSD = 0;
+jmethodID JNI::_MID_setWindowCaption = 0;
+jmethodID JNI::_MID_showVirtualKeyboard = 0;
+jmethodID JNI::_MID_getSysArchives = 0;
+jmethodID JNI::_MID_getPluginDirectories = 0;
+jmethodID JNI::_MID_initSurface = 0;
+jmethodID JNI::_MID_deinitSurface = 0;
+
+jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0;
+
+jmethodID JNI::_MID_AudioTrack_flush = 0;
+jmethodID JNI::_MID_AudioTrack_pause = 0;
+jmethodID JNI::_MID_AudioTrack_play = 0;
+jmethodID JNI::_MID_AudioTrack_stop = 0;
+jmethodID JNI::_MID_AudioTrack_write = 0;
+
+const JNINativeMethod JNI::_natives[] = {
+ { "create", "(Landroid/content/res/AssetManager;"
+ "Ljavax/microedition/khronos/egl/EGL10;"
+ "Ljavax/microedition/khronos/egl/EGLDisplay;"
+ "Landroid/media/AudioTrack;II)V",
+ (void *)JNI::create },
+ { "destroy", "()V",
+ (void *)JNI::destroy },
+ { "setSurface", "(II)V",
+ (void *)JNI::setSurface },
+ { "main", "([Ljava/lang/String;)I",
+ (void *)JNI::main },
+ { "pushEvent", "(IIIIII)V",
+ (void *)JNI::pushEvent },
+ { "enableZoning", "(Z)V",
+ (void *)JNI::enableZoning },
+ { "setPause", "(Z)V",
+ (void *)JNI::setPause }
+};
+
+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;
+
+ return JNI_VERSION_1_2;
+}
+
+JNIEnv *JNI::getEnv() {
+ JNIEnv *env = 0;
+
+ jint res = _vm->GetEnv((void **)&env, JNI_VERSION_1_2);
+
+ if (res != JNI_OK) {
+ LOGE("GetEnv() failed: %d", res);
+ abort();
+ }
+
+ return env;
+}
+
+void JNI::attachThread() {
+ JNIEnv *env = 0;
+
+ jint res = _vm->AttachCurrentThread(&env, 0);
+
+ if (res != JNI_OK) {
+ LOGE("AttachCurrentThread() failed: %d", res);
+ abort();
+ }
+}
+
+void JNI::detachThread() {
+ jint res = _vm->DetachCurrentThread();
+
+ if (res != JNI_OK) {
+ LOGE("DetachCurrentThread() failed: %d", res);
+ abort();
+ }
+}
+
+void JNI::setReadyForEvents(bool ready) {
+ _ready_for_events = ready;
+}
+
+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
+ if (cls != 0)
+ env->ThrowNew(cls, msg);
+
+ env->DeleteLocalRef(cls);
+}
+
+void JNI::throwRuntimeException(JNIEnv *env, const char *msg) {
+ throwByName(env, "java/lang/RuntimeException", msg);
+}
+
+// calls to the dark side
+
+void JNI::getDPI(float *values) {
+ values[0] = 0.0;
+ values[1] = 0.0;
+
+ JNIEnv *env = JNI::getEnv();
+
+ jfloatArray array = env->NewFloatArray(2);
+
+ env->CallVoidMethod(_jobj, _MID_getDPI, array);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Failed to get DPIs");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ } else {
+ jfloat *res = env->GetFloatArrayElements(array, 0);
+
+ if (res) {
+ values[0] = res[0];
+ values[1] = res[1];
+
+ env->ReleaseFloatArrayElements(array, res, 0);
+ }
+ }
+
+ env->DeleteLocalRef(array);
+}
+
+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()) {
+ LOGE("Failed to display OSD message");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->DeleteLocalRef(java_msg);
+}
+
+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()) {
+ LOGE("Failed to set window caption");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->DeleteLocalRef(java_caption);
+}
+
+void JNI::showVirtualKeyboard(bool enable) {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable);
+
+ if (env->ExceptionCheck()) {
+ LOGE("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()) {
+ LOGE("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);
+ }
+}
+
+void JNI::getPluginDirectories(Common::FSList &dirs) {
+ JNIEnv *env = JNI::getEnv();
+
+ jobjectArray array =
+ (jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories);
+
+ if (env->ExceptionCheck()) {
+ LOGE("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) {
+ LOGE("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);
+ }
+}
+
+bool JNI::initSurface() {
+ JNIEnv *env = JNI::getEnv();
+
+ jobject obj = env->CallObjectMethod(_jobj, _MID_initSurface);
+
+ if (!obj || env->ExceptionCheck()) {
+ LOGE("initSurface failed");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+
+ return false;
+ }
+
+ _jobj_egl_surface = env->NewGlobalRef(obj);
+
+ return true;
+}
+
+void JNI::deinitSurface() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj, _MID_deinitSurface);
+
+ if (env->ExceptionCheck()) {
+ LOGE("deinitSurface failed");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->DeleteGlobalRef(_jobj_egl_surface);
+ _jobj_egl_surface = 0;
+}
+
+void JNI::setAudioPause() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_flush);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error flushing AudioTrack");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error setting AudioTrack: pause");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+void JNI::setAudioPlay() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_play);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error setting AudioTrack: play");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+void JNI::setAudioStop() {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_stop);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error setting AudioTrack: stop");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
+// natives for the dark side
+
+void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
+ jobject egl, jobject egl_display,
+ jobject at, jint audio_sample_rate, jint audio_buffer_size) {
+ LOGI(gScummVMFullVersion);
+
+ assert(!_system);
+
+ pause = false;
+ // initial value of zero!
+ sem_init(&pause_sem, 0, 0);
+
+ _asset_archive = new AndroidAssetArchive(asset_manager);
+ assert(_asset_archive);
+
+ _system = new OSystem_Android(audio_sample_rate, audio_buffer_size);
+ 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);
+
+ jclass cls = env->GetObjectClass(_jobj);
+
+#define FIND_METHOD(prefix, name, signature) do { \
+ _MID_ ## prefix ## name = env->GetMethodID(cls, #name, signature); \
+ if (_MID_ ## prefix ## name == 0) \
+ return; \
+ } while (0)
+
+ FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V");
+ FIND_METHOD(, getDPI, "([F)V");
+ FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V");
+ FIND_METHOD(, showVirtualKeyboard, "(Z)V");
+ FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
+ FIND_METHOD(, getPluginDirectories, "()[Ljava/lang/String;");
+ FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
+ FIND_METHOD(, deinitSurface, "()V");
+
+ _jobj_egl = env->NewGlobalRef(egl);
+ _jobj_egl_display = env->NewGlobalRef(egl_display);
+
+ cls = env->GetObjectClass(_jobj_egl);
+
+ FIND_METHOD(EGL10_, eglSwapBuffers,
+ "(Ljavax/microedition/khronos/egl/EGLDisplay;"
+ "Ljavax/microedition/khronos/egl/EGLSurface;)Z");
+
+ _jobj_audio_track = env->NewGlobalRef(at);
+
+ cls = env->GetObjectClass(_jobj_audio_track);
+
+ FIND_METHOD(AudioTrack_, flush, "()V");
+ FIND_METHOD(AudioTrack_, pause, "()V");
+ FIND_METHOD(AudioTrack_, play, "()V");
+ FIND_METHOD(AudioTrack_, stop, "()V");
+ FIND_METHOD(AudioTrack_, write, "([BII)I");
+
+#undef FIND_METHOD
+
+ g_system = _system;
+}
+
+void JNI::destroy(JNIEnv *env, jobject self) {
+ delete _asset_archive;
+ _asset_archive = 0;
+
+ delete _system;
+ g_system = 0;
+ _system = 0;
+
+ sem_destroy(&pause_sem);
+
+ // see above
+ //JNI::getEnv()->DeleteWeakGlobalRef(_jobj);
+
+ JNI::getEnv()->DeleteGlobalRef(_jobj_egl_display);
+ JNI::getEnv()->DeleteGlobalRef(_jobj_egl);
+ JNI::getEnv()->DeleteGlobalRef(_jobj_audio_track);
+ JNI::getEnv()->DeleteGlobalRef(_jobj);
+}
+
+void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height) {
+ egl_surface_width = width;
+ egl_surface_height = height;
+ surface_changeid++;
+}
+
+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) {
+ 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("scummvm_main exited with code %d", res);
+
+ _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;
+}
+
+void JNI::pushEvent(JNIEnv *env, jobject self, int type, int arg1, int arg2,
+ int arg3, int arg4, int arg5) {
+ // drop events until we're ready and after we quit
+ if (!_ready_for_events) {
+ LOGW("dropping event");
+ return;
+ }
+
+ assert(_system);
+
+ _system->pushEvent(type, arg1, arg2, arg3, arg4, arg5);
+}
+
+void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) {
+ assert(_system);
+
+ _system->enableZoning(enable);
+}
+
+void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
+ if (!_system)
+ return;
+
+ if (g_engine) {
+ LOGD("pauseEngine: %d", value);
+
+ g_engine->pauseEngine(value);
+
+ if (value &&
+ g_engine->hasFeature(Engine::kSupportsSavingDuringRuntime) &&
+ g_engine->canSaveGameStateCurrently())
+ g_engine->saveGameState(0, "Android parachute");
+ }
+
+ pause = value;
+
+ if (!pause) {
+ // wake up all threads
+ for (uint i = 0; i < 3; ++i)
+ sem_post(&pause_sem);
+ }
+}
+
+#endif
+
diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h
new file mode 100644
index 0000000000..d029f1a2a8
--- /dev/null
+++ b/backends/platform/android/jni.h
@@ -0,0 +1,151 @@
+/* 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>
+#include <semaphore.h>
+
+#include "common/fs.h"
+#include "common/archive.h"
+
+class OSystem_Android;
+
+class JNI {
+private:
+ JNI();
+ virtual ~JNI();
+
+public:
+ static bool pause;
+ static sem_t pause_sem;
+
+ static int surface_changeid;
+ static int egl_surface_width;
+ static int egl_surface_height;
+
+ static jint onLoad(JavaVM *vm);
+
+ static JNIEnv *getEnv();
+
+ static void attachThread();
+ static void detachThread();
+
+ static void setReadyForEvents(bool ready);
+
+ static void getPluginDirectories(Common::FSList &dirs);
+ static void setWindowCaption(const char *caption);
+ static void getDPI(float *values);
+ static void displayMessageOnOSD(const char *msg);
+ static void showVirtualKeyboard(bool enable);
+ static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
+
+ static inline bool haveSurface();
+ static inline bool swapBuffers();
+ static bool initSurface();
+ static void deinitSurface();
+
+ static void setAudioPause();
+ static void setAudioPlay();
+ static void setAudioStop();
+
+ static inline int writeAudio(JNIEnv *env, jbyteArray &data, int offset,
+ int size);
+
+private:
+ static JavaVM *_vm;
+ // back pointer to (java) peer instance
+ static jobject _jobj;
+ static jobject _jobj_audio_track;
+ static jobject _jobj_egl;
+ static jobject _jobj_egl_display;
+ static jobject _jobj_egl_surface;
+
+ static Common::Archive *_asset_archive;
+ static OSystem_Android *_system;
+
+ static bool _ready_for_events;
+
+ static jmethodID _MID_getDPI;
+ static jmethodID _MID_displayMessageOnOSD;
+ static jmethodID _MID_setWindowCaption;
+ static jmethodID _MID_showVirtualKeyboard;
+ static jmethodID _MID_getSysArchives;
+ static jmethodID _MID_getPluginDirectories;
+ static jmethodID _MID_initSurface;
+ static jmethodID _MID_deinitSurface;
+
+ static jmethodID _MID_EGL10_eglSwapBuffers;
+
+ static jmethodID _MID_AudioTrack_flush;
+ static jmethodID _MID_AudioTrack_pause;
+ static jmethodID _MID_AudioTrack_play;
+ static jmethodID _MID_AudioTrack_stop;
+ static jmethodID _MID_AudioTrack_write;
+
+ static const JNINativeMethod _natives[];
+
+ static void throwByName(JNIEnv *env, const char *name, const char *msg);
+ static void throwRuntimeException(JNIEnv *env, const char *msg);
+
+ // natives for the dark side
+ static void create(JNIEnv *env, jobject self, jobject asset_manager,
+ jobject egl, jobject egl_display,
+ jobject at, jint audio_sample_rate,
+ jint audio_buffer_size);
+ static void destroy(JNIEnv *env, jobject self);
+
+ static void setSurface(JNIEnv *env, jobject self, jint width, jint height);
+ static jint main(JNIEnv *env, jobject self, jobjectArray args);
+
+ static void pushEvent(JNIEnv *env, jobject self, int type, int arg1,
+ int arg2, int arg3, int arg4, int arg5);
+ static void enableZoning(JNIEnv *env, jobject self, jboolean enable);
+
+ static void setPause(JNIEnv *env, jobject self, jboolean value);
+};
+
+inline bool JNI::haveSurface() {
+ return _jobj_egl_surface != 0;
+}
+
+inline bool JNI::swapBuffers() {
+ JNIEnv *env = JNI::getEnv();
+
+ return env->CallBooleanMethod(_jobj_egl, _MID_EGL10_eglSwapBuffers,
+ _jobj_egl_display, _jobj_egl_surface);
+}
+
+inline int JNI::writeAudio(JNIEnv *env, jbyteArray &data, int offset, int size) {
+ return env->CallIntMethod(_jobj_audio_track, _MID_AudioTrack_write, data,
+ offset, size);
+}
+
+#endif
+#endif
+
diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk
index b457b388b1..2fe4b40585 100644
--- a/backends/platform/android/module.mk
+++ b/backends/platform/android/module.mk
@@ -1,84 +1,15 @@
MODULE := backends/platform/android
MODULE_OBJS := \
- android.o asset-archive.o video.o
+ jni.o \
+ texture.o \
+ asset-archive.o \
+ android.o \
+ gfx.o \
+ events.o
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
OBJS := $(MODULE_OBJS) $(OBJS)
MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
-JAVA_SRC = \
- $(MODULE)/org/inodes/gus/scummvm/ScummVM.java \
- $(MODULE)/org/inodes/gus/scummvm/ScummVMApplication.java \
- $(MODULE)/org/inodes/gus/scummvm/ScummVMActivity.java \
- $(MODULE)/org/inodes/gus/scummvm/EditableSurfaceView.java \
- $(MODULE)/org/inodes/gus/scummvm/Unpacker.java \
- $(MODULE)/org/inodes/gus/scummvm/Manifest.java \
- $(MODULE)/org/inodes/gus/scummvm/R.java
-
-JAVA_PLUGIN_SRC = \
- $(MODULE)/org/inodes/gus/scummvm/PluginProvider.java
-
-RESOURCES = \
- $(srcdir)/dists/android/res/values/strings.xml \
- $(srcdir)/dists/android/res/layout/main.xml \
- $(srcdir)/dists/android/res/layout/splash.xml \
- $(srcdir)/dists/android/res/drawable/gradient.xml \
- $(srcdir)/dists/android/res/drawable/scummvm.png \
- $(srcdir)/dists/android/res/drawable/scummvm_big.png
-
-ASSETS = $(DIST_FILES_ENGINEDATA) $(DIST_FILES_THEMES)
-
-PLUGIN_RESOURCES = \
- $(srcdir)/dists/android/res/values/strings.xml \
- $(srcdir)/dists/android/res/drawable/scummvm.png
-
-# These must be incremented for each market upload
-#ANDROID_VERSIONCODE = 6 Specified in dists/android/AndroidManifest.xml.in
-ANDROID_PLUGIN_VERSIONCODE = 6
-
-# This is a bit silly. I want to compile against the 1.6 android.jar,
-# to make the compiler check that I don't use something that requires
-# a newer Android. However, in order to use android:installLocation,
-# we need to give aapt a version >=8 android.jar - even though the
-# result will work ok on 1.5+.
-ANDROID_JAR = $(ANDROID_SDK)/platforms/android-1.5/android.jar
-ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
-
-# This library contains scummvm proper
-build.tmp/libscummvm.so: $(OBJS)
- @$(MKDIR) -p $(@D)
- $(QUIET_LINK)$(CXX) -shared $(LDFLAGS) -Wl,-Bsymbolic -Wl,-soname,$(@F) -Wl,--no-undefined -o $@ $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LIBS)
-
-
-backends/platform/android/org/inodes/gus/scummvm/R.java backends/platform/android/org/inodes/gus/scummvm/Manifest.java: $(srcdir)/dists/android/AndroidManifest.xml $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
- $(AAPT) package -m -J backends/platform/android -M $< -S $(srcdir)/dists/android/res -I $(ANDROID_JAR8)
-
-build.tmp/classes/%.class: $(srcdir)/backends/platform/android/%.java $(srcdir)/backends/platform/android/org/inodes/gus/scummvm/R.java
- @$(MKDIR) -p $(@D)
- $(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes -bootclasspath $(ANDROID_JAR) $<
-
-build.tmp/classes.plugin/%.class: $(srcdir)/backends/platform/android/%.java
- @$(MKDIR) -p $(@D)
- $(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes.plugin -bootclasspath $(ANDROID_JAR) $<
-
-classes.dex: $(JAVA_SRC:backends/platform/android/%.java=build.tmp/classes/%.class)
- $(DX) --dex --output=$@ build.tmp/classes
-
-build.tmp/plugins/classes.dex: $(JAVA_PLUGIN_SRC:backends/platform/android/%.java=build.tmp/classes.plugin/%.class)
- @$(MKDIR) -p $(@D)
- $(DX) --dex --output=$@ build.tmp/classes.plugin
-
-build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml: dists/android/mkmanifest.pl configure dists/android/AndroidManifest.xml
- dists/android/mkmanifest.pl --id=$* --configure=configure \
- --version-name=$(VERSION) \
- --version-code=$(ANDROID_PLUGIN_VERSIONCODE) \
- --stringres=build.stage/$*/res/values/strings.xml \
- --manifest=build.tmp/$*/AndroidManifest.xml \
- --master-manifest=dists/android/AndroidManifest.xml \
- --unpacklib=mylib/armeabi/lib$*.so
-
-build.stage/%/res/drawable/scummvm.png: dists/android/res/drawable/scummvm.png
- @$(MKDIR) -p $(@D)
- $(CP) $< $@
diff --git a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
index 5b71d4a3a5..cede7eedd4 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java
@@ -19,13 +19,13 @@ public class EditableSurfaceView extends SurfaceView {
}
public EditableSurfaceView(Context context, AttributeSet attrs,
- int defStyle) {
+ int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onCheckIsTextEditor() {
- return true;
+ return false;
}
private class MyInputConnection extends BaseInputConnection {
@@ -40,7 +40,9 @@ public class EditableSurfaceView extends SurfaceView {
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
- return super.performEditorAction(actionCode); // Sends enter key
+
+ // Sends enter key
+ return super.performEditorAction(actionCode);
}
}
@@ -49,11 +51,12 @@ public class EditableSurfaceView extends SurfaceView {
outAttrs.initialCapsMode = 0;
outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
outAttrs.inputType = (InputType.TYPE_CLASS_TEXT |
- InputType.TYPE_TEXT_VARIATION_NORMAL |
- InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+ InputType.TYPE_TEXT_VARIATION_NORMAL |
+ InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
outAttrs.imeOptions = (EditorInfo.IME_ACTION_DONE |
- EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+ EditorInfo.IME_FLAG_NO_EXTRACT_UI);
return new MyInputConnection();
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Event.java b/backends/platform/android/org/inodes/gus/scummvm/Event.java
deleted file mode 100644
index f9c7aba93b..0000000000
--- a/backends/platform/android/org/inodes/gus/scummvm/Event.java
+++ /dev/null
@@ -1,330 +0,0 @@
-package org.inodes.gus.scummvm;
-
-import android.view.KeyEvent;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-public class Event {
- // Common::EventType enum.
- // Must be kept in sync with common/events.h
- public final static int EVENT_INVALID = 0;
- public final static int EVENT_KEYDOWN = 1;
- public final static int EVENT_KEYUP = 2;
- public final static int EVENT_MOUSEMOVE = 3;
- public final static int EVENT_LBUTTONDOWN = 4;
- public final static int EVENT_LBUTTONUP = 5;
- public final static int EVENT_RBUTTONDOWN = 6;
- public final static int EVENT_RBUTTONUP = 7;
- public final static int EVENT_WHEELUP = 8;
- public final static int EVENT_WHEELDOWN = 9;
- public final static int EVENT_QUIT = 10;
- public final static int EVENT_SCREEN_CHANGED = 11;
- public final static int EVENT_PREDICTIVE_DIALOG = 12;
- public final static int EVENT_MBUTTONDOWN = 13;
- public final static int EVENT_MBUTTONUP = 14;
- public final static int EVENT_MAINMENU = 15;
- public final static int EVENT_RTL = 16;
-
- // common/keyboard.h
- public final static int ASCII_F1 = 315;
- public final static int ASCII_F2 = 316;
- public final static int ASCII_F3 = 317;
- public final static int ASCII_F4 = 318;
- public final static int ASCII_F5 = 319;
- public final static int ASCII_F6 = 320;
- public final static int ASCII_F7 = 321;
- public final static int ASCII_F8 = 322;
- public final static int ASCII_F9 = 323;
- public final static int ASCII_F10 = 324;
- public final static int ASCII_F11 = 325;
- public final static int ASCII_F12 = 326;
- public final static int KBD_CTRL = 1 << 0;
- public final static int KBD_ALT = 1 << 1;
- public final static int KBD_SHIFT = 1 << 2;
-
- public final static int KEYCODE_INVALID = 0;
- public final static int KEYCODE_BACKSPACE = 8;
- public final static int KEYCODE_TAB = 9;
- public final static int KEYCODE_CLEAR = 12;
- public final static int KEYCODE_RETURN = 13;
- public final static int KEYCODE_PAUSE = 19;
- public final static int KEYCODE_ESCAPE = 27;
- public final static int KEYCODE_SPACE = 32;
- public final static int KEYCODE_EXCLAIM = 33;
- public final static int KEYCODE_QUOTEDBL = 34;
- public final static int KEYCODE_HASH = 35;
- public final static int KEYCODE_DOLLAR = 36;
- public final static int KEYCODE_AMPERSAND = 38;
- public final static int KEYCODE_QUOTE = 39;
- public final static int KEYCODE_LEFTPAREN = 40;
- public final static int KEYCODE_RIGHTPAREN = 41;
- public final static int KEYCODE_ASTERISK = 42;
- public final static int KEYCODE_PLUS = 43;
- public final static int KEYCODE_COMMA = 44;
- public final static int KEYCODE_MINUS = 45;
- public final static int KEYCODE_PERIOD = 46;
- public final static int KEYCODE_SLASH = 47;
- public final static int KEYCODE_0 = 48;
- public final static int KEYCODE_1 = 49;
- public final static int KEYCODE_2 = 50;
- public final static int KEYCODE_3 = 51;
- public final static int KEYCODE_4 = 52;
- public final static int KEYCODE_5 = 53;
- public final static int KEYCODE_6 = 54;
- public final static int KEYCODE_7 = 55;
- public final static int KEYCODE_8 = 56;
- public final static int KEYCODE_9 = 57;
- public final static int KEYCODE_COLON = 58;
- public final static int KEYCODE_SEMICOLON = 59;
- public final static int KEYCODE_LESS = 60;
- public final static int KEYCODE_EQUALS = 61;
- public final static int KEYCODE_GREATER = 62;
- public final static int KEYCODE_QUESTION = 63;
- public final static int KEYCODE_AT = 64;
- public final static int KEYCODE_LEFTBRACKET = 91;
- public final static int KEYCODE_BACKSLASH = 92;
- public final static int KEYCODE_RIGHTBRACKET = 93;
- public final static int KEYCODE_CARET = 94;
- public final static int KEYCODE_UNDERSCORE = 95;
- public final static int KEYCODE_BACKQUOTE = 96;
- public final static int KEYCODE_a = 97;
- public final static int KEYCODE_b = 98;
- public final static int KEYCODE_c = 99;
- public final static int KEYCODE_d = 100;
- public final static int KEYCODE_e = 101;
- public final static int KEYCODE_f = 102;
- public final static int KEYCODE_g = 103;
- public final static int KEYCODE_h = 104;
- public final static int KEYCODE_i = 105;
- public final static int KEYCODE_j = 106;
- public final static int KEYCODE_k = 107;
- public final static int KEYCODE_l = 108;
- public final static int KEYCODE_m = 109;
- public final static int KEYCODE_n = 110;
- public final static int KEYCODE_o = 111;
- public final static int KEYCODE_p = 112;
- public final static int KEYCODE_q = 113;
- public final static int KEYCODE_r = 114;
- public final static int KEYCODE_s = 115;
- public final static int KEYCODE_t = 116;
- public final static int KEYCODE_u = 117;
- public final static int KEYCODE_v = 118;
- public final static int KEYCODE_w = 119;
- public final static int KEYCODE_x = 120;
- public final static int KEYCODE_y = 121;
- public final static int KEYCODE_z = 122;
- public final static int KEYCODE_DELETE = 127;
- // Numeric keypad
- public final static int KEYCODE_KP0 = 256;
- public final static int KEYCODE_KP1 = 257;
- public final static int KEYCODE_KP2 = 258;
- public final static int KEYCODE_KP3 = 259;
- public final static int KEYCODE_KP4 = 260;
- public final static int KEYCODE_KP5 = 261;
- public final static int KEYCODE_KP6 = 262;
- public final static int KEYCODE_KP7 = 263;
- public final static int KEYCODE_KP8 = 264;
- public final static int KEYCODE_KP9 = 265;
- public final static int KEYCODE_KP_PERIOD = 266;
- public final static int KEYCODE_KP_DIVIDE = 267;
- public final static int KEYCODE_KP_MULTIPLY = 268;
- public final static int KEYCODE_KP_MINUS = 269;
- public final static int KEYCODE_KP_PLUS = 270;
- public final static int KEYCODE_KP_ENTER = 271;
- public final static int KEYCODE_KP_EQUALS = 272;
- // Arrows + Home/End pad
- public final static int KEYCODE_UP = 273;
- public final static int KEYCODE_DOWN = 274;
- public final static int KEYCODE_RIGHT = 275;
- public final static int KEYCODE_LEFT = 276;
- public final static int KEYCODE_INSERT = 277;
- public final static int KEYCODE_HOME = 278;
- public final static int KEYCODE_END = 279;
- public final static int KEYCODE_PAGEUP = 280;
- public final static int KEYCODE_PAGEDOWN = 281;
- // Function keys
- public final static int KEYCODE_F1 = 282;
- public final static int KEYCODE_F2 = 283;
- public final static int KEYCODE_F3 = 284;
- public final static int KEYCODE_F4 = 285;
- public final static int KEYCODE_F5 = 286;
- public final static int KEYCODE_F6 = 287;
- public final static int KEYCODE_F7 = 288;
- public final static int KEYCODE_F8 = 289;
- public final static int KEYCODE_F9 = 290;
- public final static int KEYCODE_F10 = 291;
- public final static int KEYCODE_F11 = 292;
- public final static int KEYCODE_F12 = 293;
- public final static int KEYCODE_F13 = 294;
- public final static int KEYCODE_F14 = 295;
- public final static int KEYCODE_F15 = 296;
- // Key state modifier keys
- public final static int KEYCODE_NUMLOCK = 300;
- public final static int KEYCODE_CAPSLOCK = 301;
- public final static int KEYCODE_SCROLLOCK = 302;
- public final static int KEYCODE_RSHIFT = 303;
- public final static int KEYCODE_LSHIFT = 304;
- public final static int KEYCODE_RCTRL = 305;
- public final static int KEYCODE_LCTRL = 306;
- public final static int KEYCODE_RALT = 307;
- public final static int KEYCODE_LALT = 308;
- public final static int KEYCODE_RMETA = 309;
- public final static int KEYCODE_LMETA = 310;
- public final static int KEYCODE_LSUPER = 311; // Left "Windows" key
- public final static int KEYCODE_RSUPER = 312; // Right "Windows" key
- public final static int KEYCODE_MODE = 313; // "Alt Gr" key
- public final static int KEYCODE_COMPOSE = 314; // Multi-key compose key
- // Miscellaneous function keys
- public final static int KEYCODE_HELP = 315;
- public final static int KEYCODE_PRINT = 316;
- public final static int KEYCODE_SYSREQ = 317;
- public final static int KEYCODE_BREAK = 318;
- public final static int KEYCODE_MENU = 319;
- public final static int KEYCODE_POWER = 320; // Power Macintosh power key
- public final static int KEYCODE_EURO = 321; // Some european keyboards
- public final static int KEYCODE_UNDO = 322; // Atari keyboard has Undo
-
- // Android KeyEvent keycode -> ScummVM keycode
- public final static Map<Integer, Integer> androidKeyMap;
- static {
- Map<Integer, Integer> map = new HashMap<Integer, Integer>();
-
- map.put(KeyEvent.KEYCODE_DEL, KEYCODE_BACKSPACE);
- map.put(KeyEvent.KEYCODE_TAB, KEYCODE_TAB);
- map.put(KeyEvent.KEYCODE_CLEAR, KEYCODE_CLEAR);
- map.put(KeyEvent.KEYCODE_ENTER, KEYCODE_RETURN);
- //map.put(??, KEYCODE_PAUSE);
- map.put(KeyEvent.KEYCODE_BACK, KEYCODE_ESCAPE);
- map.put(KeyEvent.KEYCODE_SPACE, KEYCODE_SPACE);
- //map.put(??, KEYCODE_EXCLAIM);
- //map.put(??, KEYCODE_QUOTEDBL);
- map.put(KeyEvent.KEYCODE_POUND, KEYCODE_HASH);
- //map.put(??, KEYCODE_DOLLAR);
- //map.put(??, KEYCODE_AMPERSAND);
- map.put(KeyEvent.KEYCODE_APOSTROPHE, KEYCODE_QUOTE);
- //map.put(??, KEYCODE_LEFTPAREN);
- //map.put(??, KEYCODE_RIGHTPAREN);
- //map.put(??, KEYCODE_ASTERISK);
- map.put(KeyEvent.KEYCODE_PLUS, KEYCODE_PLUS);
- map.put(KeyEvent.KEYCODE_COMMA, KEYCODE_COMMA);
- map.put(KeyEvent.KEYCODE_MINUS, KEYCODE_MINUS);
- map.put(KeyEvent.KEYCODE_PERIOD, KEYCODE_PERIOD);
- map.put(KeyEvent.KEYCODE_SLASH, KEYCODE_SLASH);
- map.put(KeyEvent.KEYCODE_0, KEYCODE_0);
- map.put(KeyEvent.KEYCODE_1, KEYCODE_1);
- map.put(KeyEvent.KEYCODE_2, KEYCODE_2);
- map.put(KeyEvent.KEYCODE_3, KEYCODE_3);
- map.put(KeyEvent.KEYCODE_4, KEYCODE_4);
- map.put(KeyEvent.KEYCODE_5, KEYCODE_5);
- map.put(KeyEvent.KEYCODE_6, KEYCODE_6);
- map.put(KeyEvent.KEYCODE_7, KEYCODE_7);
- map.put(KeyEvent.KEYCODE_8, KEYCODE_8);
- map.put(KeyEvent.KEYCODE_9, KEYCODE_9);
- //map.put(??, KEYCODE_COLON);
- map.put(KeyEvent.KEYCODE_SEMICOLON, KEYCODE_SEMICOLON);
- //map.put(??, KEYCODE_LESS);
- map.put(KeyEvent.KEYCODE_EQUALS, KEYCODE_EQUALS);
- //map.put(??, KEYCODE_GREATER);
- //map.put(??, KEYCODE_QUESTION);
- map.put(KeyEvent.KEYCODE_AT, KEYCODE_AT);
- map.put(KeyEvent.KEYCODE_LEFT_BRACKET, KEYCODE_LEFTBRACKET);
- map.put(KeyEvent.KEYCODE_BACKSLASH, KEYCODE_BACKSLASH);
- map.put(KeyEvent.KEYCODE_RIGHT_BRACKET, KEYCODE_RIGHTBRACKET);
- //map.put(??, KEYCODE_CARET);
- //map.put(??, KEYCODE_UNDERSCORE);
- //map.put(??, KEYCODE_BACKQUOTE);
- map.put(KeyEvent.KEYCODE_A, KEYCODE_a);
- map.put(KeyEvent.KEYCODE_B, KEYCODE_b);
- map.put(KeyEvent.KEYCODE_C, KEYCODE_c);
- map.put(KeyEvent.KEYCODE_D, KEYCODE_d);
- map.put(KeyEvent.KEYCODE_E, KEYCODE_e);
- map.put(KeyEvent.KEYCODE_F, KEYCODE_f);
- map.put(KeyEvent.KEYCODE_G, KEYCODE_g);
- map.put(KeyEvent.KEYCODE_H, KEYCODE_h);
- map.put(KeyEvent.KEYCODE_I, KEYCODE_i);
- map.put(KeyEvent.KEYCODE_J, KEYCODE_j);
- map.put(KeyEvent.KEYCODE_K, KEYCODE_k);
- map.put(KeyEvent.KEYCODE_L, KEYCODE_l);
- map.put(KeyEvent.KEYCODE_M, KEYCODE_m);
- map.put(KeyEvent.KEYCODE_N, KEYCODE_n);
- map.put(KeyEvent.KEYCODE_O, KEYCODE_o);
- map.put(KeyEvent.KEYCODE_P, KEYCODE_p);
- map.put(KeyEvent.KEYCODE_Q, KEYCODE_q);
- map.put(KeyEvent.KEYCODE_R, KEYCODE_r);
- map.put(KeyEvent.KEYCODE_S, KEYCODE_s);
- map.put(KeyEvent.KEYCODE_T, KEYCODE_t);
- map.put(KeyEvent.KEYCODE_U, KEYCODE_u);
- map.put(KeyEvent.KEYCODE_V, KEYCODE_v);
- map.put(KeyEvent.KEYCODE_W, KEYCODE_w);
- map.put(KeyEvent.KEYCODE_X, KEYCODE_x);
- map.put(KeyEvent.KEYCODE_Y, KEYCODE_y);
- map.put(KeyEvent.KEYCODE_Z, KEYCODE_z);
- //map.put(KeyEvent.KEYCODE_DEL, KEYCODE_DELETE); use BACKSPACE instead
- //map.put(??, KEYCODE_KP_*);
- map.put(KeyEvent.KEYCODE_DPAD_UP, KEYCODE_UP);
- map.put(KeyEvent.KEYCODE_DPAD_DOWN, KEYCODE_DOWN);
- map.put(KeyEvent.KEYCODE_DPAD_RIGHT, KEYCODE_RIGHT);
- map.put(KeyEvent.KEYCODE_DPAD_LEFT, KEYCODE_LEFT);
- //map.put(??, KEYCODE_INSERT);
- //map.put(??, KEYCODE_HOME);
- //map.put(??, KEYCODE_END);
- //map.put(??, KEYCODE_PAGEUP);
- //map.put(??, KEYCODE_PAGEDOWN);
- //map.put(??, KEYCODE_F{1-15});
- map.put(KeyEvent.KEYCODE_NUM, KEYCODE_NUMLOCK);
- //map.put(??, KEYCODE_CAPSLOCK);
- //map.put(??, KEYCODE_SCROLLLOCK);
- map.put(KeyEvent.KEYCODE_SHIFT_RIGHT, KEYCODE_RSHIFT);
- map.put(KeyEvent.KEYCODE_SHIFT_LEFT, KEYCODE_LSHIFT);
- //map.put(??, KEYCODE_RCTRL);
- //map.put(??, KEYCODE_LCTRL);
- map.put(KeyEvent.KEYCODE_ALT_RIGHT, KEYCODE_RALT);
- map.put(KeyEvent.KEYCODE_ALT_LEFT, KEYCODE_LALT);
- // ?? META, SUPER
- // ?? MODE, COMPOSE
- // ?? HELP, PRINT, SYSREQ, BREAK, EURO, UNDO
- map.put(KeyEvent.KEYCODE_MENU, KEYCODE_MENU);
- map.put(KeyEvent.KEYCODE_POWER, KEYCODE_POWER);
-
- androidKeyMap = Collections.unmodifiableMap(map);
- }
-
- public int type;
- public boolean synthetic;
- public int kbd_keycode;
- public int kbd_ascii;
- public int kbd_flags;
- public int mouse_x;
- public int mouse_y;
- public boolean mouse_relative; // Used for trackball events
-
- public Event() {
- type = EVENT_INVALID;
- synthetic = false;
- }
-
- public Event(int type) {
- this.type = type;
- synthetic = false;
- }
-
- public static Event KeyboardEvent(int type, int keycode, int ascii,
- int flags) {
- Event e = new Event();
- e.type = type;
- e.kbd_keycode = keycode;
- e.kbd_ascii = ascii;
- e.kbd_flags = flags;
- return e;
- }
-
- public static Event MouseEvent(int type, int x, int y) {
- Event e = new Event();
- e.type = type;
- e.mouse_x = x;
- e.mouse_y = y;
- return e;
- }
-}
diff --git a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
index 840f3440d5..3c91d9f5dc 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
@@ -13,6 +13,8 @@ import android.util.Log;
import java.util.ArrayList;
public class PluginProvider extends BroadcastReceiver {
+ private final static String LOG_TAG = "ScummVM";
+
public final static String META_UNPACK_LIB =
"org.inodes.gus.scummvm.meta.UNPACK_LIB";
@@ -26,9 +28,9 @@ public class PluginProvider extends BroadcastReceiver {
try {
info = context.getPackageManager()
.getReceiverInfo(new ComponentName(context, this.getClass()),
- PackageManager.GET_META_DATA);
+ PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
- Log.e(this.toString(), "Error finding my own info?", e);
+ Log.e(LOG_TAG, "Error finding my own info?", e);
return;
}
@@ -36,17 +38,17 @@ public class PluginProvider extends BroadcastReceiver {
if (mylib != null) {
ArrayList<String> all_libs =
extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
-
all_libs.add(new Uri.Builder()
- .scheme("plugin")
- .authority(context.getPackageName())
- .path(mylib)
- .toString());
+ .scheme("plugin")
+ .authority(context.getPackageName())
+ .path(mylib)
+ .toString());
extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
- all_libs);
+ all_libs);
}
setResultExtras(extras);
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index 6986f3988d..8bf40ac553 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -1,450 +1,435 @@
package org.inodes.gus.scummvm;
-import android.content.Context;
+import android.util.Log;
import android.content.res.AssetManager;
+import android.view.SurfaceHolder;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import java.io.File;
-import java.util.concurrent.Semaphore;
-import java.util.Map;
import java.util.LinkedHashMap;
+public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
+ final protected static String LOG_TAG = "ScummVM";
+ final private AssetManager _asset_manager;
+ final private Object _sem_surface;
+
+ private EGL10 _egl;
+ private EGLDisplay _egl_display = EGL10.EGL_NO_DISPLAY;
+ private EGLConfig _egl_config;
+ private EGLContext _egl_context = EGL10.EGL_NO_CONTEXT;
+ private EGLSurface _egl_surface = EGL10.EGL_NO_SURFACE;
+
+ private SurfaceHolder _surface_holder;
+ private AudioTrack _audio_track;
+ private int _sample_rate = 0;
+ private int _buffer_size = 0;
+
+ private String[] _args;
+
+ final private native void create(AssetManager _asset_manager,
+ EGL10 egl, EGLDisplay egl_display,
+ AudioTrack audio_track,
+ int sample_rate, int buffer_size);
+ final private native void destroy();
+ final private native void setSurface(int width, int height);
+ final private native int main(String[] args);
+
+ // pause the engine and all native threads
+ final public native void setPause(boolean pause);
+ final public native void enableZoning(boolean enable);
+ // Feed an event to ScummVM. Safe to call from other threads.
+ final public native void pushEvent(int type, int arg1, int arg2, int arg3,
+ int arg4, int arg5);
-// At least in Android 2.1, eglCreateWindowSurface() requires an
-// EGLNativeWindowSurface object, which is hidden deep in the bowels
-// of libui. Until EGL is properly exposed, it's probably safer to
-// use the Java versions of most EGL functions :(
-
-public class ScummVM implements SurfaceHolder.Callback {
- private final static String LOG_TAG = "ScummVM.java";
+ // Callbacks from C++ peer instance
+ abstract protected void getDPI(float[] values);
+ abstract protected void displayMessageOnOSD(String msg);
+ abstract protected void setWindowCaption(String caption);
+ abstract protected String[] getPluginDirectories();
+ abstract protected void showVirtualKeyboard(boolean enable);
+ abstract protected String[] getSysArchives();
- private final int AUDIO_FRAME_SIZE = 2 * 2; // bytes. 16bit audio * stereo
- public static class AudioSetupException extends Exception {}
+ public ScummVM(AssetManager asset_manager, SurfaceHolder holder) {
+ _asset_manager = asset_manager;
+ _sem_surface = new Object();
- private long nativeScummVM; // native code hangs itself here
- boolean scummVMRunning = false;
+ holder.addCallback(this);
+ }
- private native void create(AssetManager am);
+ // SurfaceHolder callback
+ final public void surfaceCreated(SurfaceHolder holder) {
+ Log.d(LOG_TAG, "surfaceCreated");
- public ScummVM(Context context) {
- create(context.getAssets()); // Init C++ code, set nativeScummVM
+ // no need to do anything, surfaceChanged() will be called in any case
}
- private native void nativeDestroy();
+ // SurfaceHolder callback
+ final public void surfaceChanged(SurfaceHolder holder, int format,
+ int width, int height) {
+ // the orientation may reset on standby mode and the theme manager
+ // could assert when using a portrait resolution. so lets not do that.
+ if (height > width) {
+ Log.d(LOG_TAG, String.format("Ignoring surfaceChanged: %dx%d (%d)",
+ width, height, format));
+ return;
+ }
+
+ Log.d(LOG_TAG, String.format("surfaceChanged: %dx%d (%d)",
+ width, height, format));
- public synchronized void destroy() {
- if (nativeScummVM != 0) {
- nativeDestroy();
- nativeScummVM = 0;
+ synchronized(_sem_surface) {
+ _surface_holder = holder;
+ _sem_surface.notifyAll();
}
- }
- protected void finalize() {
- destroy();
- }
- // Surface creation:
- // GUI thread: create surface, release lock
- // ScummVM thread: acquire lock (block), read surface
- //
- // Surface deletion:
- // GUI thread: post event, acquire lock (block), return
- // ScummVM thread: read event, free surface, release lock
- //
- // In other words, ScummVM thread does this:
- // acquire lock
- // setup surface
- // when SCREEN_CHANGED arrives:
- // destroy surface
- // release lock
- // back to acquire lock
- static final int configSpec[] = {
- EGL10.EGL_RED_SIZE, 5,
- EGL10.EGL_GREEN_SIZE, 5,
- EGL10.EGL_BLUE_SIZE, 5,
- EGL10.EGL_DEPTH_SIZE, 0,
- EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
- EGL10.EGL_NONE,
- };
- EGL10 egl;
- EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
- EGLConfig eglConfig;
- EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
- EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
- Semaphore surfaceLock = new Semaphore(0, true);
- SurfaceHolder nativeSurface;
-
- public void surfaceCreated(SurfaceHolder holder) {
- nativeSurface = holder;
- surfaceLock.release();
+ // store values for the native code
+ setSurface(width, height);
}
- public void surfaceChanged(SurfaceHolder holder, int format,
- int width, int height) {
- // Disabled while I debug GL problems
- //pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
- }
+ // SurfaceHolder callback
+ final public void surfaceDestroyed(SurfaceHolder holder) {
+ Log.d(LOG_TAG, "surfaceDestroyed");
- public void surfaceDestroyed(SurfaceHolder holder) {
- pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
- try {
- surfaceLock.acquire();
- } catch (InterruptedException e) {
- Log.e(this.toString(),
- "Interrupted while waiting for surface lock", e);
+ synchronized(_sem_surface) {
+ _surface_holder = null;
+ _sem_surface.notifyAll();
}
+
+ // clear values for the native code
+ setSurface(0, 0);
}
- // For debugging
- private static final Map<String, Integer> attribs;
- static {
- attribs = new LinkedHashMap<String, Integer>();
- attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID);
- attribs.put("BUFFER_SIZE", EGL10.EGL_BUFFER_SIZE);
- attribs.put("RED_SIZE", EGL10.EGL_RED_SIZE);
- attribs.put("GREEN_SIZE", EGL10.EGL_GREEN_SIZE);
- attribs.put("BLUE_SIZE", EGL10.EGL_BLUE_SIZE);
- attribs.put("ALPHA_SIZE", EGL10.EGL_ALPHA_SIZE);
- //attribs.put("BIND_TO_RGB", EGL10.EGL_BIND_TO_TEXTURE_RGB);
- //attribs.put("BIND_TO_RGBA", EGL10.EGL_BIND_TO_TEXTURE_RGBA);
- attribs.put("CONFIG_CAVEAT", EGL10.EGL_CONFIG_CAVEAT);
- attribs.put("DEPTH_SIZE", EGL10.EGL_DEPTH_SIZE);
- attribs.put("LEVEL", EGL10.EGL_LEVEL);
- attribs.put("MAX_PBUFFER_WIDTH", EGL10.EGL_MAX_PBUFFER_WIDTH);
- attribs.put("MAX_PBUFFER_HEIGHT", EGL10.EGL_MAX_PBUFFER_HEIGHT);
- attribs.put("MAX_PBUFFER_PIXELS", EGL10.EGL_MAX_PBUFFER_PIXELS);
- //attribs.put("MAX_SWAP_INTERVAL", EGL10.EGL_MAX_SWAP_INTERVAL);
- //attribs.put("MIN_SWAP_INTERVAL", EGL10.EGL_MIN_SWAP_INTERVAL);
- attribs.put("NATIVE_RENDERABLE", EGL10.EGL_NATIVE_RENDERABLE);
- attribs.put("NATIVE_VISUAL_ID", EGL10.EGL_NATIVE_VISUAL_ID);
- attribs.put("NATIVE_VISUAL_TYPE", EGL10.EGL_NATIVE_VISUAL_TYPE);
- attribs.put("SAMPLE_BUFFERS", EGL10.EGL_SAMPLE_BUFFERS);
- attribs.put("SAMPLES", EGL10.EGL_SAMPLES);
- attribs.put("STENCIL_SIZE", EGL10.EGL_STENCIL_SIZE);
- attribs.put("SURFACE_TYPE", EGL10.EGL_SURFACE_TYPE);
- attribs.put("TRANSPARENT_TYPE", EGL10.EGL_TRANSPARENT_TYPE);
- attribs.put("TRANSPARENT_RED_VALUE", EGL10.EGL_TRANSPARENT_RED_VALUE);
- attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE);
- attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE);
+ final public void setArgs(String[] args) {
+ _args = args;
}
- private void dumpEglConfig(EGLConfig config) {
- int[] value = new int[1];
- for (Map.Entry<String, Integer> entry : attribs.entrySet()) {
- egl.eglGetConfigAttrib(eglDisplay, config,
- entry.getValue(), value);
- if (value[0] == EGL10.EGL_NONE)
- Log.d(LOG_TAG, entry.getKey() + ": NONE");
- else
- Log.d(LOG_TAG, String.format("%s: %d",
- entry.getKey(), value[0]));
+
+ final public void run() {
+ try {
+ initAudio();
+ initEGL();
+
+ // wait for the surfaceChanged callback
+ synchronized(_sem_surface) {
+ while (_surface_holder == null)
+ _sem_surface.wait();
+ }
+ } catch (Exception e) {
+ deinitEGL();
+ deinitAudio();
+
+ throw new RuntimeException("Error preparing the ScummVM thread", e);
}
+
+ create(_asset_manager, _egl, _egl_display,
+ _audio_track, _sample_rate, _buffer_size);
+
+ int res = main(_args);
+
+ destroy();
+
+ deinitEGL();
+ deinitAudio();
+
+ // On exit, tear everything down for a fresh restart next time.
+ System.exit(res);
}
- // Called by ScummVM thread (from initBackend)
- private void createScummVMGLContext() {
- egl = (EGL10)EGLContext.getEGL();
- eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ final private void initEGL() throws Exception {
+ _egl = (EGL10)EGLContext.getEGL();
+ _egl_display = _egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
int[] version = new int[2];
- egl.eglInitialize(eglDisplay, version);
+ _egl.eglInitialize(_egl_display, version);
+
int[] num_config = new int[1];
- egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
+ _egl.eglGetConfigs(_egl_display, null, 0, num_config);
final int numConfigs = num_config[0];
+
if (numConfigs <= 0)
- throw new IllegalArgumentException("No configs match configSpec");
+ throw new IllegalArgumentException("No EGL configs");
EGLConfig[] configs = new EGLConfig[numConfigs];
- egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
- num_config);
-
- if (false) {
- Log.d(LOG_TAG,
- String.format("Found %d EGL configurations.", numConfigs));
- for (EGLConfig config : configs)
- dumpEglConfig(config);
- }
+ _egl.eglGetConfigs(_egl_display, configs, numConfigs, num_config);
// Android's eglChooseConfig is busted in several versions and
- // devices so we have to filter/rank the configs again ourselves.
- eglConfig = chooseEglConfig(configs);
- if (false) {
- Log.d(LOG_TAG,
- String.format("Chose EGL config from %d possibilities.", numConfigs));
- dumpEglConfig(eglConfig);
- }
+ // devices so we have to filter/rank the configs ourselves.
+ _egl_config = chooseEglConfig(configs);
+
+ _egl_context = _egl.eglCreateContext(_egl_display, _egl_config,
+ EGL10.EGL_NO_CONTEXT, null);
- eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
- EGL10.EGL_NO_CONTEXT, null);
- if (eglContext == EGL10.EGL_NO_CONTEXT)
- throw new RuntimeException("Failed to create context");
+ if (_egl_context == EGL10.EGL_NO_CONTEXT)
+ throw new Exception(String.format("Failed to create context: 0x%x",
+ _egl.eglGetError()));
}
- private EGLConfig chooseEglConfig(EGLConfig[] configs) {
- int best = 0;
- int bestScore = -1;
- int[] value = new int[1];
- for (int i = 0; i < configs.length; i++) {
- EGLConfig config = configs[i];
- int score = 10000;
- egl.eglGetConfigAttrib(eglDisplay, config,
- EGL10.EGL_SURFACE_TYPE, value);
- if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0)
- continue; // must have
-
- egl.eglGetConfigAttrib(eglDisplay, config,
- EGL10.EGL_CONFIG_CAVEAT, value);
- if (value[0] != EGL10.EGL_NONE)
- score -= 1000;
+ // Callback from C++ peer instance
+ final protected EGLSurface initSurface() throws Exception {
+ _egl_surface = _egl.eglCreateWindowSurface(_egl_display, _egl_config,
+ _surface_holder, null);
- // Must be at least 555, but then smaller is better
- final int[] colorBits = {EGL10.EGL_RED_SIZE,
- EGL10.EGL_GREEN_SIZE,
- EGL10.EGL_BLUE_SIZE,
- EGL10.EGL_ALPHA_SIZE};
- for (int component : colorBits) {
- egl.eglGetConfigAttrib(eglDisplay, config,
- component, value);
- if (value[0] >= 5)
- score += 10; // boost if >5 bits accuracy
- score -= value[0]; // penalize for wasted bits
- }
+ if (_egl_surface == EGL10.EGL_NO_SURFACE)
+ throw new Exception(String.format(
+ "eglCreateWindowSurface failed: 0x%x", _egl.eglGetError()));
- egl.eglGetConfigAttrib(eglDisplay, config,
- EGL10.EGL_DEPTH_SIZE, value);
- score -= value[0]; // penalize for wasted bits
+ _egl.eglMakeCurrent(_egl_display, _egl_surface, _egl_surface,
+ _egl_context);
- if (score > bestScore) {
- best = i;
- bestScore = score;
- }
- }
+ GL10 gl = (GL10)_egl_context.getGL();
- if (bestScore < 0) {
- Log.e(LOG_TAG, "Unable to find an acceptable EGL config, expect badness.");
- return configs[0];
- }
+ Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
+ _egl.eglQueryString(_egl_display, EGL10.EGL_VERSION),
+ _egl.eglQueryString(_egl_display, EGL10.EGL_VENDOR),
+ gl.glGetString(GL10.GL_VERSION),
+ gl.glGetString(GL10.GL_RENDERER),
+ gl.glGetString(GL10.GL_VENDOR)));
- return configs[best];
+ return _egl_surface;
}
- // Called by ScummVM thread
- static private boolean _log_version = true;
- protected void setupScummVMSurface() {
- try {
- surfaceLock.acquire();
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e);
- return;
- }
- eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
- nativeSurface, null);
- if (eglSurface == EGL10.EGL_NO_SURFACE)
- Log.e(LOG_TAG, "CreateWindowSurface failed!");
- egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
-
- GL10 gl = (GL10)eglContext.getGL();
-
- if (_log_version) {
- Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)",
- egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION),
- egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR),
- gl.glGetString(GL10.GL_VERSION),
- gl.glGetString(GL10.GL_RENDERER),
- gl.glGetString(GL10.GL_VENDOR)));
- _log_version = false; // only log this once
+ // Callback from C++ peer instance
+ final protected void deinitSurface() {
+ if (_egl_display != EGL10.EGL_NO_DISPLAY) {
+ _egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+
+ if (_egl_surface != EGL10.EGL_NO_SURFACE)
+ _egl.eglDestroySurface(_egl_display, _egl_surface);
}
- int[] value = new int[1];
- egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value);
- int width = value[0];
- egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value);
- int height = value[0];
- Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height));
- setSurfaceSize(width, height);
+ _egl_surface = EGL10.EGL_NO_SURFACE;
}
- // Called by ScummVM thread
- protected void destroyScummVMSurface() {
- if (eglSurface != null) {
- egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- egl.eglDestroySurface(eglDisplay, eglSurface);
- eglSurface = EGL10.EGL_NO_SURFACE;
+ final private void deinitEGL() {
+ if (_egl_display != EGL10.EGL_NO_DISPLAY) {
+ _egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+
+ if (_egl_surface != EGL10.EGL_NO_SURFACE)
+ _egl.eglDestroySurface(_egl_display, _egl_surface);
+
+ if (_egl_context != EGL10.EGL_NO_CONTEXT)
+ _egl.eglDestroyContext(_egl_display, _egl_context);
+
+ _egl.eglTerminate(_egl_display);
}
- surfaceLock.release();
+ _egl_surface = EGL10.EGL_NO_SURFACE;
+ _egl_context = EGL10.EGL_NO_CONTEXT;
+ _egl_config = null;
+ _egl_display = EGL10.EGL_NO_DISPLAY;
+ _egl = null;
}
- public void setSurface(SurfaceHolder holder) {
- holder.addCallback(this);
- }
+ final private void initAudio() throws Exception {
+ _sample_rate = AudioTrack.getNativeOutputSampleRate(
+ AudioManager.STREAM_MUSIC);
+ _buffer_size = AudioTrack.getMinBufferSize(_sample_rate,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT);
+
+ // ~50ms
+ int buffer_size_want = (_sample_rate * 2 * 2 / 20) & ~1023;
+
+ if (_buffer_size < buffer_size_want) {
+ Log.w(LOG_TAG, String.format(
+ "adjusting audio buffer size (was: %d)", _buffer_size));
- final public boolean swapBuffers() {
- if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) {
- int error = egl.eglGetError();
- Log.w(LOG_TAG, String.format("eglSwapBuffers exited with error 0x%x", error));
- if (error == EGL11.EGL_CONTEXT_LOST)
- return false;
+ _buffer_size = buffer_size_want;
}
- return true;
- }
- // Set scummvm config options
- final public native static void loadConfigFile(String path);
- final public native static void setConfMan(String key, int value);
- final public native static void setConfMan(String key, String value);
- final public native void enableZoning(boolean enable);
- final public native void setSurfaceSize(int width, int height);
+ Log.i(LOG_TAG, String.format("Using %d bytes buffer for %dHz audio",
+ _buffer_size, _sample_rate));
- // Feed an event to ScummVM. Safe to call from other threads.
- final public native void pushEvent(Event e);
+ _audio_track = new AudioTrack(AudioManager.STREAM_MUSIC,
+ _sample_rate,
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ _buffer_size,
+ AudioTrack.MODE_STREAM);
- final private native void audioMixCallback(byte[] buf);
+ if (_audio_track.getState() != AudioTrack.STATE_INITIALIZED)
+ throw new Exception(
+ String.format("Error initialising AudioTrack: %d",
+ _audio_track.getState()));
+ }
- // Runs the actual ScummVM program and returns when it does.
- // This should not be called from multiple threads simultaneously...
- final public native int scummVMMain(String[] argv);
+ final private void deinitAudio() {
+ if (_audio_track != null)
+ _audio_track.stop();
- // Callbacks from C++ peer instance
- //protected GraphicsMode[] getSupportedGraphicsModes() {}
- protected void displayMessageOnOSD(String msg) {}
- protected void setWindowCaption(String caption) {}
- protected void showVirtualKeyboard(boolean enable) {}
- protected String[] getSysArchives() { return new String[0]; }
- protected String[] getPluginDirectories() { return new String[0]; }
- protected void initBackend() throws AudioSetupException {
- createScummVMGLContext();
- initAudio();
+ _audio_track = null;
+ _buffer_size = 0;
+ _sample_rate = 0;
}
- private static class AudioThread extends Thread {
- final private int buf_size;
- private boolean is_paused = false;
- final private ScummVM scummvm;
- final private AudioTrack audio_track;
-
- AudioThread(ScummVM scummvm, AudioTrack audio_track, int buf_size) {
- super("AudioThread");
- this.scummvm = scummvm;
- this.audio_track = audio_track;
- this.buf_size = buf_size;
- setPriority(Thread.MAX_PRIORITY);
- setDaemon(true);
- }
+ private static final int[] s_eglAttribs = {
+ EGL10.EGL_CONFIG_ID,
+ EGL10.EGL_BUFFER_SIZE,
+ EGL10.EGL_RED_SIZE,
+ EGL10.EGL_GREEN_SIZE,
+ EGL10.EGL_BLUE_SIZE,
+ EGL10.EGL_ALPHA_SIZE,
+ EGL10.EGL_CONFIG_CAVEAT,
+ EGL10.EGL_DEPTH_SIZE,
+ EGL10.EGL_LEVEL,
+ EGL10.EGL_MAX_PBUFFER_WIDTH,
+ EGL10.EGL_MAX_PBUFFER_HEIGHT,
+ EGL10.EGL_MAX_PBUFFER_PIXELS,
+ EGL10.EGL_NATIVE_RENDERABLE,
+ EGL10.EGL_NATIVE_VISUAL_ID,
+ EGL10.EGL_NATIVE_VISUAL_TYPE,
+ EGL10.EGL_SAMPLE_BUFFERS,
+ EGL10.EGL_SAMPLES,
+ EGL10.EGL_STENCIL_SIZE,
+ EGL10.EGL_SURFACE_TYPE,
+ EGL10.EGL_TRANSPARENT_TYPE,
+ EGL10.EGL_TRANSPARENT_RED_VALUE,
+ EGL10.EGL_TRANSPARENT_GREEN_VALUE,
+ EGL10.EGL_TRANSPARENT_BLUE_VALUE
+ };
- public void pauseAudio() {
- synchronized (this) {
- is_paused = true;
+ final private class EglAttribs extends LinkedHashMap<Integer, Integer> {
+ public EglAttribs(EGLConfig config) {
+ super(s_eglAttribs.length);
+
+ int[] value = new int[1];
+
+ for (int i : s_eglAttribs) {
+ _egl.eglGetConfigAttrib(_egl_display, config, i, value);
+
+ put(i, value[0]);
}
- audio_track.pause();
}
- public void resumeAudio() {
- synchronized (this) {
- is_paused = false;
- notifyAll();
- }
- audio_track.play();
+ private int weightBits(int attr, int size) {
+ final int value = get(attr);
+
+ int score = 0;
+
+ if (value == size || (size > 0 && value > size))
+ score += 10;
+
+ // penalize for wasted bits
+ score -= value - size;
+
+ return score;
}
- public void run() {
- byte[] buf = new byte[buf_size];
- audio_track.play();
- int offset = 0;
- try {
- while (true) {
- synchronized (this) {
- while (is_paused)
- wait();
- }
-
- if (offset == buf.length) {
- // Grab new audio data
- scummvm.audioMixCallback(buf);
- offset = 0;
- }
- int len = buf.length - offset;
- int ret = audio_track.write(buf, offset, len);
- if (ret < 0) {
- Log.w(LOG_TAG, String.format(
- "AudioTrack.write(%dB) returned error %d",
- buf.length, ret));
- break;
- } else if (ret != len) {
- Log.w(LOG_TAG, String.format(
- "Short audio write. Wrote %dB, not %dB",
- ret, buf.length));
- // Buffer is full, so yield cpu for a while
- Thread.sleep(100);
- }
- offset += ret;
- }
- } catch (InterruptedException e) {
- Log.e(this.toString(), "Audio thread interrupted", e);
- }
+ public int weight() {
+ int score = 10000;
+
+ if (get(EGL10.EGL_CONFIG_CAVEAT) != EGL10.EGL_NONE)
+ score -= 1000;
+
+ // less MSAA is better
+ score -= get(EGL10.EGL_SAMPLES) * 100;
+
+ // Must be at least 565, but then smaller is better
+ score += weightBits(EGL10.EGL_RED_SIZE, 5);
+ score += weightBits(EGL10.EGL_GREEN_SIZE, 6);
+ score += weightBits(EGL10.EGL_BLUE_SIZE, 5);
+ score += weightBits(EGL10.EGL_ALPHA_SIZE, 0);
+ score += weightBits(EGL10.EGL_DEPTH_SIZE, 0);
+ score += weightBits(EGL10.EGL_STENCIL_SIZE, 0);
+
+ return score;
}
- }
- private AudioThread audio_thread;
- final public int audioSampleRate() {
- return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
- }
+ public String toString() {
+ String s;
- private void initAudio() throws AudioSetupException {
- int sample_rate = audioSampleRate();
- int buf_size =
- AudioTrack.getMinBufferSize(sample_rate,
- AudioFormat.CHANNEL_CONFIGURATION_STEREO,
- AudioFormat.ENCODING_PCM_16BIT);
- if (buf_size < 0) {
- int guess = AUDIO_FRAME_SIZE * sample_rate / 100; // 10ms of audio
- Log.w(LOG_TAG, String.format(
- "Unable to get min audio buffer size (error %d). Guessing %dB.",
- buf_size, guess));
- buf_size = guess;
+ if (get(EGL10.EGL_ALPHA_SIZE) > 0)
+ s = String.format("[%d] RGBA%d%d%d%d",
+ get(EGL10.EGL_CONFIG_ID),
+ get(EGL10.EGL_RED_SIZE),
+ get(EGL10.EGL_GREEN_SIZE),
+ get(EGL10.EGL_BLUE_SIZE),
+ get(EGL10.EGL_ALPHA_SIZE));
+ else
+ s = String.format("[%d] RGB%d%d%d",
+ get(EGL10.EGL_CONFIG_ID),
+ get(EGL10.EGL_RED_SIZE),
+ get(EGL10.EGL_GREEN_SIZE),
+ get(EGL10.EGL_BLUE_SIZE));
+
+ if (get(EGL10.EGL_DEPTH_SIZE) > 0)
+ s += String.format(" D%d", get(EGL10.EGL_DEPTH_SIZE));
+
+ if (get(EGL10.EGL_STENCIL_SIZE) > 0)
+ s += String.format(" S%d", get(EGL10.EGL_STENCIL_SIZE));
+
+ if (get(EGL10.EGL_SAMPLES) > 0)
+ s += String.format(" MSAAx%d", get(EGL10.EGL_SAMPLES));
+
+ if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) > 0)
+ s += " W";
+ if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_PBUFFER_BIT) > 0)
+ s += " P";
+ if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_PIXMAP_BIT) > 0)
+ s += " X";
+
+ switch (get(EGL10.EGL_CONFIG_CAVEAT)) {
+ case EGL10.EGL_NONE:
+ break;
+
+ case EGL10.EGL_SLOW_CONFIG:
+ s += " SLOW";
+ break;
+
+ case EGL10.EGL_NON_CONFORMANT_CONFIG:
+ s += " NON_CONFORMANT";
+
+ default:
+ s += String.format(" unknown CAVEAT 0x%x",
+ get(EGL10.EGL_CONFIG_CAVEAT));
+ }
+
+ return s;
}
- Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",
- buf_size, sample_rate));
- AudioTrack audio_track =
- new AudioTrack(AudioManager.STREAM_MUSIC,
- sample_rate,
- AudioFormat.CHANNEL_CONFIGURATION_STEREO,
- AudioFormat.ENCODING_PCM_16BIT,
- buf_size,
- AudioTrack.MODE_STREAM);
- if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) {
- Log.e(LOG_TAG, "Error initialising Android audio system.");
- throw new AudioSetupException();
+ };
+
+ final private EGLConfig chooseEglConfig(EGLConfig[] configs) {
+ EGLConfig res = configs[0];
+ int bestScore = -1;
+
+ Log.d(LOG_TAG, "EGL configs:");
+
+ for (EGLConfig config : configs) {
+ EglAttribs attr = new EglAttribs(config);
+
+ // must have
+ if ((attr.get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) == 0)
+ continue;
+
+ int score = attr.weight();
+
+ Log.d(LOG_TAG, String.format("%s (%d)", attr.toString(), score));
+
+ if (score > bestScore) {
+ res = config;
+ bestScore = score;
+ }
}
- audio_thread = new AudioThread(this, audio_track, buf_size);
- audio_thread.start();
- }
+ if (bestScore < 0)
+ Log.e(LOG_TAG,
+ "Unable to find an acceptable EGL config, expect badness.");
- public void pause() {
- audio_thread.pauseAudio();
- // TODO: need to pause engine too
- }
+ Log.d(LOG_TAG, String.format("Chosen EGL config: %s",
+ new EglAttribs(res).toString()));
- public void resume() {
- // TODO: need to resume engine too
- audio_thread.resumeAudio();
+ return res;
}
static {
@@ -452,15 +437,16 @@ public class ScummVM implements SurfaceHolder.Callback {
final boolean sleep_for_debugger = false;
if (sleep_for_debugger) {
try {
- Thread.sleep(20*1000);
+ Thread.sleep(20 * 1000);
} catch (InterruptedException e) {
}
}
- //System.loadLibrary("scummvm");
File cache_dir = ScummVMApplication.getLastCacheDir();
String libname = System.mapLibraryName("scummvm");
File libpath = new File(cache_dir, libname);
+
System.load(libpath.getPath());
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index b37b2b8a52..1978b690d0 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -3,41 +3,27 @@ package org.inodes.gus.scummvm;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
-import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
-import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.SurfaceView;
-import android.view.View;
-import android.view.ViewConfiguration;
+import android.view.SurfaceHolder;
+import android.view.MotionEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
-import java.io.IOException;
-
public class ScummVMActivity extends Activity {
- private boolean _do_right_click;
- private boolean _last_click_was_right;
-
- // game pixels to move per trackball/dpad event.
- // FIXME: replace this with proper mouse acceleration
- private final static int TRACKBALL_SCALE = 2;
private class MyScummVM extends ScummVM {
- private boolean scummvmRunning = false;
-
private boolean usingSmallScreen() {
// Multiple screen sizes came in with Android 1.6. Have
// to use reflection in order to continue supporting 1.5
// devices :(
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
try {
// This 'density' term is very confusing.
int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null);
@@ -48,32 +34,27 @@ public class ScummVMActivity extends Activity {
}
}
- public MyScummVM() {
- super(ScummVMActivity.this);
+ public MyScummVM(SurfaceHolder holder) {
+ super(ScummVMActivity.this.getAssets(), holder);
// 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
- protected void initBackend() throws ScummVM.AudioSetupException {
- synchronized (this) {
- scummvmRunning = true;
- notifyAll();
- }
- super.initBackend();
- }
+ protected void getDPI(float[] values) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
- public void waitUntilRunning() throws InterruptedException {
- synchronized (this) {
- while (!scummvmRunning)
- wait();
- }
+ values[0] = metrics.xdpi;
+ values[1] = metrics.ydpi;
}
@Override
protected void displayMessageOnOSD(String msg) {
- Log.i(this.toString(), "OSD: " + msg);
+ Log.i(LOG_TAG, "OSD: " + msg);
Toast.makeText(ScummVMActivity.this, msg, Toast.LENGTH_LONG).show();
}
@@ -95,24 +76,28 @@ public class ScummVMActivity extends Activity {
@Override
protected void showVirtualKeyboard(final boolean enable) {
- if (getResources().getConfiguration().keyboard ==
- Configuration.KEYBOARD_NOKEYS) {
- runOnUiThread(new Runnable() {
- public void run() {
- showKeyboard(enable);
- }
- });
- }
+ runOnUiThread(new Runnable() {
+ public void run() {
+ showKeyboard(enable);
+ }
+ });
}
+
+ @Override
+ protected String[] getSysArchives() {
+ return new String[0];
+ }
+
}
- private MyScummVM scummvm;
- private Thread scummvm_thread;
+
+ private MyScummVM _scummvm;
+ private ScummVMEvents _events;
+ private Thread _scummvm_thread;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- _do_right_click = false;
setVolumeControlStream(AudioManager.STREAM_MUSIC);
setContentView(R.layout.main);
@@ -126,337 +111,110 @@ public class ScummVMActivity extends Activity {
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.no_sdcard)
.setNegativeButton(R.string.quit,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog,
- int which) {
- finish();
- }
- })
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ finish();
+ }
+ })
.show();
+
return;
}
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
- main_surface.setOnTouchListener(new View.OnTouchListener() {
- public boolean onTouch(View v, MotionEvent event) {
- return onTouchEvent(event);
- }
- });
- main_surface.setOnKeyListener(new View.OnKeyListener() {
- public boolean onKey(View v, int code, KeyEvent ev) {
- return onKeyDown(code, ev);
- }
- });
+
main_surface.requestFocus();
- // Start ScummVM
- scummvm = new MyScummVM();
- scummvm_thread = new Thread(new Runnable() {
- public void run() {
- try {
- runScummVM();
- } catch (Exception e) {
- Log.e("ScummVM", "Fatal error in ScummVM thread", e);
- new AlertDialog.Builder(ScummVMActivity.this)
- .setTitle("Error")
- .setMessage(e.toString())
- .setIcon(android.R.drawable.ic_dialog_alert)
- .show();
- finish();
- }
- }
- }, "ScummVM");
- scummvm_thread.start();
-
- // Block UI thread until ScummVM has started. In particular,
- // this means that surface and event callbacks should be safe
- // after this point.
- try {
- scummvm.waitUntilRunning();
- } catch (InterruptedException e) {
- Log.e(this.toString(),
- "Interrupted while waiting for ScummVM.initBackend", e);
- finish();
- }
+ getFilesDir().mkdirs();
- scummvm.setSurface(main_surface.getHolder());
- }
+ // Start ScummVM
+ _scummvm = new MyScummVM(main_surface.getHolder());
- // Runs in another thread
- private void runScummVM() throws IOException {
- getFilesDir().mkdirs();
- String[] args = {
- "ScummVM-lib",
+ _scummvm.setArgs(new String[] {
+ "ScummVM",
"--config=" + getFileStreamPath("scummvmrc").getPath(),
"--path=" + Environment.getExternalStorageDirectory().getPath(),
"--gui-theme=scummmodern",
- "--savepath=" + getDir("saves", 0).getPath(),
- };
+ "--savepath=" + getDir("saves", 0).getPath()
+ });
- int ret = scummvm.scummVMMain(args);
+ _events = new ScummVMEvents(this, _scummvm);
- // On exit, tear everything down for a fresh
- // restart next time.
- System.exit(ret);
- }
+ main_surface.setOnKeyListener(_events);
+ main_surface.setOnTouchListener(_events);
- private boolean was_paused = false;
+ _scummvm_thread = new Thread(_scummvm, "ScummVM");
+ _scummvm_thread.start();
+ }
@Override
- public void onPause() {
- if (scummvm != null) {
- was_paused = true;
- scummvm.pause();
- }
- super.onPause();
+ public void onStart() {
+ Log.d(ScummVM.LOG_TAG, "onStart");
+
+ super.onStart();
}
@Override
public void onResume() {
+ Log.d(ScummVM.LOG_TAG, "onResume");
+
super.onResume();
- if (scummvm != null && was_paused)
- scummvm.resume();
- was_paused = false;
+
+ if (_scummvm != null)
+ _scummvm.setPause(false);
}
@Override
- public void onStop() {
- if (scummvm != null) {
- scummvm.pushEvent(new Event(Event.EVENT_QUIT));
- try {
- scummvm_thread.join(1000); // 1s timeout
- } catch (InterruptedException e) {
- Log.i(this.toString(),
- "Error while joining ScummVM thread", e);
- }
- }
- super.onStop();
- }
+ public void onPause() {
+ Log.d(ScummVM.LOG_TAG, "onPause");
- static final int MSG_MENU_LONG_PRESS = 1;
- private final Handler keycodeMenuTimeoutHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_MENU_LONG_PRESS) {
- InputMethodManager imm = (InputMethodManager)
- getSystemService(INPUT_METHOD_SERVICE);
- if (imm != null)
- imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
- }
- }
- };
+ super.onPause();
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent kevent) {
- return onKeyDown(keyCode, kevent);
+ if (_scummvm != null)
+ _scummvm.setPause(true);
}
@Override
- public boolean onKeyMultiple(int keyCode, int repeatCount,
- KeyEvent kevent) {
- return onKeyDown(keyCode, kevent);
+ public void onStop() {
+ Log.d(ScummVM.LOG_TAG, "onStop");
+
+ super.onStop();
}
@Override
- public boolean onKeyDown(int keyCode, KeyEvent kevent) {
- // Filter out "special" keys
- switch (keyCode) {
- case KeyEvent.KEYCODE_MENU:
- // Have to reimplement hold-down-menu-brings-up-softkeybd
- // ourselves, since we are otherwise hijacking the menu
- // key :(
- // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
- // for the usual Android implementation of this feature.
- if (kevent.getRepeatCount() > 0)
- // Ignore keyrepeat for menu
- return false;
- boolean timeout_fired = false;
- if (getResources().getConfiguration().keyboard ==
- Configuration.KEYBOARD_NOKEYS) {
- timeout_fired = !keycodeMenuTimeoutHandler.hasMessages(MSG_MENU_LONG_PRESS);
- keycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
- if (kevent.getAction() == KeyEvent.ACTION_DOWN) {
- keycodeMenuTimeoutHandler.sendMessageDelayed(
- keycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
- ViewConfiguration.getLongPressTimeout());
- return true;
- }
- }
- if (kevent.getAction() == KeyEvent.ACTION_UP) {
- if (!timeout_fired)
- scummvm.pushEvent(new Event(Event.EVENT_MAINMENU));
- return true;
- }
- return false;
- case KeyEvent.KEYCODE_CAMERA:
- case KeyEvent.KEYCODE_SEARCH:
- _do_right_click = (kevent.getAction() == KeyEvent.ACTION_DOWN);
- return true;
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT: {
- // HTC Hero doesn't seem to generate
- // MotionEvent.ACTION_DOWN events on trackball press :(
- // We'll have to just fake one here.
- // Some other handsets lack a trackball, so the DPAD is
- // the only way of moving the cursor.
- int motion_action;
- // FIXME: this logic is a mess.
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- switch (kevent.getAction()) {
- case KeyEvent.ACTION_DOWN:
- motion_action = MotionEvent.ACTION_DOWN;
- break;
- case KeyEvent.ACTION_UP:
- motion_action = MotionEvent.ACTION_UP;
- break;
- default: // ACTION_MULTIPLE
- return false;
- }
- } else
- motion_action = MotionEvent.ACTION_MOVE;
-
- Event e = new Event(getEventType(motion_action));
- e.mouse_x = 0;
- e.mouse_y = 0;
- e.mouse_relative = true;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- e.mouse_y = -TRACKBALL_SCALE;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- e.mouse_y = TRACKBALL_SCALE;
- break;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- e.mouse_x = -TRACKBALL_SCALE;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- e.mouse_x = TRACKBALL_SCALE;
- break;
- }
- scummvm.pushEvent(e);
- return true;
- }
- case KeyEvent.KEYCODE_BACK:
- // skip isSystem() check and fall through to main code
- break;
- default:
- if (kevent.isSystem())
- return false;
- }
+ public void onDestroy() {
+ Log.d(ScummVM.LOG_TAG, "onDestroy");
- // FIXME: what do I need to do for composed characters?
-
- Event e = new Event();
-
- switch (kevent.getAction()) {
- case KeyEvent.ACTION_DOWN:
- e.type = Event.EVENT_KEYDOWN;
- e.synthetic = false;
- break;
- case KeyEvent.ACTION_UP:
- e.type = Event.EVENT_KEYUP;
- e.synthetic = false;
- break;
- case KeyEvent.ACTION_MULTIPLE:
- // e.type is handled below
- e.synthetic = true;
- break;
- default:
- return false;
- }
+ super.onDestroy();
- e.kbd_keycode = Event.androidKeyMap.containsKey(keyCode) ?
- Event.androidKeyMap.get(keyCode) : Event.KEYCODE_INVALID;
- e.kbd_ascii = kevent.getUnicodeChar();
- if (e.kbd_ascii == 0)
- e.kbd_ascii = e.kbd_keycode; // scummvm keycodes are mostly ascii
-
-
- e.kbd_flags = 0;
- if (kevent.isAltPressed())
- e.kbd_flags |= Event.KBD_ALT;
- if (kevent.isSymPressed()) // no ctrl key in android, so use sym (?)
- e.kbd_flags |= Event.KBD_CTRL;
- if (kevent.isShiftPressed()) {
- if (keyCode >= KeyEvent.KEYCODE_0 &&
- keyCode <= KeyEvent.KEYCODE_9) {
- // Shift+number -> convert to F* key
- int offset = keyCode == KeyEvent.KEYCODE_0 ?
- 10 : keyCode - KeyEvent.KEYCODE_1; // turn 0 into 10
- e.kbd_keycode = Event.KEYCODE_F1 + offset;
- e.kbd_ascii = Event.ASCII_F1 + offset;
- } else
- e.kbd_flags |= Event.KBD_SHIFT;
- }
+ if (_events != null) {
+ _events.sendQuitEvent();
- if (kevent.getAction() == KeyEvent.ACTION_MULTIPLE) {
- for (int i = 0; i <= kevent.getRepeatCount(); i++) {
- e.type = Event.EVENT_KEYDOWN;
- scummvm.pushEvent(e);
- e.type = Event.EVENT_KEYUP;
- scummvm.pushEvent(e);
+ try {
+ // 1s timeout
+ _scummvm_thread.join(1000);
+ } catch (InterruptedException e) {
+ Log.i(ScummVM.LOG_TAG, "Error while joining ScummVM thread", e);
}
- } else
- scummvm.pushEvent(e);
-
- return true;
- }
- private int getEventType(int action) {
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- _last_click_was_right = _do_right_click;
- return _last_click_was_right ?
- Event.EVENT_RBUTTONDOWN : Event.EVENT_LBUTTONDOWN;
- case MotionEvent.ACTION_UP:
- return _last_click_was_right ?
- Event.EVENT_RBUTTONUP : Event.EVENT_LBUTTONUP;
- case MotionEvent.ACTION_MOVE:
- return Event.EVENT_MOUSEMOVE;
- default:
- return Event.EVENT_INVALID;
+ _scummvm = null;
}
}
@Override
- public boolean onTrackballEvent(MotionEvent event) {
- int type = getEventType(event.getAction());
- if (type == Event.EVENT_INVALID)
- return false;
-
- Event e = new Event(type);
- e.mouse_x =
- (int)(event.getX() * event.getXPrecision()) * TRACKBALL_SCALE;
- e.mouse_y =
- (int)(event.getY() * event.getYPrecision()) * TRACKBALL_SCALE;
- e.mouse_relative = true;
- scummvm.pushEvent(e);
-
- return true;
- }
+ public boolean onTrackballEvent(MotionEvent e) {
+ if (_events != null)
+ return _events.onTrackballEvent(e);
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int type = getEventType(event.getAction());
- if (type == Event.EVENT_INVALID)
- return false;
-
- Event e = new Event(type);
- e.mouse_x = (int)event.getX();
- e.mouse_y = (int)event.getY();
- e.mouse_relative = false;
- scummvm.pushEvent(e);
-
- return true;
+ return false;
}
private void showKeyboard(boolean show) {
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
InputMethodManager imm = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
+
if (show)
imm.showSoftInput(main_surface, InputMethodManager.SHOW_IMPLICIT);
else
@@ -464,3 +222,4 @@ public class ScummVMActivity extends Activity {
InputMethodManager.HIDE_IMPLICIT_ONLY);
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
index 37a9d09e1a..f9eec72eac 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java
@@ -8,22 +8,24 @@ public class ScummVMApplication extends Application {
public final static String ACTION_PLUGIN_QUERY = "org.inodes.gus.scummvm.action.PLUGIN_QUERY";
public final static String EXTRA_UNPACK_LIBS = "org.inodes.gus.scummvm.extra.UNPACK_LIBS";
- private static File cache_dir;
+ private static File _cache_dir;
@Override
public void onCreate() {
super.onCreate();
+
// This is still on /data :(
- cache_dir = getCacheDir();
+ _cache_dir = getCacheDir();
// This is mounted noexec :(
//cache_dir = new File(Environment.getExternalStorageDirectory(),
- // "/.ScummVM.tmp");
+ // "/.ScummVM.tmp");
// This is owned by download manager and requires special
// permissions to access :(
//cache_dir = Environment.getDownloadCacheDirectory();
}
public static File getLastCacheDir() {
- return cache_dir;
+ return _cache_dir;
}
}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java
new file mode 100644
index 0000000000..2d5c100a1c
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java
@@ -0,0 +1,232 @@
+package org.inodes.gus.scummvm;
+
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.content.Context;
+import android.view.KeyEvent;
+import android.view.KeyCharacterMap;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.GestureDetector;
+import android.view.inputmethod.InputMethodManager;
+
+public class ScummVMEvents implements
+ android.view.View.OnKeyListener,
+ android.view.View.OnTouchListener,
+ android.view.GestureDetector.OnGestureListener,
+ android.view.GestureDetector.OnDoubleTapListener {
+
+ public static final int JE_SYS_KEY = 0;
+ public static final int JE_KEY = 1;
+ public static final int JE_DPAD = 2;
+ public static final int JE_DOWN = 3;
+ public static final int JE_SCROLL = 4;
+ public static final int JE_TAP = 5;
+ public static final int JE_DOUBLE_TAP = 6;
+ public static final int JE_MULTI = 7;
+ public static final int JE_BALL = 8;
+ public static final int JE_QUIT = 0x1000;
+
+ final protected Context _context;
+ final protected ScummVM _scummvm;
+ final protected GestureDetector _gd;
+ final protected int _longPress;
+
+ public ScummVMEvents(Context context, ScummVM scummvm) {
+ _context = context;
+ _scummvm = scummvm;
+
+ _gd = new GestureDetector(context, this);
+ _gd.setOnDoubleTapListener(this);
+ _gd.setIsLongpressEnabled(false);
+
+ _longPress = ViewConfiguration.getLongPressTimeout();
+ }
+
+ final public void sendQuitEvent() {
+ _scummvm.pushEvent(JE_QUIT, 0, 0, 0, 0, 0);
+ }
+
+ public boolean onTrackballEvent(MotionEvent e) {
+ _scummvm.pushEvent(JE_BALL, e.getAction(),
+ (int)(e.getX() * e.getXPrecision() * 100),
+ (int)(e.getY() * e.getYPrecision() * 100),
+ 0, 0);
+ return true;
+ }
+
+ final static int MSG_MENU_LONG_PRESS = 1;
+
+ final private Handler keyHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_MENU_LONG_PRESS) {
+ InputMethodManager imm = (InputMethodManager)
+ _context.getSystemService(_context.INPUT_METHOD_SERVICE);
+
+ if (imm != null)
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ }
+ }
+ };
+
+ // OnKeyListener
+ final public boolean onKey(View v, int keyCode, KeyEvent e) {
+ final int action = e.getAction();
+
+ if (e.isSystem()) {
+ // filter what we handle
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ case KeyEvent.KEYCODE_MENU:
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_SEARCH:
+ break;
+
+ default:
+ return false;
+ }
+
+ // no repeats for system keys
+ if (e.getRepeatCount() > 0)
+ return false;
+
+ // Have to reimplement hold-down-menu-brings-up-softkeybd
+ // ourselves, since we are otherwise hijacking the menu key :(
+ // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
+ // for the usual Android implementation of this feature.
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ final boolean fired =
+ !keyHandler.hasMessages(MSG_MENU_LONG_PRESS);
+
+ keyHandler.removeMessages(MSG_MENU_LONG_PRESS);
+
+ if (action == KeyEvent.ACTION_DOWN) {
+ keyHandler.sendMessageDelayed(keyHandler.obtainMessage(
+ MSG_MENU_LONG_PRESS), _longPress);
+ return true;
+ }
+
+ if (fired)
+ return true;
+
+ // only send up events of the menu button to the native side
+ if (action != KeyEvent.ACTION_UP)
+ return true;
+ }
+
+ _scummvm.pushEvent(JE_SYS_KEY, action, keyCode, 0, 0, 0);
+
+ return true;
+ }
+
+ // sequence of characters
+ if (action == KeyEvent.ACTION_MULTIPLE &&
+ keyCode == KeyEvent.KEYCODE_UNKNOWN) {
+ final KeyCharacterMap m = KeyCharacterMap.load(e.getDeviceId());
+ final KeyEvent[] es = m.getEvents(e.getCharacters().toCharArray());
+
+ if (es == null)
+ return true;
+
+ for (KeyEvent s : es) {
+ _scummvm.pushEvent(JE_KEY, s.getAction(), s.getKeyCode(),
+ s.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK,
+ s.getMetaState(), s.getRepeatCount());
+ }
+
+ return true;
+ }
+
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ _scummvm.pushEvent(JE_DPAD, action, keyCode,
+ (int)(e.getEventTime() - e.getDownTime()),
+ e.getRepeatCount(), 0);
+ return true;
+ }
+
+ _scummvm.pushEvent(JE_KEY, action, keyCode,
+ e.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK,
+ e.getMetaState(), e.getRepeatCount());
+
+ return true;
+ }
+
+ // OnTouchListener
+ final public boolean onTouch(View v, MotionEvent e) {
+ final int action = e.getAction();
+
+ // constants from APIv5:
+ // (action & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT
+ final int pointer = (action & 0xff00) >> 8;
+
+ if (pointer > 0) {
+ _scummvm.pushEvent(JE_MULTI, pointer, action & 0xff, // ACTION_MASK
+ (int)e.getX(), (int)e.getY(), 0);
+ return true;
+ }
+
+ return _gd.onTouchEvent(e);
+ }
+
+ // OnGestureListener
+ final public boolean onDown(MotionEvent e) {
+ _scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0);
+ return true;
+ }
+
+ final public boolean onFling(MotionEvent e1, MotionEvent e2,
+ float velocityX, float velocityY) {
+ //Log.d(ScummVM.LOG_TAG, String.format("onFling: %s -> %s (%.3f %.3f)",
+ // e1.toString(), e2.toString(),
+ // velocityX, velocityY));
+
+ return true;
+ }
+
+ final public void onLongPress(MotionEvent e) {
+ // disabled, interferes with drag&drop
+ }
+
+ final public boolean onScroll(MotionEvent e1, MotionEvent e2,
+ float distanceX, float distanceY) {
+ _scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(),
+ (int)e2.getX(), (int)e2.getY(), 0);
+
+ return true;
+ }
+
+ final public void onShowPress(MotionEvent e) {
+ }
+
+ final public boolean onSingleTapUp(MotionEvent e) {
+ _scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(),
+ (int)(e.getEventTime() - e.getDownTime()), 0, 0);
+
+ return true;
+ }
+
+ // OnDoubleTapListener
+ final public boolean onDoubleTap(MotionEvent e) {
+ return true;
+ }
+
+ final public boolean onDoubleTapEvent(MotionEvent e) {
+ _scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(),
+ e.getAction(), 0, 0);
+
+ return true;
+ }
+
+ final public boolean onSingleTapConfirmed(MotionEvent e) {
+ return true;
+ }
+}
+
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
index 7280aac7d4..c4b2ad7f5d 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
@@ -34,7 +34,9 @@ import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
public class Unpacker extends Activity {
- private final static boolean PLUGINS_ENABLED = true;
+ protected final static String LOG_TAG = "ScummVM";
+ // TODO don't hardcode this
+ private final static boolean PLUGINS_ENABLED = false;
private final static String META_NEXT_ACTIVITY =
"org.inodes.gus.unpacker.nextActivity";
private ProgressBar mProgress;
@@ -88,11 +90,11 @@ public class Unpacker extends Activity {
origIntent.getType());
//intent.fillIn(getIntent(), 0);
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
- Log.i(this.toString(),
+ Log.i(LOG_TAG,
"Starting next activity with intent " + intent);
startActivity(intent);
} else {
- Log.w(this.toString(),
+ Log.w(LOG_TAG,
"Unable to extract a component name from " + nextActivity);
}
}
@@ -128,12 +130,12 @@ public class Unpacker extends Activity {
new ZipFile(context.getPackageResourcePath());
job = new UnpackJob(zipfile, new HashSet<String>(1));
} catch (PackageManager.NameNotFoundException e) {
- Log.e(this.toString(), "Package " + pkg +
+ Log.e(LOG_TAG, "Package " + pkg +
" not found", e);
continue;
} catch (IOException e) {
// FIXME: show some sort of GUI error dialog
- Log.e(this.toString(),
+ Log.e(LOG_TAG,
"Error opening ZIP for package " + pkg, e);
continue;
}
@@ -145,7 +147,7 @@ public class Unpacker extends Activity {
// Delete stale filenames from mUnpackDest
for (File file: mUnpackDest.listFiles()) {
if (!all_files.contains(file.getName())) {
- Log.i(this.toString(),
+ Log.i(LOG_TAG,
"Deleting stale cached file " + file);
file.delete();
}
@@ -177,14 +179,14 @@ public class Unpacker extends Activity {
progress += zipentry.getSize();
} else {
if (dest.exists())
- Log.d(this.toString(),
+ Log.d(LOG_TAG,
"Replacing " + dest.getPath() +
" old.mtime=" + dest.lastModified() +
" new.mtime=" + zipentry.getTime() +
" old.size=" + dest.length() +
" new.size=" + zipentry.getSize());
else
- Log.i(this.toString(),
+ Log.i(LOG_TAG,
"Extracting " + zipentry.getName() +
" from " + zipfile.getName() +
" to " + dest.getPath());
@@ -215,12 +217,12 @@ public class Unpacker extends Activity {
zipfile.close();
} catch (IOException e) {
// FIXME: show some sort of GUI error dialog
- Log.e(this.toString(), "Error unpacking plugin", e);
+ Log.e(LOG_TAG, "Error unpacking plugin", e);
}
}
if (progress != total_size)
- Log.d(this.toString(), "Ended with progress " + progress +
+ Log.d(LOG_TAG, "Ended with progress " + progress +
" != total size " + total_size);
setResult(RESULT_OK);
@@ -234,7 +236,7 @@ public class Unpacker extends Activity {
public void onReceive(Context context, Intent intent) {
if (!intent.getAction()
.equals(ScummVMApplication.ACTION_PLUGIN_QUERY)) {
- Log.e(this.toString(),
+ Log.e(LOG_TAG,
"Received unexpected action " + intent.getAction());
return;
}
@@ -323,7 +325,7 @@ public class Unpacker extends Activity {
startActivityForResult(market_intent,
REQUEST_MARKET);
} catch (ActivityNotFoundException e) {
- Log.e(this.toString(),
+ Log.e(LOG_TAG,
"Error starting market", e);
}
}
@@ -351,7 +353,7 @@ public class Unpacker extends Activity {
switch (requestCode) {
case REQUEST_MARKET:
if (resultCode != RESULT_OK)
- Log.w(this.toString(), "Market returned " + resultCode);
+ Log.w(LOG_TAG, "Market returned " + resultCode);
tryUnpack();
break;
}
@@ -363,8 +365,9 @@ public class Unpacker extends Activity {
.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
return ai.metaData;
} catch (PackageManager.NameNotFoundException e) {
- Log.w(this.toString(), "Unable to find my own meta-data", e);
+ Log.w(LOG_TAG, "Unable to find my own meta-data", e);
return new Bundle();
}
}
}
+
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
new file mode 100644
index 0000000000..a6b28ca485
--- /dev/null
+++ b/backends/platform/android/texture.cpp
@@ -0,0 +1,477 @@
+/* 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"
+
+// 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 GLESBaseTexture::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
+ }
+}
+
+GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat) :
+ _glFormat(glFormat),
+ _glType(glType),
+ _glFilter(GL_NEAREST),
+ _texture_name(0),
+ _surface(),
+ _texture_width(0),
+ _texture_height(0),
+ _draw_rect(),
+ _all_dirty(false),
+ _dirty_rect(),
+ _pixelFormat(pixelFormat),
+ _palettePixelFormat()
+{
+ GLCALL(glGenTextures(1, &_texture_name));
+}
+
+GLESBaseTexture::~GLESBaseTexture() {
+ release();
+}
+
+void GLESBaseTexture::release() {
+ if (_texture_name) {
+ LOGD("Destroying texture %u", _texture_name);
+
+ GLCALL(glDeleteTextures(1, &_texture_name));
+ _texture_name = 0;
+ }
+}
+
+void GLESBaseTexture::reinit() {
+ GLCALL(glGenTextures(1, &_texture_name));
+
+ initSize();
+
+ setDirty();
+}
+
+void GLESBaseTexture::initSize() {
+ // 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, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
+ 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 GLESBaseTexture::setLinearFilter(bool value) {
+ if (value)
+ _glFilter = GL_LINEAR;
+ else
+ _glFilter = GL_NEAREST;
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
+ GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
+}
+
+void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) {
+ _surface.w = w;
+ _surface.h = h;
+ _surface.bytesPerPixel = _pixelFormat.bytesPerPixel;
+
+ 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);
+ }
+
+ initSize();
+}
+
+void GLESBaseTexture::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 && !hasPalette()) {
+ //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));
+ }
+
+ clearDirty();
+}
+
+const Graphics::PixelFormat &GLESBaseTexture::getPixelFormat() const {
+ return _pixelFormat;
+}
+
+GLESTexture::GLESTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat) :
+ GLESBaseTexture(glFormat, glType, pixelFormat),
+ _pixels(0),
+ _buf(0) {
+}
+
+GLESTexture::~GLESTexture() {
+ delete[] _buf;
+ delete[] _pixels;
+}
+
+void GLESTexture::allocBuffer(GLuint w, GLuint h) {
+ GLuint oldw = _surface.w;
+ GLuint oldh = _surface.h;
+
+ GLESBaseTexture::allocBuffer(w, h);
+
+ _surface.pitch = w * _pixelFormat.bytesPerPixel;
+
+ if (_surface.w == oldw && _surface.h == oldh) {
+ fillBuffer(0);
+ return;
+ }
+
+ delete[] _buf;
+ delete[] _pixels;
+
+ _pixels = new byte[w * h * _surface.bytesPerPixel];
+ assert(_pixels);
+
+ _surface.pixels = _pixels;
+
+ fillBuffer(0);
+
+ _buf = new byte[w * h * _surface.bytesPerPixel];
+ assert(_buf);
+}
+
+void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
+ const void *buf, int pitch_buf) {
+ setDirtyRect(Common::Rect(x, y, x + w, y + h));
+
+ const byte *src = (const byte *)buf;
+ byte *dst = _pixels + y * _surface.pitch + x * _surface.bytesPerPixel;
+
+ do {
+ memcpy(dst, src, w * _surface.bytesPerPixel);
+ dst += _surface.pitch;
+ src += pitch_buf;
+ } while (--h);
+}
+
+void GLESTexture::fillBuffer(uint32 color) {
+ assert(_surface.pixels);
+
+ if (_pixelFormat.bytesPerPixel == 1 ||
+ ((color & 0xff) == ((color >> 8) & 0xff)))
+ memset(_pixels, color & 0xff, _surface.pitch * _surface.h);
+ else
+ Common::set_to(_pixels, _pixels + _surface.pitch * _surface.h,
+ (uint16)color);
+
+ setDirty();
+}
+
+void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+ if (_all_dirty) {
+ _dirty_rect.top = 0;
+ _dirty_rect.left = 0;
+ _dirty_rect.bottom = _surface.h;
+ _dirty_rect.right = _surface.w;
+
+ _all_dirty = false;
+ }
+
+ if (!_dirty_rect.isEmpty()) {
+ byte *_tex;
+
+ int16 dwidth = _dirty_rect.width();
+ int16 dheight = _dirty_rect.height();
+
+ if (dwidth == _surface.w) {
+ _tex = _pixels + _dirty_rect.top * _surface.pitch;
+ } else {
+ _tex = _buf;
+
+ byte *src = _pixels + _dirty_rect.top * _surface.pitch +
+ _dirty_rect.left * _surface.bytesPerPixel;
+ byte *dst = _buf;
+
+ uint16 l = dwidth * _surface.bytesPerPixel;
+
+ for (uint16 i = 0; i < dheight; ++i) {
+ memcpy(dst, src, l);
+ src += _surface.pitch;
+ dst += l;
+ }
+ }
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+ GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
+
+ GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ _dirty_rect.left, _dirty_rect.top,
+ dwidth, dheight, _glFormat, _glType, _tex));
+ }
+
+ GLESBaseTexture::drawTexture(x, y, w, h);
+}
+
+GLES4444Texture::GLES4444Texture() :
+ GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {
+}
+
+GLES4444Texture::~GLES4444Texture() {
+}
+
+GLES5551Texture::GLES5551Texture() :
+ GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {
+}
+
+GLES5551Texture::~GLES5551Texture() {
+}
+
+GLES565Texture::GLES565Texture() :
+ GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {
+}
+
+GLES565Texture::~GLES565Texture() {
+}
+
+GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat) :
+ GLESBaseTexture(glFormat, glType, pixelFormat),
+ _palette(0),
+ _pixels(0),
+ _buf(0)
+{
+ _palettePixelFormat = pixelFormat;
+ _fake_format = Graphics::PixelFormat::createFormatCLUT8();
+
+ _palette = new uint16[256];
+ assert(_palette);
+
+ memset(_palette, 0, 256 * 2);
+}
+
+GLESFakePaletteTexture::~GLESFakePaletteTexture() {
+ delete[] _buf;
+ delete[] _pixels;
+ delete[] _palette;
+}
+
+void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
+ GLuint oldw = _surface.w;
+ GLuint oldh = _surface.h;
+
+ GLESBaseTexture::allocBuffer(w, h);
+
+ _surface.bytesPerPixel = 1;
+ _surface.pitch = w;
+
+ if (_surface.w == oldw && _surface.h == oldh) {
+ fillBuffer(0);
+ return;
+ }
+
+ delete[] _buf;
+ delete[] _pixels;
+
+ _pixels = new byte[w * h];
+ assert(_pixels);
+
+ // fixup surface, for the outside this is a CLUT8 surface
+ _surface.pixels = _pixels;
+
+ fillBuffer(0);
+
+ _buf = new uint16[w * h];
+ assert(_buf);
+}
+
+void GLESFakePaletteTexture::fillBuffer(uint32 color) {
+ assert(_surface.pixels);
+ memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h);
+ setDirty();
+}
+
+void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w,
+ GLuint h, const void *buf,
+ int pitch_buf) {
+ setDirtyRect(Common::Rect(x, y, x + w, y + h));
+
+ const byte *src = (const byte *)buf;
+ byte *dst = _pixels + y * _surface.pitch + x;
+
+ do {
+ memcpy(dst, src, w);
+ dst += _surface.pitch;
+ src += pitch_buf;
+ } while (--h);
+}
+
+void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
+ GLshort h) {
+ if (_all_dirty) {
+ _dirty_rect.top = 0;
+ _dirty_rect.left = 0;
+ _dirty_rect.bottom = _surface.h;
+ _dirty_rect.right = _surface.w;
+
+ _all_dirty = false;
+ }
+
+ if (!_dirty_rect.isEmpty()) {
+ int16 dwidth = _dirty_rect.width();
+ int16 dheight = _dirty_rect.height();
+
+ byte *src = _pixels + _dirty_rect.top * _surface.pitch +
+ _dirty_rect.left;
+ uint16 *dst = _buf;
+ uint pitch_delta = _surface.pitch - dwidth;
+
+ for (uint16 j = 0; j < dheight; ++j) {
+ for (uint16 i = 0; i < dwidth; ++i)
+ *dst++ = _palette[*src++];
+ src += pitch_delta;
+ }
+
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+ GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
+ _dirty_rect.left, _dirty_rect.top,
+ dwidth, dheight, _glFormat, _glType, _buf));
+ }
+
+ GLESBaseTexture::drawTexture(x, y, w, h);
+}
+
+const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const {
+ return _fake_format;
+}
+
+GLESFakePalette565Texture::GLESFakePalette565Texture() :
+ GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
+ GLES565Texture::pixelFormat()) {
+}
+
+GLESFakePalette565Texture::~GLESFakePalette565Texture() {
+}
+
+GLESFakePalette5551Texture::GLESFakePalette5551Texture() :
+ GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
+ GLES5551Texture::pixelFormat()) {
+}
+
+GLESFakePalette5551Texture::~GLESFakePalette5551Texture() {
+}
+
+#endif
+
diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h
new file mode 100644
index 0000000000..6344326259
--- /dev/null
+++ b/backends/platform/android/texture.h
@@ -0,0 +1,277 @@
+/* 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 "graphics/pixelformat.h"
+
+#include "common/rect.h"
+#include "common/array.h"
+
+class GLESBaseTexture {
+public:
+ static void initGLExtensions();
+
+protected:
+ GLESBaseTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat);
+
+public:
+ virtual ~GLESBaseTexture();
+
+ void release();
+ void reinit();
+ void initSize();
+
+ void setLinearFilter(bool value);
+
+ virtual void allocBuffer(GLuint w, GLuint h);
+
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void *buf, int pitch_buf) = 0;
+ virtual void fillBuffer(uint32 color) = 0;
+
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+ inline void setDrawRect(const Common::Rect &rect) {
+ _draw_rect = rect;
+ }
+
+ inline void setDrawRect(int16 w, int16 h) {
+ _draw_rect = Common::Rect(w, h);
+ }
+
+ inline void setDrawRect(int16 x1, int16 y1, int16 x2, int16 y2) {
+ _draw_rect = Common::Rect(x1, y1, x2, y2);
+ }
+
+ inline const Common::Rect &getDrawRect() const {
+ return _draw_rect;
+ }
+
+ inline void drawTextureRect() {
+ drawTexture(_draw_rect.left, _draw_rect.top,
+ _draw_rect.width(), _draw_rect.height());
+ }
+
+ inline void drawTextureOrigin() {
+ drawTexture(0, 0, _surface.w, _surface.h);
+ }
+
+ inline GLuint width() const {
+ return _surface.w;
+ }
+
+ inline GLuint height() const {
+ return _surface.h;
+ }
+
+ inline uint16 pitch() const {
+ return _surface.pitch;
+ }
+
+ inline bool isEmpty() const {
+ return _surface.w == 0 || _surface.h == 0;
+ }
+
+ inline const Graphics::Surface *surface_const() const {
+ return &_surface;
+ }
+
+ inline Graphics::Surface *surface() {
+ setDirty();
+ return &_surface;
+ }
+
+ virtual const byte *palette_const() const {
+ return 0;
+ };
+
+ virtual byte *palette() {
+ return 0;
+ };
+
+ inline bool hasPalette() const {
+ return _palettePixelFormat.bytesPerPixel > 0;
+ }
+
+ inline bool dirty() const {
+ return _all_dirty || !_dirty_rect.isEmpty();
+ }
+
+ virtual const Graphics::PixelFormat &getPixelFormat() const;
+
+ inline const Graphics::PixelFormat &getPalettePixelFormat() const {
+ return _palettePixelFormat;
+ }
+
+protected:
+ inline void setDirty() {
+ _all_dirty = true;
+ }
+
+ inline void clearDirty() {
+ _all_dirty = false;
+ _dirty_rect.top = 0;
+ _dirty_rect.left = 0;
+ _dirty_rect.bottom = 0;
+ _dirty_rect.right = 0;
+ }
+
+ inline void setDirtyRect(const Common::Rect& r) {
+ if (!_all_dirty) {
+ if (_dirty_rect.isEmpty())
+ _dirty_rect = r;
+ else
+ _dirty_rect.extend(r);
+ }
+ }
+
+ GLenum _glFormat;
+ GLenum _glType;
+ GLint _glFilter;
+
+ GLuint _texture_name;
+ Graphics::Surface _surface;
+ GLuint _texture_width;
+ GLuint _texture_height;
+
+ Common::Rect _draw_rect;
+
+ bool _all_dirty;
+ Common::Rect _dirty_rect;
+
+ Graphics::PixelFormat _pixelFormat;
+ Graphics::PixelFormat _palettePixelFormat;
+};
+
+class GLESTexture : public GLESBaseTexture {
+protected:
+ GLESTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat);
+
+public:
+ virtual ~GLESTexture();
+
+ virtual void allocBuffer(GLuint w, GLuint h);
+
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void *buf, int pitch_buf);
+ virtual void fillBuffer(uint32 color);
+
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+protected:
+ byte *_pixels;
+ byte *_buf;
+};
+
+// RGBA4444 texture
+class GLES4444Texture : public GLESTexture {
+public:
+ GLES4444Texture();
+ virtual ~GLES4444Texture();
+
+ static Graphics::PixelFormat pixelFormat() {
+ return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
+ }
+};
+
+// RGBA5551 texture
+class GLES5551Texture : public GLESTexture {
+public:
+ GLES5551Texture();
+ virtual ~GLES5551Texture();
+
+ static inline Graphics::PixelFormat pixelFormat() {
+ return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
+ }
+};
+
+// RGB565 texture
+class GLES565Texture : public GLESTexture {
+public:
+ GLES565Texture();
+ virtual ~GLES565Texture();
+
+ static inline Graphics::PixelFormat pixelFormat() {
+ return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ }
+};
+
+class GLESFakePaletteTexture : public GLESBaseTexture {
+protected:
+ GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat pixelFormat);
+
+public:
+ virtual ~GLESFakePaletteTexture();
+
+ virtual void allocBuffer(GLuint w, GLuint h);
+ virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
+ const void *buf, int pitch_buf);
+ virtual void fillBuffer(uint32 color);
+
+ virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
+
+ virtual const byte *palette_const() const {
+ return (byte *)_palette;
+ };
+
+ virtual byte *palette() {
+ setDirty();
+ return (byte *)_palette;
+ };
+
+ virtual const Graphics::PixelFormat &getPixelFormat() const;
+
+protected:
+ Graphics::PixelFormat _fake_format;
+ uint16 *_palette;
+ byte *_pixels;
+ uint16 *_buf;
+};
+
+class GLESFakePalette565Texture : public GLESFakePaletteTexture {
+public:
+ GLESFakePalette565Texture();
+ virtual ~GLESFakePalette565Texture();
+};
+
+class GLESFakePalette5551Texture : public GLESFakePaletteTexture {
+public:
+ GLESFakePalette5551Texture();
+ virtual ~GLESFakePalette5551Texture();
+};
+
+#endif
+#endif
+
diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp
deleted file mode 100644
index 3275335d97..0000000000
--- a/backends/platform/android/video.cpp
+++ /dev/null
@@ -1,354 +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$
- *
- */
-
-#include "base/main.h"
-#include "graphics/surface.h"
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <android/log.h>
-
-#include "common/rect.h"
-#include "common/array.h"
-#include "common/util.h"
-#include "common/tokenizer.h"
-
-#include "backends/platform/android/video.h"
-
-// Unfortunately, Android devices are too varied to make broad assumptions :/
-#define TEXSUBIMAGE_IS_EXPENSIVE 0
-
-#undef LOG_TAG
-#define LOG_TAG "ScummVM-video"
-
-#if 0
-#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args)
-#else
-#define ENTER(args...) /**/
-#endif
-
-#if 0
-#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__)
-static const char* getGlErrStr(GLenum error) {
- switch (error) {
- case GL_NO_ERROR: return "GL_NO_ERROR";
- case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
- case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
- case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
- case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
- case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
- }
-
- static char buf[40];
- snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error);
- return buf;
-}
-static void checkGlError(const char* file, int line) {
- GLenum error = glGetError();
- if (error != GL_NO_ERROR)
- warning("%s:%d: GL error: %s", file, line, getGlErrStr(error));
-}
-#else
-#define CHECK_GL_ERROR() do {} while (false)
-#endif
-
-// 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));
- __android_log_print(ANDROID_LOG_INFO, LOG_TAG,
- "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)
-{
- glGenTextures(1, &_texture_name);
- // This all gets reset later in allocBuffer:
- _surface.w = 0;
- _surface.h = 0;
- _surface.pitch = _texture_width;
- _surface.pixels = NULL;
- _surface.bytesPerPixel = 0;
-}
-
-GLESTexture::~GLESTexture() {
- debug("Destroying texture %u", _texture_name);
- glDeleteTextures(1, &_texture_name);
-}
-
-void GLESTexture::reinitGL() {
- glGenTextures(1, &_texture_name);
- setDirty();
-}
-
-void GLESTexture::allocBuffer(GLuint w, GLuint h) {
- CHECK_GL_ERROR();
- int bpp = bytesPerPixel();
- _surface.w = w;
- _surface.h = h;
- _surface.bytesPerPixel = bpp;
-
- if (w <= _texture_width && h <= _texture_height)
- // Already allocated a sufficiently large buffer
- 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).
- CHECK_GL_ERROR();
- glBindTexture(GL_TEXTURE_2D, _texture_name);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- CHECK_GL_ERROR();
- glTexImage2D(GL_TEXTURE_2D, 0, glFormat(),
- _texture_width, _texture_height,
- 0, glFormat(), glType(), NULL);
- CHECK_GL_ERROR();
-}
-
-void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
- const void* buf, int pitch) {
- ENTER("updateBuffer(%u, %u, %u, %u, %p, %d)", x, y, w, h, buf, pitch);
- glBindTexture(GL_TEXTURE_2D, _texture_name);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- setDirtyRect(Common::Rect(x, y, x+w, y+h));
-
- if (static_cast<int>(w) * bytesPerPixel() == pitch) {
- 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);
- 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 {
- 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) {
- 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) {
- //glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- const GLint crop[4] = {0, _surface.h, _surface.w, -_surface.h};
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
- glColor4ub(0xff, 0xff, 0xff, 0xff); // Android GLES bug?
- 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,
- };
- glTexCoordPointer(2, GL_FIXED, 0, texcoords);
-
- const GLshort vertices[] = {
- x, y,
- x+w, y,
- x, y+h,
- x+w, y+h,
- };
- glVertexPointer(2, GL_SHORT, 0, vertices);
-
- assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
- glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices)/2);
- }
-
- _all_dirty = false;
- _dirty_rect = Common::Rect();
-}
-
-GLESPaletteTexture::GLESPaletteTexture() :
- GLESTexture(),
- _texture(NULL)
-{
-}
-
-GLESPaletteTexture::~GLESPaletteTexture() {
- delete[] _texture;
-}
-
-void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
- CHECK_GL_ERROR();
- int bpp = bytesPerPixel();
- _surface.w = w;
- _surface.h = h;
- _surface.bytesPerPixel = bpp;
-
- if (w <= _texture_width && h <= _texture_height)
- // Already allocated a sufficiently large buffer
- 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) {
- memcpy(new_buffer, _texture, paletteSize()); // preserve palette
- 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();
- glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(),
- _texture_width, _texture_height,
- 0, texture_size, _texture);
- CHECK_GL_ERROR();
-}
-
-void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
- if (_all_dirty) {
- glBindTexture(GL_TEXTURE_2D, _texture_name);
- CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- CHECK_GL_ERROR();
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- CHECK_GL_ERROR();
- uploadTexture();
- _all_dirty = false;
- }
-
- GLESTexture::drawTexture(x, y, w, h);
-}
diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h
deleted file mode 100644
index 2ca07e0afd..0000000000
--- a/backends/platform/android/video.h
+++ /dev/null
@@ -1,140 +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);
- const Graphics::Surface* surface_const() const { return &_surface; }
- GLuint width() const { return _surface.w; }
- GLuint height() const { return _surface.h; }
- GLuint texture_name() const { return _texture_name; }
- bool dirty() const { return _all_dirty || !_dirty_rect.isEmpty(); }
- virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
- const void* buf, int pitch);
- virtual void fillBuffer(byte x);
- virtual void drawTexture() {
- drawTexture(0, 0, _surface.w, _surface.h);
- }
- virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
-protected:
- virtual byte bytesPerPixel() const = 0;
- virtual GLenum glFormat() const = 0;
- virtual GLenum glType() const = 0;
- virtual size_t paletteSize() const { return 0; };
- void setDirty() {
- _all_dirty = true;
- _dirty_rect = Common::Rect();
- }
- 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;
- Common::Rect _dirty_rect; // Covers dirty area
-};
-
-// 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);
- Graphics::Surface* surface() {
- setDirty();
- return &_surface;
- }
- void* pixels() {
- setDirty();
- return _surface.pixels;
- }
- const byte* palette_const() const { return _texture; };
- byte* palette() {
- setDirty();
- return _texture;
- };
- virtual void drawTexture() {
- drawTexture(0, 0, _surface.w, _surface.h);
- }
- virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
- virtual void fillBuffer(byte x);
-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; };
- virtual 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
diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp
index 53dbff333d..b297022775 100644
--- a/backends/platform/dc/display.cpp
+++ b/backends/platform/dc/display.cpp
@@ -156,7 +156,7 @@ void OSystem_Dreamcast::setPalette(const byte *colors, uint start, uint num)
*dst++ = ((colors[0]<<7)&0x7c00)|
((colors[1]<<2)&0x03e0)|
((colors[2]>>3)&0x001f);
- colors += 4;
+ colors += 3;
}
_screen_dirty = true;
}
@@ -169,7 +169,7 @@ void OSystem_Dreamcast::setCursorPalette(const byte *colors, uint start, uint nu
*dst++ = ((colors[0]<<7)&0x7c00)|
((colors[1]<<2)&0x03e0)|
((colors[2]>>3)&0x001f);
- colors += 4;
+ colors += 3;
}
_enable_cursor_palette = true;
}
@@ -188,8 +188,7 @@ void OSystem_Dreamcast::grabPalette(byte *colors, uint start, uint num)
colors[0] = ((p&0x7c00)>>7)|((p&0x7000)>>12);
colors[1] = ((p&0x03e0)>>2)|((p&0x0380)>>7);
colors[2] = ((p&0x001f)<<3)|((p&0x001c)>>2);
- colors[3] = 0xff;
- colors += 4;
+ colors += 3;
}
}
diff --git a/backends/platform/dc/dreamcast.mk b/backends/platform/dc/dreamcast.mk
index d53af90585..8651a2936c 100644
--- a/backends/platform/dc/dreamcast.mk
+++ b/backends/platform/dc/dreamcast.mk
@@ -29,7 +29,7 @@ IP.BIN : ip.txt
ip.txt : $(srcdir)/backends/platform/dc/ip.txt.in
if [ x"$(VER_EXTRA)" = xgit ]; then \
- if [ -z "$(VER_REV)" ]; then ver="GIT"; else ver="r$(VER_REV)"; fi; \
+ ver="GIT"; \
else ver="V$(VERSION)"; fi; \
if expr "$$ver" : V...... >/dev/null; then \
ver="V$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)"; fi; \
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index 55e3be6cca..3ad92b4355 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -204,7 +204,7 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
}
// if (num == 255) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
- colors += 4;
+ colors += 3;
}
}
@@ -235,7 +235,7 @@ void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
u16 paletteValue = red | (green << 5) | (blue << 10);
_cursorPalette[r] = paletteValue;
- colors += 4;
+ colors += 3;
}
_disableCursorPalette = false;
@@ -266,7 +266,6 @@ void OSystem_DS::grabPalette(unsigned char *colours, uint start, uint num) {
*colours++ = (BG_PALETTE[r] & 0x001F) << 3;
*colours++ = (BG_PALETTE[r] & 0x03E0) >> 5 << 3;
*colours++ = (BG_PALETTE[r] & 0x7C00) >> 10 << 3;
- colours++;
}
}
diff --git a/backends/platform/ds/build-ds.sh b/backends/platform/ds/build-ds.sh
index d56af5a092..8e0b0575f4 100755
--- a/backends/platform/ds/build-ds.sh
+++ b/backends/platform/ds/build-ds.sh
@@ -1,4 +1,8 @@
#!/bin/sh
+
+echo "FIXME: feature disabled in configure"
+exit 1
+
#
# build-ds.sh -- script for building a ds build with every usable dynamic engine plugin
diff --git a/backends/platform/gp2x/build/README-GP2X b/backends/platform/gp2x/build/README-GP2X
deleted file mode 100644
index 3c6591d369..0000000000
--- a/backends/platform/gp2x/build/README-GP2X
+++ /dev/null
@@ -1,54 +0,0 @@
-ScummVM - GP2X SPECIFIC README
-------------------------------------------------------------------------
-
-Contents:
-
- * About the backend/port <#About_the_backendport>
- * Supported audio options <#Supported_audio_options>
- * Credits <#Credits>
-
-------------------------------------------------------------------------
-
-Please refer to the:
-
-GP2X/GP2XWiz ScummVM Forum: <http://forums.scummvm.org/viewforum.php?f=14>
-WiKi: <http://wiki.scummvm.org/index.php/GP2X>
-
-for the most current information on the port and any updates to this
-documentation.
-
-The wiki includes detailed instructions on how to use the port and
-control information.
-
-------------------------------------------------------------------------
-About the backend/port
-
-This is the readme for the official GP2X ScummVM backend (also known as
-the GP2X port).
-
-This is an SVN test release of ScummVM for the GP2X, it would be
-appreciated if this SVN test distribution was not mirrored and that
-people be directed to http://scummvm.distant-earth.com/ instead for
-updated SVN builds.
-
-Full supported official releases of the GP2X ScummVM backend are made in
-line with main official releases and are avalalble from the ScummVM
-downloads page <http://www.scummvm.org/downloads.php>.
-
-------------------------------------------------------------------------
-Supported audio options
-
-Raw audio.
-MP3 audio.
-OGG Vorbis audio.
-
-FLAC audio is currently unsupported.
-
-For best results use uncompressed audio in games.
-
-------------------------------------------------------------------------
-Credits
-
-Core ScummVM code (c) The ScummVM Team
-Portions of the GP2X backend (c) John Willis
-Detailed (c) information can be found within the source code
diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh
deleted file mode 100755
index d17f8bd831..0000000000
--- a/backends/platform/gp2x/build/bundle.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-echo Quick script to make building a distribution of the GP2X port more consistent.
-
-cd ../../../..
-
-echo Building ScummVM for GP2X Wiz.
-
-make gp2x-bundle
-
diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h
index 4d2a9c33cc..2a06cab788 100644
--- a/backends/platform/gp2x/gp2x-common.h
+++ b/backends/platform/gp2x/gp2x-common.h
@@ -26,7 +26,11 @@
#ifndef PLATFORM_SDL_GP2X_H
#define PLATFORM_SDL_GP2X_H
+#include "backends/base-backend.h"
+#include "backends/platform/sdl/sdl.h"
#include "backends/platform/sdl/posix/posix.h"
+#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
+#include "backends/events/gp2xsdl/gp2xsdl-events.h"
#ifndef PATH_MAX
#define PATH_MAX 255
@@ -34,12 +38,15 @@
class OSystem_GP2X : public OSystem_POSIX {
public:
- virtual void initBackend();
- virtual void quit();
- virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+ OSystem_GP2X() {}
+
+ void initBackend();
+ void quit();
+ void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+ void initSDL();
protected:
- virtual void initSDL();
+
};
#endif
diff --git a/backends/platform/gp2x/gp2x-main.cpp b/backends/platform/gp2x/gp2x-main.cpp
index a194accd77..f1ee5ed5f3 100644
--- a/backends/platform/gp2x/gp2x-main.cpp
+++ b/backends/platform/gp2x/gp2x-main.cpp
@@ -18,15 +18,13 @@
* 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$
- *
*/
#include "backends/platform/gp2x/gp2x-common.h"
-#include "backends/plugins/posix/posix-provider.h"
+#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
+#if defined(GP2X)
int main(int argc, char *argv[]) {
// Create our OSystem instance
@@ -37,7 +35,7 @@ int main(int argc, char *argv[]) {
((OSystem_GP2X *)g_system)->init();
#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new POSIXPluginProvider());
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
@@ -48,3 +46,5 @@ int main(int argc, char *argv[]) {
return res;
}
+
+#endif
diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp
index 8ae54d679c..4cdb4cd0d5 100644
--- a/backends/platform/gp2x/gp2x.cpp
+++ b/backends/platform/gp2x/gp2x.cpp
@@ -18,9 +18,6 @@
* 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$
- *
*/
/*
@@ -31,12 +28,11 @@
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "backends/platform/sdl/sdl-sys.h"
#include "backends/platform/gp2x/gp2x-common.h"
#include "backends/platform/gp2x/gp2x-hw.h"
#include "backends/platform/gp2x/gp2x-mem.h"
-#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h"
-#include "backends/events/gp2xsdl/gp2xsdl-events.h"
#include "backends/saves/default/default-saves.h"
#include "common/config-manager.h"
@@ -143,7 +139,7 @@ void OSystem_GP2X::initBackend() {
if (_graphicsManager == 0)
_graphicsManager = new GP2XSdlGraphicsManager(_eventSource);
- // Call parent implementation of this method
+ /* Pass to POSIX method to do the heavy lifting */
OSystem_POSIX::initBackend();
}
diff --git a/backends/platform/gph/caanoo/build.sh b/backends/platform/gph/build/caanoo-build.sh
index 8000d2595d..8000d2595d 100755..100644
--- a/backends/platform/gph/caanoo/build.sh
+++ b/backends/platform/gph/build/caanoo-build.sh
diff --git a/backends/platform/gph/caanoo/bundle-debug.sh b/backends/platform/gph/build/caanoo-bundle-debug.sh
index 2d5cefe80e..2d5cefe80e 100755..100644
--- a/backends/platform/gph/caanoo/bundle-debug.sh
+++ b/backends/platform/gph/build/caanoo-bundle-debug.sh
diff --git a/backends/platform/gph/caanoo/bundle.sh b/backends/platform/gph/build/caanoo-bundle.sh
index 76fd31cec6..76fd31cec6 100755..100644
--- a/backends/platform/gph/caanoo/bundle.sh
+++ b/backends/platform/gph/build/caanoo-bundle.sh
diff --git a/backends/platform/gph/caanoo/config-alleng.sh b/backends/platform/gph/build/caanoo-config-alleng.sh
index 97fed942fa..97fed942fa 100755..100644
--- a/backends/platform/gph/caanoo/config-alleng.sh
+++ b/backends/platform/gph/build/caanoo-config-alleng.sh
diff --git a/backends/platform/gph/caanoo/config.sh b/backends/platform/gph/build/caanoo-config.sh
index 11d597481a..11d597481a 100755..100644
--- a/backends/platform/gph/caanoo/config.sh
+++ b/backends/platform/gph/build/caanoo-config.sh
diff --git a/backends/platform/gph/build/clean.sh b/backends/platform/gph/build/clean.sh
index 5ec1b9e62c..6d58b7a975 100755
--- a/backends/platform/gph/build/clean.sh
+++ b/backends/platform/gph/build/clean.sh
@@ -4,5 +4,5 @@ echo Quick script to make building all the time less painful.
cd ../../../..
-echo Cleaning ScummVM for the GP2X Wiz.
+echo Cleaning ScummVM for the GPH devices.
make clean
diff --git a/backends/platform/gp2x/build/build.sh b/backends/platform/gph/build/gp2x-build.sh
index 1ea77f4937..1ea77f4937 100755..100644
--- a/backends/platform/gp2x/build/build.sh
+++ b/backends/platform/gph/build/gp2x-build.sh
diff --git a/backends/platform/gph/build/gp2x-bundle.sh b/backends/platform/gph/build/gp2x-bundle.sh
new file mode 100644
index 0000000000..c4fe63ed9e
--- /dev/null
+++ b/backends/platform/gph/build/gp2x-bundle.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+echo Quick script to make building a distribution of the GP2X port more consistent.
+
+# Set the paths up here to support the build.
+
+export PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin:$PATH
+export PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin:$PATH
+export CXX=arm-open2x-linux-g++
+export CC=arm-open2x-linux-gcc
+export CXXFLAGS=-march=armv4t
+export LDFLAGS=-static
+export ASFLAGS=-mfloat-abi=soft
+
+cd ../../../..
+
+echo Building ScummVM for GP2X Wiz.
+
+make gp2x-bundle
diff --git a/backends/platform/gp2x/build/config-alleng.sh b/backends/platform/gph/build/gp2x-config-alleng.sh
index 4a3526d50c..4a3526d50c 100755..100644
--- a/backends/platform/gp2x/build/config-alleng.sh
+++ b/backends/platform/gph/build/gp2x-config-alleng.sh
diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gph/build/gp2x-config.sh
index e0a1bf1209..9092b0b1ea 100755..100644
--- a/backends/platform/gp2x/build/config.sh
+++ b/backends/platform/gph/build/gp2x-config.sh
@@ -17,7 +17,7 @@ export DEFINES=-DNDEBUG
# Edit the configure line to suit.
cd ../../../..
-./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd
+./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd --enable-plugins --default-dynamic
# --disable-release --enable-debug
# --enable-plugins --default-dynamic
diff --git a/backends/platform/gph/build/build.sh b/backends/platform/gph/build/gp2xwiz-build.sh
index 876c3e378a..876c3e378a 100755..100644
--- a/backends/platform/gph/build/build.sh
+++ b/backends/platform/gph/build/gp2xwiz-build.sh
diff --git a/backends/platform/gph/build/bundle-debug.sh b/backends/platform/gph/build/gp2xwiz-bundle-debug.sh
index cd5145b31d..cd5145b31d 100755..100644
--- a/backends/platform/gph/build/bundle-debug.sh
+++ b/backends/platform/gph/build/gp2xwiz-bundle-debug.sh
diff --git a/backends/platform/gph/build/bundle.sh b/backends/platform/gph/build/gp2xwiz-bundle.sh
index 579e2dc77b..579e2dc77b 100755..100644
--- a/backends/platform/gph/build/bundle.sh
+++ b/backends/platform/gph/build/gp2xwiz-bundle.sh
diff --git a/backends/platform/gph/build/config-alleng.sh b/backends/platform/gph/build/gp2xwiz-config-alleng.sh
index 9ec8a09cd2..9ec8a09cd2 100755..100644
--- a/backends/platform/gph/build/config-alleng.sh
+++ b/backends/platform/gph/build/gp2xwiz-config-alleng.sh
diff --git a/backends/platform/gph/build/config.sh b/backends/platform/gph/build/gp2xwiz-config.sh
index ac7c34ad12..ac7c34ad12 100755..100644
--- a/backends/platform/gph/build/config.sh
+++ b/backends/platform/gph/build/gp2xwiz-config.sh
diff --git a/backends/platform/gph/build/scummvm.png b/backends/platform/gph/build/scummvm.png
deleted file mode 100644
index 128e59efc4..0000000000
--- a/backends/platform/gph/build/scummvm.png
+++ /dev/null
Binary files differ
diff --git a/backends/platform/gph/caanoo-bundle.mk b/backends/platform/gph/caanoo-bundle.mk
index b7b3c9e188..8aabca9028 100755
--- a/backends/platform/gph/caanoo-bundle.mk
+++ b/backends/platform/gph/caanoo-bundle.mk
@@ -14,11 +14,11 @@ caanoo-bundle: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm.gpe $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/caanoo/scummvm.gpe $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
@@ -45,11 +45,11 @@ caanoo-bundle-debug: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
diff --git a/backends/platform/gph/caanoo/clean.sh b/backends/platform/gph/caanoo/clean.sh
deleted file mode 100755
index 5ec1b9e62c..0000000000
--- a/backends/platform/gph/caanoo/clean.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-echo Quick script to make building all the time less painful.
-
-cd ../../../..
-
-echo Cleaning ScummVM for the GP2X Wiz.
-make clean
diff --git a/backends/platform/gph/build/scummvm-gdb.gpe b/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe
index 63ce193ca8..63ce193ca8 100755..100644
--- a/backends/platform/gph/build/scummvm-gdb.gpe
+++ b/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe
diff --git a/backends/platform/gph/caanoo/scummvm.gpe b/backends/platform/gph/devices/caanoo/scummvm.gpe
index 37d0f65d18..37d0f65d18 100755..100644
--- a/backends/platform/gph/caanoo/scummvm.gpe
+++ b/backends/platform/gph/devices/caanoo/scummvm.gpe
diff --git a/backends/platform/gph/build/README-GPH b/backends/platform/gph/devices/common/README-GPH
index 64b9fcb76b..ea196f6649 100644
--- a/backends/platform/gph/build/README-GPH
+++ b/backends/platform/gph/devices/common/README-GPH
@@ -1,4 +1,4 @@
-ScummVM - GPH SPECIFIC README
+ScummVM - GPH DEVICE SPECIFIC README
------------------------------------------------------------------------
Contents:
@@ -29,7 +29,7 @@ control information.
About the backend/port
This is the readme for the official GPH ScummVM backend (also known as
-the GP2X port/GP2XWiz port and Caanoo port).
+the GP2X port/GP2XWiz port or Caanoo port).
This is an SVN test release of ScummVM for GPH devices, it would be
appreciated if this SVN test distribution was not mirrored and that
diff --git a/backends/platform/gph/build/scummvm.ini b/backends/platform/gph/devices/common/scummvm.ini
index c9cce92379..c9cce92379 100644
--- a/backends/platform/gph/build/scummvm.ini
+++ b/backends/platform/gph/devices/common/scummvm.ini
diff --git a/backends/platform/gp2x/build/scummvm.png b/backends/platform/gph/devices/common/scummvm.png
index 128e59efc4..128e59efc4 100644
--- a/backends/platform/gp2x/build/scummvm.png
+++ b/backends/platform/gph/devices/common/scummvm.png
Binary files differ
diff --git a/backends/platform/gph/build/scummvmb.png b/backends/platform/gph/devices/common/scummvmb.png
index 24a27bc0e1..24a27bc0e1 100644
--- a/backends/platform/gph/build/scummvmb.png
+++ b/backends/platform/gph/devices/common/scummvmb.png
Binary files differ
diff --git a/backends/platform/gp2x/mmuhack/Makefile b/backends/platform/gph/devices/gp2x/mmuhack/Makefile
index a35d5c2a98..a35d5c2a98 100644
--- a/backends/platform/gp2x/mmuhack/Makefile
+++ b/backends/platform/gph/devices/gp2x/mmuhack/Makefile
diff --git a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.h b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h
index 520841ace7..520841ace7 100644
--- a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.h
+++ b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h
diff --git a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.s b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s
index 17628c156a..17628c156a 100644
--- a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.s
+++ b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s
diff --git a/backends/platform/gp2x/mmuhack/mmuhack.c b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c
index 7e27262e5f..7e27262e5f 100644
--- a/backends/platform/gp2x/mmuhack/mmuhack.c
+++ b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c
diff --git a/backends/platform/gp2x/build/mmuhack.o b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o
index 475f4a54ae..475f4a54ae 100644
--- a/backends/platform/gp2x/build/mmuhack.o
+++ b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o
Binary files differ
diff --git a/backends/platform/gp2x/mmuhack/readme.txt b/backends/platform/gph/devices/gp2x/mmuhack/readme.txt
index bea49d7d6d..bea49d7d6d 100644
--- a/backends/platform/gp2x/mmuhack/readme.txt
+++ b/backends/platform/gph/devices/gp2x/mmuhack/readme.txt
diff --git a/backends/platform/gp2x/build/scummvm.gpe b/backends/platform/gph/devices/gp2x/scummvm.gpe
index c6b051831c..e8983aa2ce 100755..100644
--- a/backends/platform/gp2x/build/scummvm.gpe
+++ b/backends/platform/gph/devices/gp2x/scummvm.gpe
@@ -3,6 +3,10 @@
# Remount SD with forced Sync, does this really work?
mount -o sync,remount /dev/mmcsd/disc0/part1 /mnt/sd/
+# Export the location of any libs ScummVM depends on
+# (to avoid installing to the NAND and overwriting the broken ones there).
+export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH
+
# Run ScummVM, important this bit.
./scummvm.gph
diff --git a/backends/platform/gph/caanoo/scummvm-gdb.gpe b/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe
index 63ce193ca8..63ce193ca8 100755..100644
--- a/backends/platform/gph/caanoo/scummvm-gdb.gpe
+++ b/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe
diff --git a/backends/platform/gph/build/scummvm.gpe b/backends/platform/gph/devices/gp2xwiz/scummvm.gpe
index 59ff562aeb..59ff562aeb 100755..100644
--- a/backends/platform/gph/build/scummvm.gpe
+++ b/backends/platform/gph/devices/gp2xwiz/scummvm.gpe
diff --git a/backends/platform/gp2x/gp2x-bundle.mk b/backends/platform/gph/gp2x-bundle.mk
index 67d22d1889..810ff8b8f0 100755..100644
--- a/backends/platform/gp2x/gp2x-bundle.mk
+++ b/backends/platform/gph/gp2x-bundle.mk
@@ -1,18 +1,21 @@
# Special target to create bundles for the GP2X.
bundle_name = release/scummvm-gp2x
+f=$(shell which $(STRIP))
+libloc = $(shell dirname $(f))
gp2x-bundle: $(EXECUTABLE)
$(MKDIR) "$(bundle_name)"
$(MKDIR) "$(bundle_name)/saves"
$(MKDIR) "$(bundle_name)/engine-data"
+ $(MKDIR) "$(bundle_name)/lib"
echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/scummvm.gpe $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/
@@ -27,6 +30,8 @@ ifdef DYNAMIC_MODULES
$(STRIP) $(bundle_name)/plugins/*
endif
+ $(CP) $(libloc)/../arm-open2x-linux/lib/libdl.so $(bundle_name)/lib/libdl.so
+
tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 .
rm -R ./$(bundle_name)
@@ -37,10 +42,10 @@ gp2x-bundle-debug: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/
- $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/scummvm.gpe $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/
@@ -54,6 +59,8 @@ ifdef DYNAMIC_MODULES
$(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins"
endif
+ $(CP) $(libloc)/../arm-open2x-linux/lib/libdl.so $(bundle_name)/lib/libdl.so
+
tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 .
rm -R ./$(bundle_name)
diff --git a/backends/platform/gph/gp2xwiz-bundle.mk b/backends/platform/gph/gp2xwiz-bundle.mk
index df4cae7f4f..65e2952fde 100755
--- a/backends/platform/gph/gp2xwiz-bundle.mk
+++ b/backends/platform/gph/gp2xwiz-bundle.mk
@@ -1,6 +1,5 @@
# Special target to create bundles for the GP2X Wiz.
-#bundle_name = release/scummvm-wiz-`date '+%Y-%m-%d'`
bundle_name = release/scummvm-gp2xwiz
f=$(shell which $(STRIP))
libloc = $(shell dirname $(f))
@@ -14,11 +13,11 @@ gp2xwiz-bundle: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.gpe $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2xwiz/scummvm.gpe $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
@@ -48,11 +47,11 @@ gp2xwiz-bundle-debug: $(EXECUTABLE)
echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR"
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/
- $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/
+ $(CP) $(srcdir)/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/
+ $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/
$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/
diff --git a/backends/platform/gph/gph-backend.cpp b/backends/platform/gph/gph-backend.cpp
new file mode 100644
index 0000000000..0432974246
--- /dev/null
+++ b/backends/platform/gph/gph-backend.cpp
@@ -0,0 +1,211 @@
+/* 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.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/platform/sdl/sdl-sys.h"
+
+// #include "backends/platform/gph/gph-options.h"
+#include "backends/platform/gph/gph-sdl.h"
+#include "backends/platform/gph/gph-hw.h"
+#include "backends/plugins/posix/posix-provider.h"
+#include "base/main.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/util.h"
+
+#include "common/file.h"
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+
+#include "backends/timer/default/default-timer.h"
+#include "audio/mixer_intern.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <time.h> // for getTimeAndDate()
+
+/* Dump console info to files. */
+#define DUMP_STDOUT
+
+void OSystem_GPH::initBackend() {
+
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new GPHEventSource();
+
+ // Create the graphics manager
+ if (_graphicsManager == 0) {
+ _graphicsManager = new GPHGraphicsManager(_eventSource);
+ }
+
+ /* Setup default save path to be workingdir/saves */
+
+ char savePath[PATH_MAX+1];
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Could not obtain current working directory");
+ } else {
+ printf("Current working directory: %s\n", workDirName);
+ }
+
+ strcpy(savePath, workDirName);
+ strcat(savePath, "/saves");
+ printf("Current save directory: %s\n", savePath);
+ struct stat sb;
+ if (stat(savePath, &sb) == -1)
+ if (errno == ENOENT) // Create the dir if it does not exist
+ if (mkdir(savePath, 0755) != 0)
+ warning("mkdir for '%s' failed!", savePath);
+
+ _savefileManager = new DefaultSaveFileManager(savePath);
+
+ #ifdef DUMP_STDOUT
+ // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we
+ // output all our STDOUT and STDERR to files for debug purposes.
+ char STDOUT_FILE[PATH_MAX+1];
+ char STDERR_FILE[PATH_MAX+1];
+
+ strcpy(STDOUT_FILE, workDirName);
+ strcpy(STDERR_FILE, workDirName);
+ strcat(STDOUT_FILE, "/scummvm.stdout.txt");
+ strcat(STDERR_FILE, "/scummvm.stderr.txt");
+
+ // Flush the output in case anything is queued
+ fclose(stdout);
+ fclose(stderr);
+
+ // Redirect standard input and standard output
+ FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
+ if (newfp == NULL) {
+ #if !defined(stdout)
+ stdout = fopen(STDOUT_FILE, "w");
+ #else
+ newfp = fopen(STDOUT_FILE, "w");
+ if (newfp) {
+ *stdout = *newfp;
+ }
+ #endif
+ }
+
+ newfp = freopen(STDERR_FILE, "w", stderr);
+ if (newfp == NULL) {
+ #if !defined(stderr)
+ stderr = fopen(STDERR_FILE, "w");
+ #else
+ newfp = fopen(STDERR_FILE, "w");
+ if (newfp) {
+ *stderr = *newfp;
+ }
+ #endif
+ }
+
+ setbuf(stderr, NULL);
+ printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
+ #endif /* DUMP_STDOUT */
+
+ /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */
+ WIZ_HW::deviceInit();
+
+ /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */
+ WIZ_HW::mixerMoveVolume(0);
+
+ /* Up default volume values as we use a seperate system level volume anyway. */
+ ConfMan.registerDefault("music_volume", 192);
+ ConfMan.registerDefault("sfx_volume", 192);
+ ConfMan.registerDefault("speech_volume", 192);
+
+ /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */
+ ConfMan.registerDefault("autosave_period", 4 * 60);
+
+ /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */
+ ConfMan.registerDefault("aspect_ratio", true);
+
+ /* Make sure SDL knows that we have a joystick we want to use. */
+ ConfMan.setInt("joystick_num", 0);
+
+ /* Now setup any device specific user options (Left handed mode, that sort of thing). */
+ // GPH::setOptions();
+
+ printf("%s\n", "Passing to OSystem::SDL initBackend.");
+
+ /* Pass to POSIX method to do the heavy lifting */
+ OSystem_POSIX::initBackend();
+}
+
+void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+
+ /* Setup default extra data paths for engine data files and plugins */
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Error: Could not obtain current working directory");
+ }
+
+ Common::FSNode workdirNode(workDirName);
+ if (workdirNode.exists() && workdirNode.isDirectory()) {
+ s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority);
+ }
+
+ char enginedataPath[PATH_MAX+1];
+
+ strcpy(enginedataPath, workDirName);
+ strcat(enginedataPath, "/engine-data");
+
+ Common::FSNode engineNode(enginedataPath);
+ if (engineNode.exists() && engineNode.isDirectory()) {
+ s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
+ }
+
+ char pluginsPath[PATH_MAX+1];
+
+ strcpy(pluginsPath, workDirName);
+ strcat(pluginsPath, "/plugins");
+
+ Common::FSNode pluginsNode(pluginsPath);
+ if (pluginsNode.exists() && pluginsNode.isDirectory()) {
+ s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority);
+ }
+}
+
+void OSystem_GPH::quit() {
+
+ WIZ_HW::deviceDeinit();
+
+ #ifdef DUMP_STDOUT
+ printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
+ fclose(stdout);
+ fclose(stderr);
+ #endif /* DUMP_STDOUT */
+
+ OSystem_SDL::quit();
+}
diff --git a/backends/platform/gph/gph-main.cpp b/backends/platform/gph/gph-main.cpp
index e711135c15..f91ec8f478 100644
--- a/backends/platform/gph/gph-main.cpp
+++ b/backends/platform/gph/gph-main.cpp
@@ -18,199 +18,34 @@
* 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$
- *
*/
-#include "backends/platform/sdl/sdl-sys.h"
-
-// #include "backends/platform/gph/gph-options.h"
#include "backends/platform/gph/gph-sdl.h"
-#include "backends/platform/gph/gph-hw.h"
-#include "backends/plugins/posix/posix-provider.h"
+#include "backends/plugins/sdl/sdl-provider.h"
#include "base/main.h"
-#include "common/archive.h"
-#include "common/config-manager.h"
-#include "common/debug.h"
-#include "common/events.h"
-#include "common/util.h"
-
-#include "common/file.h"
-#include "base/main.h"
-
-#include "backends/saves/default/default-saves.h"
-
-#include "backends/timer/default/default-timer.h"
-#include "audio/mixer_intern.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h> // for getTimeAndDate()
-
-/* Dump console info to files. */
-#define DUMP_STDOUT
+#if defined(GPH_DEVICE)
int main(int argc, char *argv[]) {
+
+ // Create our OSystem instance
g_system = new OSystem_GPH();
assert(g_system);
+
+ // Pre initialize the backend
+ ((OSystem_GPH *)g_system)->init();
+
#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new POSIXPluginProvider());
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
- g_system->quit();
-
- return res;
-}
-
-void OSystem_GPH::initBackend() {
-
- /* Setup default save path to be workingdir/saves */
-
- char savePath[PATH_MAX+1];
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Could not obtain current working directory");
- } else {
- printf("Current working directory: %s\n", workDirName);
- }
-
- strcpy(savePath, workDirName);
- strcat(savePath, "/saves");
- printf("Current save directory: %s\n", savePath);
- struct stat sb;
- if (stat(savePath, &sb) == -1)
- if (errno == ENOENT) // Create the dir if it does not exist
- if (mkdir(savePath, 0755) != 0)
- warning("mkdir for '%s' failed!", savePath);
-
- _savefile = new DefaultSaveFileManager(savePath);
-
- #ifdef DUMP_STDOUT
- // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we
- // output all our STDOUT and STDERR to files for debug purposes.
- char STDOUT_FILE[PATH_MAX+1];
- char STDERR_FILE[PATH_MAX+1];
-
- strcpy(STDOUT_FILE, workDirName);
- strcpy(STDERR_FILE, workDirName);
- strcat(STDOUT_FILE, "/scummvm.stdout.txt");
- strcat(STDERR_FILE, "/scummvm.stderr.txt");
-
- // Flush the output in case anything is queued
- fclose(stdout);
- fclose(stderr);
-
- // Redirect standard input and standard output
- FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
- if (newfp == NULL) {
- #if !defined(stdout)
- stdout = fopen(STDOUT_FILE, "w");
- #else
- newfp = fopen(STDOUT_FILE, "w");
- if (newfp) {
- *stdout = *newfp;
- }
- #endif
- }
-
- newfp = freopen(STDERR_FILE, "w", stderr);
- if (newfp == NULL) {
- #if !defined(stderr)
- stderr = fopen(STDERR_FILE, "w");
- #else
- newfp = fopen(STDERR_FILE, "w");
- if (newfp) {
- *stderr = *newfp;
- }
- #endif
- }
- setbuf(stderr, NULL);
- printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
- #endif /* DUMP_STDOUT */
+ // Free OSystem
+ delete (OSystem_GPH *)g_system;
- /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */
- WIZ_HW::deviceInit();
-
- /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */
- WIZ_HW::mixerMoveVolume(0);
-
- /* Up default volume values as we use a seperate system level volume anyway. */
- ConfMan.registerDefault("music_volume", 192);
- ConfMan.registerDefault("sfx_volume", 192);
- ConfMan.registerDefault("speech_volume", 192);
-
- /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */
- ConfMan.registerDefault("autosave_period", 4 * 60);
-
- /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */
- ConfMan.registerDefault("aspect_ratio", true);
-
- /* Make sure SDL knows that we have a joystick we want to use. */
- ConfMan.setInt("joystick_num", 0);
-
- /* Now setup any device specific user options (Left handed mode, that sort of thing). */
- // GPH::setOptions();
-
- printf("%s\n", "Passing to OSystem::SDL initBackend.");
-
- /* Pass to SDL backend to do the heavy lifting */
- OSystem_SDL::initBackend();
-}
-
-void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
-
- /* Setup default extra data paths for engine data files and plugins */
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Error: Could not obtain current working directory");
- }
-
- Common::FSNode workdirNode(workDirName);
- if (workdirNode.exists() && workdirNode.isDirectory()) {
- s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority);
- }
-
- char enginedataPath[PATH_MAX+1];
-
- strcpy(enginedataPath, workDirName);
- strcat(enginedataPath, "/engine-data");
-
- Common::FSNode engineNode(enginedataPath);
- if (engineNode.exists() && engineNode.isDirectory()) {
- s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
- }
-
- char pluginsPath[PATH_MAX+1];
-
- strcpy(pluginsPath, workDirName);
- strcat(pluginsPath, "/plugins");
-
- Common::FSNode pluginsNode(pluginsPath);
- if (pluginsNode.exists() && pluginsNode.isDirectory()) {
- s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority);
- }
+ return res;
}
-void OSystem_GPH::quit() {
-
- WIZ_HW::deviceDeinit();
-
- #ifdef DUMP_STDOUT
- printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
- fclose(stdout);
- fclose(stderr);
- #endif /* DUMP_STDOUT */
-
- OSystem_SDL::quit();
-}
+#endif
diff --git a/backends/platform/gph/gph-sdl.h b/backends/platform/gph/gph-sdl.h
index 136363f9a0..51c609d29e 100644
--- a/backends/platform/gph/gph-sdl.h
+++ b/backends/platform/gph/gph-sdl.h
@@ -18,20 +18,18 @@
* 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 GPH_SDL_H
-#define GPH_SDL_H
+#ifndef GPH_H
+#define GPH_H
-#include "backends/platform/sdl/sdl.h"
+#if defined(GPH_DEVICE)
-// FIXME: For now keep hacks in this header to save polluting the SDL backend.
-enum {
- GFX_HALF = 12
-};
+#include "backends/base-backend.h"
+#include "backends/platform/sdl/sdl.h"
+#include "backends/platform/sdl/posix/posix.h"
+#include "backends/graphics/gph/gph-graphics.h"
+#include "backends/events/gph/gph-events.h"
#define __GP2XWIZ__
#define MIXER_DOUBLE_BUFFERING 1
@@ -40,42 +38,13 @@ enum {
#define PATH_MAX 255
#endif
-class OSystem_GPH : public OSystem_SDL {
+class OSystem_GPH : public OSystem_POSIX {
public:
- OSystem_GPH() {}
-
- /* Graphics */
- void initSize(uint w, uint h);
- void setGraphicsModeIntern();
- bool setGraphicsMode(int mode);
- void internUpdateScreen();
- const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
- bool setGraphicsMode(const char *name);
- int getDefaultGraphicsMode() const;
- bool loadGFXMode();
- void drawMouse();
- void undrawMouse();
- void showOverlay();
- void hideOverlay();
-
- /* Event Stuff */
- void moveStick();
- void fillMouseEvent(Common::Event&, int, int);
- void warpMouse(int, int);
- bool remapKey(SDL_Event&, Common::Event&);
-
/* Platform Setup Stuff */
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
void initBackend();
void quit();
-
-protected:
- bool _stickBtn[32];
-
- bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
- bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
- bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
- bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
};
-#endif //GPH_SDL_H
+#endif
+#endif //GPH_H
diff --git a/backends/platform/gph/module.mk b/backends/platform/gph/module.mk
index f5567f581e..a9951494d1 100644
--- a/backends/platform/gph/module.mk
+++ b/backends/platform/gph/module.mk
@@ -1,10 +1,9 @@
MODULE := backends/platform/gph
MODULE_OBJS := \
- gph-events.o \
- gph-graphics.o \
- gph-hw.o \
- gph-main.o
+ gph-main.o \
+ gph-backend.o \
+ gph-hw.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/iphone/osys_video.cpp b/backends/platform/iphone/osys_video.cpp
index ee27e4d87c..d67d38932a 100644
--- a/backends/platform/iphone/osys_video.cpp
+++ b/backends/platform/iphone/osys_video.cpp
@@ -102,7 +102,7 @@ void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) {
for (uint i = start; i < start + num; ++i) {
_palette[i] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(b[0], b[1], b[2]);
- b += 4;
+ b += 3;
}
dirtyFullScreen();
@@ -114,8 +114,7 @@ void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) {
for (uint i = start; i < start + num; ++i) {
Graphics::colorToRGB<Graphics::ColorMasks<565> >(_palette[i], b[0], b[1], b[2]);
- b[3] = 0xFF;
- b += 4;
+ b += 3;
}
}
diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h
index 5264a8a82e..2daa41a9f6 100644
--- a/backends/platform/n64/osys_n64.h
+++ b/backends/platform/n64/osys_n64.h
@@ -93,7 +93,7 @@ protected:
uint16 *_screenPalette; // Array for palette entries (256 colors max)
#ifndef N64_EXTREME_MEMORY_SAVING
- uint32 *_screenExactPalette; // Array for palette entries, as received by setPalette(), no precision loss
+ uint8 *_screenExactPalette; // Array for palette entries, as received by setPalette(), no precision loss
#endif
uint16 _cursorPalette[256]; // Palette entries for the cursor
@@ -111,7 +111,10 @@ protected:
bool _cursorPaletteDisabled;
bool _dirtyPalette;
- uint _cursorWidth, _cursorHeight;
+ // FIXME: This must be left as "int" for now, to fix the sign-comparison problem
+ // there is a little more work involved than an int->uint change
+ int _cursorWidth, _cursorHeight;
+
int _cursorKeycolor;
uint16 _overlayHeight, _overlayWidth;
diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp
index 1b9c704225..54eab0fd52 100644
--- a/backends/platform/n64/osys_n64_base.cpp
+++ b/backends/platform/n64/osys_n64_base.cpp
@@ -113,8 +113,8 @@ OSystem_N64::OSystem_N64() {
// Clear palette array
_screenPalette = (uint16*)memalign(8, 256 * sizeof(uint16));
#ifndef N64_EXTREME_MEMORY_SAVING
- _screenExactPalette = (uint32*)memalign(8, 256 * sizeof(uint32));
- memset(_screenExactPalette, 0, 256 * sizeof(uint32));
+ _screenExactPalette = (uint8*)memalign(8, 256 * 3);
+ memset(_screenExactPalette, 0, 256 * 3);
#endif
memset(_screenPalette, 0, 256 * sizeof(uint16));
memset(_cursorPalette, 0, 256 * sizeof(uint16));
@@ -350,12 +350,13 @@ int16 OSystem_N64::getWidth() {
}
void OSystem_N64::setPalette(const byte *colors, uint start, uint num) {
- for (uint i = 0; i < num; ++i) {
- _screenPalette[start + i] = colRGB888toBGR555(colors[2], colors[1], colors[0]);
#ifndef N64_EXTREME_MEMORY_SAVING
- _screenExactPalette[start + i] = *((uint32*)(colors));
+ memcpy(_screenExactPalette + start * 3, colors, num * 3);
#endif
- colors += 4;
+
+ for (uint i = 0; i < num; ++i) {
+ _screenPalette[start + i] = colRGB888toBGR555(colors[2], colors[1], colors[0]);
+ colors += 3;
}
// If cursor uses the game palette, we need to rebuild the hicolor buffer
@@ -413,10 +414,9 @@ void OSystem_N64::grabPalette(byte *colors, uint start, uint num) {
*colors++ = ((color & 0x1F) << 3);
*colors++ = (((color >> 5) & 0x1F) << 3);
*colors++ = (((color >> 10) & 0x1F) << 3);
- *colors++ = 0;
}
#else
- memcpy(colors, (uint8*)(_screenExactPalette + start), num * 4);
+ memcpy(colors, _screenExactPalette + start * 3, num * 3);
#endif
return;
@@ -425,7 +425,7 @@ void OSystem_N64::grabPalette(byte *colors, uint start, uint num) {
void OSystem_N64::setCursorPalette(const byte *colors, uint start, uint num) {
for (uint i = 0; i < num; ++i) {
_cursorPalette[start + i] = colRGB888toBGR555(colors[2], colors[1], colors[0]);
- colors += 4;
+ colors += 3;
}
_cursorPaletteDisabled = false;
diff --git a/backends/platform/n64/osys_n64_events.cpp b/backends/platform/n64/osys_n64_events.cpp
index 9a53051d3d..22b9addbfb 100644
--- a/backends/platform/n64/osys_n64_events.cpp
+++ b/backends/platform/n64/osys_n64_events.cpp
@@ -118,9 +118,9 @@ void OSystem_N64::readControllerAnalogInput(void) {
// Gamepad
if (abs(pad_analogX) > PAD_DEADZONE)
- mx += tan(pad_analogX * (PI / 140));
+ mx += tan(pad_analogX * (M_PI / 140));
if (abs(pad_analogY) > PAD_DEADZONE)
- my -= tan(pad_analogY * (PI / 140));
+ my -= tan(pad_analogY * (M_PI / 140));
// Mouse
if (abs(pad_mouseX) > MOUSE_DEADZONE)
diff --git a/backends/platform/openpandora/module.mk b/backends/platform/openpandora/module.mk
index 1e5f6bcd69..8e60b87aa6 100755
--- a/backends/platform/openpandora/module.mk
+++ b/backends/platform/openpandora/module.mk
@@ -1,9 +1,8 @@
MODULE := backends/platform/openpandora
MODULE_OBJS := \
- op-graphics.o \
- op-events.o \
op-options.o \
+ op-backend.o \
op-main.o
MODULE_DIRS += \
diff --git a/backends/platform/openpandora/op-backend.cpp b/backends/platform/openpandora/op-backend.cpp
new file mode 100644
index 0000000000..5b333929c9
--- /dev/null
+++ b/backends/platform/openpandora/op-backend.cpp
@@ -0,0 +1,273 @@
+/* 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.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/platform/openpandora/op-sdl.h"
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/util.h"
+
+#include "common/file.h"
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+
+#include "backends/timer/default/default-timer.h"
+#include "audio/mixer_intern.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <time.h> // for getTimeAndDate()
+
+/* Dump console info to files. */
+#define DUMP_STDOUT
+
+static SDL_Cursor *hiddenCursor;
+
+static Uint32 timer_handler(Uint32 interval, void *param) {
+ ((DefaultTimerManager *)param)->handler();
+ return interval;
+}
+
+void OSystem_OP::initBackend() {
+
+ assert(!_inited);
+
+// int joystick_num = ConfMan.getInt("joystick_num");
+// uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
+//
+// if (ConfMan.hasKey("disable_sdl_parachute"))
+// sdlFlags |= SDL_INIT_NOPARACHUTE;
+//
+// if (joystick_num > -1)
+// sdlFlags |= SDL_INIT_JOYSTICK;
+//
+// if (SDL_Init(sdlFlags) == -1) {
+// error("Could not initialize SDL: %s", SDL_GetError());
+// }
+//
+
+ /* Setup default save path to be workingdir/saves */
+
+ char savePath[PATH_MAX+1];
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Could not obtain current working directory.");
+ } else {
+ printf("Current working directory: %s\n", workDirName);
+ }
+
+ strcpy(savePath, workDirName);
+ strcat(savePath, "/../saves");
+ printf("Current save directory: %s\n", savePath);
+ struct stat sb;
+ if (stat(savePath, &sb) == -1)
+ if (errno == ENOENT) // Create the dir if it does not exist
+ if (mkdir(savePath, 0755) != 0)
+ warning("mkdir for '%s' failed!", savePath);
+
+// _savefileManager = new DefaultSaveFileManager(savePath);
+
+ #ifdef DUMP_STDOUT
+ // The OpenPandora has a serial console on the EXT connection but most users do not use this so we
+ // output all our STDOUT and STDERR to files for debug purposes.
+ char STDOUT_FILE[PATH_MAX+1];
+ char STDERR_FILE[PATH_MAX+1];
+
+ strcpy(STDOUT_FILE, workDirName);
+ strcpy(STDERR_FILE, workDirName);
+ strcat(STDOUT_FILE, "/scummvm.stdout.txt");
+ strcat(STDERR_FILE, "/scummvm.stderr.txt");
+
+ // Flush the output in case anything is queued
+ fclose(stdout);
+ fclose(stderr);
+
+ // Redirect standard input and standard output
+ FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
+ if (newfp == NULL) {
+ #if !defined(stdout)
+ stdout = fopen(STDOUT_FILE, "w");
+ #else
+ newfp = fopen(STDOUT_FILE, "w");
+ if (newfp) {
+ *stdout = *newfp;
+ }
+ #endif
+ }
+
+ newfp = freopen(STDERR_FILE, "w", stderr);
+ if (newfp == NULL) {
+ #if !defined(stderr)
+ stderr = fopen(STDERR_FILE, "w");
+ #else
+ newfp = fopen(STDERR_FILE, "w");
+ if (newfp) {
+ *stderr = *newfp;
+ }
+ #endif
+ }
+
+ setbuf(stderr, NULL);
+ printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
+ #endif /* DUMP_STDOUT */
+
+ /* Trigger autosave every 4 minutes. */
+ ConfMan.registerDefault("autosave_period", 4 * 60);
+
+ ConfMan.registerDefault("fullscreen", true);
+
+ /* Make sure that aspect ratio correction is enabled on the 1st run to stop
+ users asking me what the 'wasted space' at the bottom is ;-). */
+ ConfMan.registerDefault("aspect_ratio", true);
+
+ /* Make sure SDL knows that we have a joystick we want to use. */
+ ConfMan.setInt("joystick_num", 0);
+
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new OPEventSource();
+
+ // Create the graphics manager
+ if (_graphicsManager == 0)
+ _graphicsManager = new OPGraphicsManager(_eventSource);
+
+// _graphicsMutex = createMutex();
+
+ // Invoke parent implementation of this method
+ OSystem_POSIX::initBackend();
+
+ _inited = true;
+}
+
+
+
+ // enable joystick
+// if (joystick_num > -1 && SDL_NumJoysticks() > 0) {
+// printf("Using joystick: %s\n", SDL_JoystickName(0));
+// _joystick = SDL_JoystickOpen(joystick_num);
+// }
+//
+// setupMixer();
+
+ // Note: We could implement a custom SDLTimerManager by using
+ // SDL_AddTimer. That might yield better timer resolution, but it would
+ // also change the semantics of a timer: Right now, ScummVM timers
+ // *never* run in parallel, due to the way they are implemented. If we
+ // switched to SDL_AddTimer, each timer might run in a separate thread.
+ // However, not all our code is prepared for that, so we can't just
+ // switch. Still, it's a potential future change to keep in mind.
+// _timer = new DefaultTimerManager();
+// _timerID = SDL_AddTimer(10, &timer_handler, _timer);
+
+void OSystem_OP::initSDL() {
+ // Check if SDL has not been initialized
+ if (!_initedSDL) {
+
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ if (ConfMan.hasKey("disable_sdl_parachute"))
+ sdlFlags |= SDL_INIT_NOPARACHUTE;
+
+ // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
+ if (SDL_Init(sdlFlags) == -1)
+ error("Could not initialize SDL: %s", SDL_GetError());
+
+ uint8_t hiddenCursorData = 0;
+
+ hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0);
+
+ /* On the OpenPandora we need to work around an SDL assumption that
+ returns relative mouse coordinates when you get to the screen
+ edges using the touchscreen. The workaround is to set a blank
+ SDL cursor and not disable it (Hackish I know).
+
+ The root issues likes in the Windows Manager GRAB code in SDL.
+ That is why the issue is not seen on framebuffer devices like the
+ GP2X (there is no X window manager ;)).
+ */
+ SDL_ShowCursor(SDL_ENABLE);
+ SDL_SetCursor(hiddenCursor);
+ SDL_EnableUNICODE(1);
+
+// memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
+// memset(&_videoMode, 0, sizeof(_videoMode));
+// memset(&_transactionDetails, 0, sizeof(_transactionDetails));
+
+// _videoMode.mode = GFX_DOUBLESIZE;
+// _videoMode.scaleFactor = 2;
+// _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
+// _scalerProc = Normal2x;
+// _scalerType = 0;
+
+// _videoMode.fullscreen = true;
+
+ _initedSDL = true;
+ }
+}
+
+void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+
+ /* Setup default extra data paths for engine data files and plugins */
+
+ char workDirName[PATH_MAX+1];
+
+ if (getcwd(workDirName, PATH_MAX) == NULL) {
+ error("Error: Could not obtain current working directory.");
+ }
+
+ char enginedataPath[PATH_MAX+1];
+
+ strcpy(enginedataPath, workDirName);
+ strcat(enginedataPath, "/../data");
+ printf("Default engine data directory: %s\n", enginedataPath);
+
+ Common::FSNode engineNode(enginedataPath);
+ if (engineNode.exists() && engineNode.isDirectory()) {
+ s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
+ }
+}
+
+void OSystem_OP::quit() {
+
+ SDL_FreeCursor(hiddenCursor);
+
+ #ifdef DUMP_STDOUT
+ printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
+ fclose(stdout);
+ fclose(stderr);
+ #endif /* DUMP_STDOUT */
+
+ OSystem_POSIX::quit();
+}
diff --git a/backends/platform/openpandora/op-main.cpp b/backends/platform/openpandora/op-main.cpp
index 6e64baddc7..ab777fec8f 100644
--- a/backends/platform/openpandora/op-main.cpp
+++ b/backends/platform/openpandora/op-main.cpp
@@ -18,250 +18,36 @@
* 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$
- *
*/
-// Disable symbol overrides so that we can use system headers.
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/sdl-sys.h"
-
#include "backends/platform/openpandora/op-sdl.h"
#include "backends/plugins/posix/posix-provider.h"
#include "base/main.h"
-#include "common/archive.h"
-#include "common/config-manager.h"
-#include "common/debug.h"
-#include "common/events.h"
-#include "common/util.h"
-
-#include "common/file.h"
-#include "base/main.h"
-
-#include "backends/saves/default/default-saves.h"
-
-#include "backends/timer/default/default-timer.h"
-#include "audio/mixer_intern.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h> // for getTimeAndDate()
-
-/* Dump console info to files. */
-#define DUMP_STDOUT
-
-static SDL_Cursor *hiddenCursor;
+#if defined(OPENPANDORA)
int main(int argc, char *argv[]) {
+
+ // Create our OSystem instance
g_system = new OSystem_OP();
assert(g_system);
+ // Pre initialize the backend
+ //((OSystem_OP *)g_system)->init();
+
#ifdef DYNAMIC_MODULES
PluginManager::instance().addPluginProvider(new POSIXPluginProvider());
#endif
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
- g_system->quit();
-
- return res;
-}
-
-static Uint32 timer_handler(Uint32 interval, void *param) {
- ((DefaultTimerManager *)param)->handler();
- return interval;
-}
-
-void OSystem_OP::initBackend() {
-
- assert(!_inited);
-
- uint8_t hiddenCursorData = 0;
-
- int joystick_num = ConfMan.getInt("joystick_num");
- uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
-
- if (ConfMan.hasKey("disable_sdl_parachute"))
- sdlFlags |= SDL_INIT_NOPARACHUTE;
-
- if (joystick_num > -1)
- sdlFlags |= SDL_INIT_JOYSTICK;
-
- if (SDL_Init(sdlFlags) == -1) {
- error("Could not initialize SDL: %s", SDL_GetError());
- }
-
- hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0);
-
- /* Setup default save path to be workingdir/saves */
-
- char savePath[PATH_MAX+1];
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Could not obtain current working directory.");
- } else {
- printf("Current working directory: %s\n", workDirName);
- }
-
- strcpy(savePath, workDirName);
- strcat(savePath, "/../saves");
- printf("Current save directory: %s\n", savePath);
- struct stat sb;
- if (stat(savePath, &sb) == -1)
- if (errno == ENOENT) // Create the dir if it does not exist
- if (mkdir(savePath, 0755) != 0)
- warning("mkdir for '%s' failed!", savePath);
-
- _savefile = new DefaultSaveFileManager(savePath);
-
- #ifdef DUMP_STDOUT
- // The OpenPandora has a serial console on the EXT connection but most users do not use this so we
- // output all our STDOUT and STDERR to files for debug purposes.
- char STDOUT_FILE[PATH_MAX+1];
- char STDERR_FILE[PATH_MAX+1];
-
- strcpy(STDOUT_FILE, workDirName);
- strcpy(STDERR_FILE, workDirName);
- strcat(STDOUT_FILE, "/scummvm.stdout.txt");
- strcat(STDERR_FILE, "/scummvm.stderr.txt");
-
- // Flush the output in case anything is queued
- fclose(stdout);
- fclose(stderr);
- // Redirect standard input and standard output
- FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
- if (newfp == NULL) {
- #if !defined(stdout)
- stdout = fopen(STDOUT_FILE, "w");
- #else
- newfp = fopen(STDOUT_FILE, "w");
- if (newfp) {
- *stdout = *newfp;
- }
- #endif
- }
+ // Free OSystem
+ delete (OSystem_OP *)g_system;
- newfp = freopen(STDERR_FILE, "w", stderr);
- if (newfp == NULL) {
- #if !defined(stderr)
- stderr = fopen(STDERR_FILE, "w");
- #else
- newfp = fopen(STDERR_FILE, "w");
- if (newfp) {
- *stderr = *newfp;
- }
- #endif
- }
-
- setbuf(stderr, NULL);
- printf("%s\n", "Debug: STDOUT and STDERR redirected to text files.");
- #endif /* DUMP_STDOUT */
-
- /* Trigger autosave every 4 minutes. */
- ConfMan.registerDefault("autosave_period", 4 * 60);
-
- ConfMan.registerDefault("fullscreen", true);
-
- /* Make sure that aspect ratio correction is enabled on the 1st run to stop
- users asking me what the 'wasted space' at the bottom is ;-). */
- ConfMan.registerDefault("aspect_ratio", true);
-
- /* Make sure SDL knows that we have a joystick we want to use. */
- ConfMan.setInt("joystick_num", 0);
-
- _graphicsMutex = createMutex();
-
- /* On the OpenPandora we need to work around an SDL assumption that
- returns relative mouse coordinates when you get to the screen
- edges using the touchscreen. The workaround is to set a blank
- SDL cursor and not disable it (Hackish I know).
-
- The root issues likes in the Windows Manager GRAB code in SDL.
- That is why the issue is not seen on framebuffer devices like the
- GP2X (there is no X window manager ;)).
- */
- SDL_ShowCursor(SDL_ENABLE);
- SDL_SetCursor(hiddenCursor);
-
- // Enable unicode support if possible
- SDL_EnableUNICODE(1);
-
- memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
- memset(&_videoMode, 0, sizeof(_videoMode));
- memset(&_transactionDetails, 0, sizeof(_transactionDetails));
-
- _videoMode.mode = GFX_DOUBLESIZE;
- _videoMode.scaleFactor = 2;
- _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
- _scalerProc = Normal2x;
- _scalerType = 0;
-
- _videoMode.fullscreen = true;
-
- // enable joystick
- if (joystick_num > -1 && SDL_NumJoysticks() > 0) {
- printf("Using joystick: %s\n", SDL_JoystickName(0));
- _joystick = SDL_JoystickOpen(joystick_num);
- }
-
- setupMixer();
-
- // Note: We could implement a custom SDLTimerManager by using
- // SDL_AddTimer. That might yield better timer resolution, but it would
- // also change the semantics of a timer: Right now, ScummVM timers
- // *never* run in parallel, due to the way they are implemented. If we
- // switched to SDL_AddTimer, each timer might run in a separate thread.
- // However, not all our code is prepared for that, so we can't just
- // switch. Still, it's a potential future change to keep in mind.
- _timer = new DefaultTimerManager();
- _timerID = SDL_AddTimer(10, &timer_handler, _timer);
-
- // Invoke parent implementation of this method
- OSystem::initBackend();
-
- _inited = true;
-}
-
-void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
-
- /* Setup default extra data paths for engine data files and plugins */
-
- char workDirName[PATH_MAX+1];
-
- if (getcwd(workDirName, PATH_MAX) == NULL) {
- error("Error: Could not obtain current working directory.");
- }
-
- char enginedataPath[PATH_MAX+1];
-
- strcpy(enginedataPath, workDirName);
- strcat(enginedataPath, "/../data");
- printf("Default engine data directory: %s\n", enginedataPath);
-
- Common::FSNode engineNode(enginedataPath);
- if (engineNode.exists() && engineNode.isDirectory()) {
- s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority);
- }
+ return res;
}
-void OSystem_OP::quit() {
-
- SDL_FreeCursor(hiddenCursor);
-
- #ifdef DUMP_STDOUT
- printf("%s\n", "Debug: STDOUT and STDERR text files closed.");
- fclose(stdout);
- fclose(stderr);
- #endif /* DUMP_STDOUT */
-
- OSystem_SDL::quit();
-}
+#endif
diff --git a/backends/platform/openpandora/op-sdl.h b/backends/platform/openpandora/op-sdl.h
index 8561b42498..93c82ca397 100644
--- a/backends/platform/openpandora/op-sdl.h
+++ b/backends/platform/openpandora/op-sdl.h
@@ -18,15 +18,18 @@
* 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 OP_SDL_H
#define OP_SDL_H
+#if defined(OPENPANDORA)
+
+#include "backends/base-backend.h"
#include "backends/platform/sdl/sdl.h"
+#include "backends/platform/sdl/posix/posix.h"
+#include "backends/events/openpandora/op-events.h"
+#include "backends/graphics/openpandora/op-graphics.h"
#define __OPENPANDORA__
#define MIXER_DOUBLE_BUFFERING 1
@@ -35,25 +38,18 @@
#define PATH_MAX 255
#endif
-class OSystem_OP : public OSystem_SDL {
+class OSystem_OP : public OSystem_POSIX {
public:
OSystem_OP() {}
- /* Events */
- bool handleKeyDown(SDL_Event &ev, Common::Event &event);
- bool handleKeyUp(SDL_Event &ev, Common::Event &event);
- bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
- bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
-
- /* Graphics */
- bool loadGFXMode();
-
/* Platform Setup Stuff */
void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
void initBackend();
+ void initSDL();
void quit();
protected:
};
#endif
+#endif //OP_SDL_H
diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp
index c6318e73d0..a460b919fd 100644
--- a/backends/platform/ps2/Gs2dScreen.cpp
+++ b/backends/platform/ps2/Gs2dScreen.cpp
@@ -408,25 +408,33 @@ void Gs2dScreen::unlockScreen() {
SignalSema(g_DmacSema);
}
-void Gs2dScreen::setPalette(const uint32 *pal, uint8 start, uint16 num) {
+void Gs2dScreen::setPalette(const uint8 *pal, uint8 start, uint16 num) {
assert(start + num <= 256);
WaitSema(g_DmacSema);
for (uint16 cnt = 0; cnt < num; cnt++) {
uint16 dest = start + cnt;
dest = (dest & 0xE7) | ((dest & 0x8) << 1) | ((dest & 0x10) >> 1); // rearrange like the GS expects it
- _clut[dest] = pal[cnt] & 0xFFFFFF;
+
+ uint32 color = pal[0] | (pal[1] << 8) | (pal[2] << 16);
+ _clut[dest] = color;
+ pal += 3;
}
_clutChanged = true;
SignalSema(g_DmacSema);
}
-void Gs2dScreen::grabPalette(uint32 *pal, uint8 start, uint16 num) {
+void Gs2dScreen::grabPalette(uint8 *pal, uint8 start, uint16 num) {
assert(start + num <= 256);
for (uint16 cnt = 0; cnt < num; cnt++) {
uint16 src = start + cnt;
src = (src & 0xE7) | ((src & 0x8) << 1) | ((src & 0x10) >> 1);
- pal[cnt] = _clut[src];
+
+ uint32 color = _clut[src];
+ pal[0] = (color >> 0) & 0xFF;
+ pal[1] = (color >> 8) & 0xFF;
+ pal[2] = (color >> 16) & 0xFF;
+ pal += 3;
}
}
@@ -672,7 +680,7 @@ void Gs2dScreen::animThread(void) {
{ SCALE(1), SCALE(1) }, { SCALE(1), SCALE(14) },
{ SCALE(128), SCALE(1) }, { SCALE(128), SCALE(14) }
};
- float angleStep = ((2 * PI) / _tvHeight);
+ float angleStep = ((2 * M_PI) / _tvHeight);
while (!_systemQuit) {
do {
@@ -731,7 +739,7 @@ void Gs2dScreen::animThread(void) {
float z[4];
GsVertex nodes[4];
- float angle = PI / 2 + angleStep * drawY;
+ float angle = M_PI / 2 + angleStep * drawY;
float rotSin = sinf(angle);
float rotCos = cosf(angle);
for (int coord = 0; coord < 4; coord++) {
diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h
index 81f47d5f4a..358e717cbe 100644
--- a/backends/platform/ps2/Gs2dScreen.h
+++ b/backends/platform/ps2/Gs2dScreen.h
@@ -65,9 +65,9 @@ public:
void unlockScreen();
void copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w, int h);
- void setPalette(const uint32 *pal, uint8 start, uint16 num);
+ void setPalette(const uint8 *pal, uint8 start, uint16 num);
void updateScreen(void);
- void grabPalette(uint32 *pal, uint8 start, uint16 num);
+ void grabPalette(uint8 *pal, uint8 start, uint16 num);
void grabScreen(Graphics::Surface *surf);
//- overlay routines
void copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index ab7839e18f..77de74eb5b 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -544,11 +544,11 @@ void OSystem_PS2::initSize(uint width, uint height, const Graphics::PixelFormat
}
void OSystem_PS2::setPalette(const byte *colors, uint start, uint num) {
- _screen->setPalette((const uint32*)colors, (uint8)start, (uint16)num);
+ _screen->setPalette(colors, (uint8)start, (uint16)num);
}
void OSystem_PS2::grabPalette(byte *colors, uint start, uint num) {
- _screen->grabPalette((uint32*)colors, (uint8)start, (uint16)num);
+ _screen->grabPalette(colors, (uint8)start, (uint16)num);
}
void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP
index 7a3cce2b75..b520022033 100644
--- a/backends/platform/psp/README.PSP
+++ b/backends/platform/psp/README.PSP
@@ -1,4 +1,4 @@
-ScummVM-PSP 1.3.0svn README
+ScummVM-PSP 1.3.0git README
==============================================================================
Installation
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp
index 82e2d17d10..76b4a28e4a 100644
--- a/backends/platform/psp/display_client.cpp
+++ b/backends/platform/psp/display_client.cpp
@@ -110,7 +110,7 @@ void Palette::setPartial(const byte *colors, uint32 start, uint32 num, bool supp
for (uint32 i = 0; i < num; ++i) {
byte alphaVal = supportsAlpha ? src[3] : 0xFF;
*palette = (uint16)_pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal);
- src += 4;
+ src += 3;
palette++;
}
} else if (_pixelFormat.bitsPerPixel == 32) {
@@ -120,7 +120,7 @@ void Palette::setPartial(const byte *colors, uint32 start, uint32 num, bool supp
for (uint32 i = 0; i < num; ++i) {
byte alphaVal = supportsAlpha ? src[3] : 0xFF;
*palette = _pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal);
- src += 4;
+ src += 3;
palette++;
}
}
@@ -214,7 +214,6 @@ void Palette::getPartial(byte *colors, uint start, uint num) {
*colors++ = (byte)r;
*colors++ = (byte)g;
*colors++ = (byte)b;
- *colors++ = (byte)a;
palette++;
}
} else if (_pixelFormat.bitsPerPixel == 32) {
@@ -227,7 +226,6 @@ void Palette::getPartial(byte *colors, uint start, uint num) {
*colors++ = (byte)r;
*colors++ = (byte)g;
*colors++ = (byte)b;
- *colors++ = (byte)a;
palette++;
}
}
diff --git a/backends/platform/sdl/posix/posix-main.cpp b/backends/platform/sdl/posix/posix-main.cpp
index 10ed43f43f..9e778ab899 100644
--- a/backends/platform/sdl/posix/posix-main.cpp
+++ b/backends/platform/sdl/posix/posix-main.cpp
@@ -25,7 +25,7 @@
#include "common/scummsys.h"
-#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(LINUXMOTO) && !defined(GP2XWIZ) && !defined(GP2X) && !defined(DINGUX)
+#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA)
#include "backends/platform/sdl/posix/posix.h"
#include "backends/plugins/sdl/sdl-provider.h"
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index dc91bd9fe7..d6e79248f9 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -125,10 +125,10 @@ void OSystem_SDL::init() {
if (_timerManager == 0)
_timerManager = new SdlTimerManager();
- #ifdef USE_OPENGL
- // Setup a list with both SDL and OpenGL graphics modes
- setupGraphicsModes();
- #endif
+#ifdef USE_OPENGL
+ // Setup a list with both SDL and OpenGL graphics modes
+ setupGraphicsModes();
+#endif
}
void OSystem_SDL::initBackend() {
@@ -148,11 +148,15 @@ void OSystem_SDL::initBackend() {
Common::String gfxMode(ConfMan.get("gfx_mode"));
bool use_opengl = false;
const OSystem::GraphicsMode *mode = OpenGLSdlGraphicsManager::supportedGraphicsModes();
+ int i = 0;
while (mode->name) {
- if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0)
+ if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0) {
+ _graphicsMode = i + _sdlModesCount;
use_opengl = true;
+ }
mode++;
+ ++i;
}
// If the gfx_mode is from OpenGL, create the OpenGL graphics manager
@@ -210,6 +214,11 @@ void OSystem_SDL::initSDL() {
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
+#ifdef WEBOS
+ // WebOS needs this flag or otherwise the application won't start
+ sdlFlags |= SDL_INIT_VIDEO;
+#endif
+
// Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
if (SDL_Init(sdlFlags) == -1)
error("Could not initialize SDL: %s", SDL_GetError());
@@ -464,6 +473,7 @@ int OSystem_SDL::getDefaultGraphicsMode() const {
bool OSystem_SDL::setGraphicsMode(int mode) {
const OSystem::GraphicsMode *srcMode;
int i;
+
// Check if mode is from SDL or OpenGL
if (mode < _sdlModesCount) {
srcMode = SdlGraphicsManager::supportedGraphicsModes();
@@ -472,28 +482,34 @@ bool OSystem_SDL::setGraphicsMode(int mode) {
srcMode = OpenGLSdlGraphicsManager::supportedGraphicsModes();
i = _sdlModesCount;
}
+
// Loop through modes
while (srcMode->name) {
if (i == mode) {
// If the new mode and the current mode are not from the same graphics
// manager, delete and create the new mode graphics manager
if (_graphicsMode >= _sdlModesCount && mode < _sdlModesCount) {
+ debug(1, "switching to plain SDL graphics");
delete _graphicsManager;
_graphicsManager = new SdlGraphicsManager(_eventSource);
((SdlGraphicsManager *)_graphicsManager)->initEventObserver();
_graphicsManager->beginGFXTransaction();
} else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) {
+ debug(1, "switching to OpenGL graphics");
delete _graphicsManager;
_graphicsManager = new OpenGLSdlGraphicsManager();
((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver();
_graphicsManager->beginGFXTransaction();
}
+
_graphicsMode = mode;
return _graphicsManager->setGraphicsMode(srcMode->id);
}
+
i++;
srcMode++;
}
+
return false;
}
diff --git a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
index c7623d09a8..12b4cb3610 100644
--- a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
+++ b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in
@@ -91,7 +91,7 @@ STATICLIBRARY esdl.lib
// *** Include paths
USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\engines
-USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\sound
+USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio
SYSTEMINCLUDE \epoc32\include\ESDL
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
index 6f14e858b0..9af6535b22 100644
--- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
+++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
@@ -91,7 +91,7 @@ STATICLIBRARY esdl.lib
// *** Include paths
USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\engines
-USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\sound
+USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio
SYSTEMINCLUDE \epoc32\include\ESDL
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
diff --git a/backends/platform/symbian/mmp/scummvm_agi.mmp.in b/backends/platform/symbian/mmp/scummvm_agi.mmp.in
index 044326405d..e2d98b9ae4 100644
--- a/backends/platform/symbian/mmp/scummvm_agi.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_agi.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\agi
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_agos.mmp.in b/backends/platform/symbian/mmp/scummvm_agos.mmp.in
index e2d1e5eff4..077111d783 100644
--- a/backends/platform/symbian/mmp/scummvm_agos.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_agos.mmp.in
@@ -65,6 +65,6 @@ SOURCEPATH ..\..\..\..\engines\agos
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in
index d25cef4ffe..b3bfbab530 100644
--- a/backends/platform/symbian/mmp/scummvm_base.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in
@@ -51,7 +51,7 @@ ALWAYS_BUILD_AS_ARM
// *** Include paths
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio
USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl
SYSTEMINCLUDE \epoc32\include\ESDL
@@ -95,7 +95,7 @@ SOURCEPATH ..\..\..\..\gui
//SOURCE KeysDialog.cpp
//SOURCE Actions.cpp
-SOURCEPATH ..\..\..\..\sound
+SOURCEPATH ..\..\..\..\audio
//START_AUTO_OBJECTS_SOUND_//
// empty base file, will be updated by Perl build scripts
@@ -110,6 +110,12 @@ SOURCE rate_arm.cpp // ARM version: add ASM .cpp wrapper
SOURCE rate_arm_asm.s // ARM version: add ASM routines
#endif
+SOURCEPATH ..\..\..\..\video
+//START_AUTO_OBJECTS_VIDEO_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_VIDEO_//
// add a few files manually, since they are not parsed from modules.mk files
SOURCEPATH ..\..\..\..
diff --git a/backends/platform/symbian/mmp/scummvm_cine.mmp.in b/backends/platform/symbian/mmp/scummvm_cine.mmp.in
index d114ec554b..2c8118ef13 100644
--- a/backends/platform/symbian/mmp/scummvm_cine.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_cine.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\cine
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in
index e4c836a68b..b43a867da3 100644
--- a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\cruise
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_draci.mmp.in b/backends/platform/symbian/mmp/scummvm_draci.mmp.in
index b10eb0b5a8..9f24927f27 100644
--- a/backends/platform/symbian/mmp/scummvm_draci.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_draci.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\draci
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in
index 529eeb9e0b..d8cc6da6ae 100644
--- a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\drascula
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_gob.mmp.in b/backends/platform/symbian/mmp/scummvm_gob.mmp.in
index fa2ce0dedf..ce94f85283 100644
--- a/backends/platform/symbian/mmp/scummvm_gob.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_gob.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\gob
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in
index 7a03cc1745..7229edf4aa 100644
--- a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\groovie
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in
index 301d23cab4..b3f9edd1e6 100644
--- a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\hugo
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
index 5fa5fdac6a..654632c229 100644
--- a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in
@@ -65,5 +65,5 @@ SOURCEPATH ..\..\..\..\engines\kyra
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
index a297137f02..418730c064 100644
--- a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\lastexpress
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_lure.mmp.in b/backends/platform/symbian/mmp/scummvm_lure.mmp.in
index c4a3900a05..e1a63b602b 100644
--- a/backends/platform/symbian/mmp/scummvm_lure.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_lure.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\lure
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_m4.mmp.in b/backends/platform/symbian/mmp/scummvm_m4.mmp.in
index f4430f2e58..c2e1ce4e8b 100644
--- a/backends/platform/symbian/mmp/scummvm_m4.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_m4.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\m4
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_made.mmp.in b/backends/platform/symbian/mmp/scummvm_made.mmp.in
index bf50157224..91b9ca756d 100644
--- a/backends/platform/symbian/mmp/scummvm_made.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_made.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\made
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
index 78e931b06f..0edba5eb4d 100644
--- a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\mohawk
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
index e96ab907cd..744a756f4e 100644
--- a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\parallaction
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_queen.mmp.in b/backends/platform/symbian/mmp/scummvm_queen.mmp.in
index 4f9d9319e0..bf88744701 100644
--- a/backends/platform/symbian/mmp/scummvm_queen.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_queen.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\queen
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_saga.mmp.in b/backends/platform/symbian/mmp/scummvm_saga.mmp.in
index e5beefc0c5..a95ee1e7fd 100644
--- a/backends/platform/symbian/mmp/scummvm_saga.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_saga.mmp.in
@@ -71,5 +71,5 @@ SOURCEPATH ..\..\..\..\engines\saga
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
index eb0d1b020f..ca9e712f3f 100644
--- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\sci
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in
index 6b5d249422..0a3cd9bb7d 100644
--- a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in
@@ -82,7 +82,7 @@ SOURCE smush/codec47ARM.s // ARM version: add ASM routines
// *** Include paths
USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\scumm\smush ..\..\..\..\engines\scumm\insane
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include\libc
diff --git a/backends/platform/symbian/mmp/scummvm_sky.mmp.in b/backends/platform/symbian/mmp/scummvm_sky.mmp.in
index d1d222b1fa..1bc2301745 100644
--- a/backends/platform/symbian/mmp/scummvm_sky.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sky.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sky
// *** Include paths
USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\sky\music
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in
index 0aaf9d504b..6bf543070b 100644
--- a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sword1
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in
index 4a7181709f..cee4143f94 100644
--- a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sword2
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
index 7832fc4880..fa4ef79692 100644
--- a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\teenagent
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
index 6190ec8152..569b79ba3c 100644
--- a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
@@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\tinsel
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_toon.mmp.in b/backends/platform/symbian/mmp/scummvm_toon.mmp.in
index f2301c4ae2..f309e6d0fa 100644
--- a/backends/platform/symbian/mmp/scummvm_toon.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_toon.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\toon
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_touche.mmp.in b/backends/platform/symbian/mmp/scummvm_touche.mmp.in
index 9e4c3d0496..ab42afe304 100644
--- a/backends/platform/symbian/mmp/scummvm_touche.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_touche.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\touche
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in
index d193ac49a9..434072bc96 100644
--- a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in
@@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\tucker
// *** Include paths
USERINCLUDE ..\..\..\..\engines
-USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src
SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version
SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/webos/main.cpp b/backends/platform/webos/main.cpp
new file mode 100644
index 0000000000..bbf55c6efd
--- /dev/null
+++ b/backends/platform/webos/main.cpp
@@ -0,0 +1,53 @@
+/* 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$
+ *
+ */
+
+#include "backends/platform/webos/webos.h"
+#include "backends/plugins/sdl/sdl-provider.h"
+#include "base/main.h"
+
+#if defined(WEBOS)
+
+#include <unistd.h>
+
+int main(int argc, char* argv[]) {
+ g_system = new OSystem_SDL_WebOS();
+ assert(g_system);
+
+ ((OSystem_SDL_WebOS *)g_system)->init();
+
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
+#endif
+
+ // Invoke the actual ScummVM main entry point:
+ int res = scummvm_main(argc, argv);
+
+ // Free OSystem
+ delete (OSystem_SDL_WebOS *)g_system;
+
+ return res;
+}
+
+#endif
diff --git a/backends/platform/webos/module.mk b/backends/platform/webos/module.mk
new file mode 100644
index 0000000000..fe4ec1e079
--- /dev/null
+++ b/backends/platform/webos/module.mk
@@ -0,0 +1,10 @@
+MODULE := backends/platform/webos
+
+MODULE_OBJS := \
+ main.o \
+ webos.o
+
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/webos/webos.cpp b/backends/platform/webos/webos.cpp
new file mode 100644
index 0000000000..7db17f4b9f
--- /dev/null
+++ b/backends/platform/webos/webos.cpp
@@ -0,0 +1,73 @@
+/* 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$
+ *
+ */
+
+#include "backends/platform/webos/webos.h"
+#include "backends/events/webossdl/webossdl-events.h"
+#include "backends/keymapper/keymapper.h"
+
+#if defined(WEBOS)
+
+using namespace Common;
+
+OSystem_SDL_WebOS::OSystem_SDL_WebOS()
+ :
+ OSystem_POSIX() {
+}
+
+/**
+ * Initializes the backend.
+ */
+void OSystem_SDL_WebOS::initBackend() {
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new WebOSSdlEventSource();
+
+ // Call parent implementation of this method
+ OSystem_SDL::initBackend();
+}
+
+/**
+ * Gets the original SDL hardware key set, adds WebOS specific keys and
+ * returns the new key set.
+ *
+ * @return The hardware key set with added webOS specific keys.
+ */
+HardwareKeySet *OSystem_SDL_WebOS::getHardwareKeySet() {
+#ifdef ENABLE_KEYMAPPER
+ // Get the original SDL hardware key set
+ HardwareKeySet *keySet = OSystem_SDL::getHardwareKeySet();
+
+ // Add WebOS specific keys
+ keySet->addHardwareKey(new HardwareKey("FORWARD",
+ KeyState((KeyCode) 229, 229, 0), "Forward", kActionKeyType));
+
+ // Return the modified hardware key set
+ return keySet;
+#else
+ return 0;
+#endif
+}
+
+#endif
diff --git a/backends/platform/webos/webos.h b/backends/platform/webos/webos.h
new file mode 100644
index 0000000000..1cdba703e0
--- /dev/null
+++ b/backends/platform/webos/webos.h
@@ -0,0 +1,40 @@
+/* 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 PLATFORM_SDL_WEBOS_H
+#define PLATFORM_SDL_WEBOS_H
+
+#include "common/system.h"
+#include "backends/platform/sdl/posix/posix.h"
+
+class OSystem_SDL_WebOS : public OSystem_POSIX {
+public:
+ OSystem_SDL_WebOS();
+
+ virtual void initBackend();
+ virtual Common::HardwareKeySet *getHardwareKeySet();
+};
+
+#endif
diff --git a/backends/platform/webos/webos.mk b/backends/platform/webos/webos.mk
new file mode 100644
index 0000000000..885c9eb90e
--- /dev/null
+++ b/backends/platform/webos/webos.mk
@@ -0,0 +1,23 @@
+# WebOS specific build targets
+
+PATH_DIST = $(srcdir)/dists/webos
+PATH_MOJO = $(PATH_DIST)/mojo
+
+STAGING_DIR=STAGING/org.scummvm.scummvm
+
+webosrelease:
+ rm -rf $(STAGING_DIR)
+ rm -f *.ipk
+ mkdir -p $(STAGING_DIR)
+ mkdir -p $(STAGING_DIR)/bin
+ mkdir -p $(STAGING_DIR)/lib
+ mkdir -p $(STAGING_DIR)/share/scummvm
+ cp -f $(PATH_MOJO)/* $(STAGING_DIR)
+ cp -f gui/themes/translations.dat $(STAGING_DIR)/share/scummvm
+ cp -f gui/themes/scummmodern.zip $(STAGING_DIR)/share/scummvm
+ cp -f scummvm $(STAGING_DIR)/bin
+ $(STRIP) $(STAGING_DIR)/bin/scummvm
+ $(WEBOS_SDK)/bin/palm-package $(STAGING_DIR)
+ rm -rf STAGING
+
+.PHONY: webosrelease
diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp
index 09575bb83d..cb9a8c72e9 100644
--- a/backends/platform/wii/osystem_gfx.cpp
+++ b/backends/platform/wii/osystem_gfx.cpp
@@ -326,23 +326,23 @@ void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) {
const byte *s = colors;
u16 *d = _texGame.palette;
- for (uint i = 0; i < num; ++i) {
+ for (uint i = 0; i < num; ++i, s +=3)
d[start + i] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(s[0], s[1], s[2]);
- s += 4;
- }
gfx_tex_flush_palette(&_texGame);
+ s = colors;
+ d = _cursorPalette;
+
+ for (uint i = 0; i < num; ++i, s += 3) {
+ d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
+ }
+
if (_cursorPaletteDisabled) {
assert(_texMouse.palette);
- s = colors;
- d = _texMouse.palette;
-
- for (uint i = 0; i < num; ++i) {
- d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
- s += 4;
- }
+ memcpy((u8 *)_texMouse.palette + start * 2,
+ (u8 *)_cursorPalette + start * 2, num * 2);
_cursorPaletteDirty = true;
}
@@ -357,13 +357,11 @@ void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) {
byte *d = colors;
u8 r, g, b;
- for (uint i = 0; i < num; ++i) {
+ for (uint i = 0; i < num; ++i, d += 3) {
Graphics::colorToRGB<Graphics::ColorMasks<565> >(s[start + i], r, g, b);
d[0] = r;
d[1] = g;
d[2] = b;
- d[3] = 0xff;
- d += 4;
}
}
@@ -388,10 +386,8 @@ void OSystem_Wii::setCursorPalette(const byte *colors, uint start, uint num) {
const byte *s = colors;
u16 *d = _texMouse.palette;
- for (uint i = 0; i < num; ++i) {
+ for (uint i = 0; i < num; ++i, s += 3)
d[start + i] = Graphics::ARGBToColor<Graphics::ColorMasks<3444> >(0xff, s[0], s[1], s[2]);
- s += 4;
- }
_cursorPaletteDirty = true;
}
diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp
index 99d0be2bdc..3895c7d6fa 100644
--- a/backends/platform/wince/CEActionsPocket.cpp
+++ b/backends/platform/wince/CEActionsPocket.cpp
@@ -38,7 +38,7 @@
#ifdef _WIN32_WCE
-#define KEY_ALL_SKIP 3457
+#define KEY_ALL_SKIP 3457
#endif
const Common::String pocketActionNames[] = {
@@ -85,14 +85,14 @@ int CEActionsPocket::version() {
}
CEActionsPocket::CEActionsPocket(const Common::String &gameid) :
-GUI::Actions() {
+ GUI::Actions() {
int i;
_right_click_needed = false;
_hide_toolbar_needed = false;
_zoom_needed = false;
- for (i=0; i<POCKET_ACTION_LAST; i++) {
+ for (i = 0; i < POCKET_ACTION_LAST; i++) {
_action_mapping[i] = 0;
_action_enabled[i] = false;
}
@@ -112,7 +112,7 @@ GUI::Actions() {
void CEActionsPocket::initInstanceMain(OSystem *mainSystem) {
// Nothing generic to do for Pocket PC
- _CESystem = static_cast<OSystem_WINCE3*>(mainSystem);
+ _CESystem = static_cast<OSystem_WINCE3 *>(mainSystem);
GUI_Actions::initInstanceMain(mainSystem);
}
@@ -126,7 +126,7 @@ void CEActionsPocket::initInstanceGame() {
bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0);
bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0);
bool is_saga = (gameid == "saga");
- bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0);
+ bool is_kyra = (strncmp(gameid.c_str(), "kyra", 4) == 0);
bool is_samnmax = (gameid == "samnmax");
bool is_cine = (gameid == "cine");
bool is_touche = (gameid == "touche");
@@ -134,7 +134,7 @@ void CEActionsPocket::initInstanceGame() {
bool is_parallaction = (gameid == "parallaction");
bool is_lure = (gameid == "lure");
bool is_feeble = (gameid == "feeble");
- bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0);
+ bool is_drascula = (strncmp(gameid.c_str(), "drascula", 8) == 0);
bool is_tucker = (gameid == "tucker");
bool is_groovie = (gameid == "groovie");
bool is_tinsel = (gameid == "tinsel");
@@ -145,7 +145,7 @@ void CEActionsPocket::initInstanceGame() {
// See if a right click mapping could be needed
if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_tinsel ||
- is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
+ is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
_right_click_needed = true;
// See if a "hide toolbar" mapping could be needed
@@ -187,7 +187,7 @@ void CEActionsPocket::initInstanceGame() {
if (!is_cine && !is_parallaction && !is_groovie && !is_cruise && !is_made)
_action_enabled[POCKET_ACTION_SKIP] = true;
if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_tinsel ||
- is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker)
+ is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker)
_key_action[POCKET_ACTION_SKIP].setKey(VK_ESCAPE);
else
_key_action[POCKET_ACTION_SKIP].setKey(KEY_ALL_SKIP);
@@ -239,10 +239,12 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
if (!pushed) {
switch (action) {
case POCKET_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(false);
+ //_CESystem->add_right_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(false);
return true;
case POCKET_ACTION_LEFTCLICK:
- _CESystem->add_left_click(false);
+ //_CESystem->add_left_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(false);
return true;
case POCKET_ACTION_PAUSE:
case POCKET_ACTION_SAVE:
@@ -272,43 +274,55 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
EventsBuffer::simulateKey(&_key_action[action], true);
return true;
case POCKET_ACTION_KEYBOARD:
- _CESystem->swap_panel();
+ //_CESystem->swap_panel();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_panel();
return true;
case POCKET_ACTION_HIDE:
- _CESystem->swap_panel_visibility();
+ //_CESystem->swap_panel_visibility();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_panel_visibility();
return true;
case POCKET_ACTION_SOUND:
_CESystem->swap_sound_master();
return true;
case POCKET_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(true);
+ //_CESystem->add_right_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(true);
return true;
case POCKET_ACTION_CURSOR:
- _CESystem->swap_mouse_visibility();
+ //_CESystem->swap_mouse_visibility();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_mouse_visibility();
return true;
case POCKET_ACTION_FREELOOK:
- _CESystem->swap_freeLook();
+ //_CESystem->swap_freeLook();
+ ((WINCESdlEventSource *)((OSystem_SDL *)g_system)->getEventManager())->swap_freeLook();
return true;
case POCKET_ACTION_ZOOM_UP:
- _CESystem->swap_zoom_up();
+ //_CESystem->swap_zoom_up();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_zoom_up();
return true;
case POCKET_ACTION_ZOOM_DOWN:
- _CESystem->swap_zoom_down();
+ //_CESystem->swap_zoom_down();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_zoom_down();
return true;
case POCKET_ACTION_LEFTCLICK:
- _CESystem->add_left_click(true);
+ //_CESystem->add_left_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(true);
return true;
case POCKET_ACTION_UP:
- _CESystem->move_cursor_up();
+ //_CESystem->move_cursor_up();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_up();
return true;
case POCKET_ACTION_DOWN:
- _CESystem->move_cursor_down();
+ //_CESystem->move_cursor_down();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_down();
return true;
case POCKET_ACTION_LEFT:
- _CESystem->move_cursor_left();
+ //_CESystem->move_cursor_left();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_left();
return true;
case POCKET_ACTION_RIGHT:
- _CESystem->move_cursor_right();
+ //_CESystem->move_cursor_right();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_right();
return true;
case POCKET_ACTION_QUIT:
if (!quitdialog) {
diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp
index 5c7feb4950..413c52af2b 100644
--- a/backends/platform/wince/CEActionsSmartphone.cpp
+++ b/backends/platform/wince/CEActionsSmartphone.cpp
@@ -36,7 +36,7 @@
#include "common/translation.h"
-#define KEY_ALL_SKIP 3457
+#define KEY_ALL_SKIP 3457
const String smartphoneActionNames[] = {
_s("Up"),
@@ -79,10 +79,10 @@ int CEActionsSmartphone::version() {
}
CEActionsSmartphone::CEActionsSmartphone()
-: GUI::Actions() {
+ : GUI::Actions() {
int i;
- for (i=0; i<SMARTPHONE_ACTION_LAST; i++) {
+ for (i = 0; i < SMARTPHONE_ACTION_LAST; i++) {
_action_mapping[i] = ACTIONS_SMARTPHONE_DEFAULT[i];
_action_enabled[i] = false;
}
@@ -90,7 +90,7 @@ CEActionsSmartphone::CEActionsSmartphone()
}
void CEActionsSmartphone::initInstanceMain(OSystem *mainSystem) {
- _CESystem = static_cast<OSystem_WINCE3*>(mainSystem);
+ _CESystem = static_cast<OSystem_WINCE3 *>(mainSystem);
GUI_Actions::initInstanceMain(mainSystem);
@@ -117,7 +117,7 @@ void CEActionsSmartphone::initInstanceGame() {
bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0);
bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0);
bool is_saga = (gameid == "saga");
- bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0);
+ bool is_kyra = (strncmp(gameid.c_str(), "kyra", 4) == 0);
bool is_samnmax = (gameid == "samnmax");
bool is_cine = (gameid == "cine");
bool is_touche = (gameid == "touche");
@@ -125,7 +125,7 @@ void CEActionsSmartphone::initInstanceGame() {
bool is_parallaction = (gameid == "parallaction");
bool is_lure = (gameid == "lure");
bool is_feeble = (gameid == "feeble");
- bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0);
+ bool is_drascula = (strncmp(gameid.c_str(), "drascula", 8) == 0);
bool is_tucker = (gameid == "tucker");
bool is_groovie = (gameid == "groovie");
bool is_tinsel = (gameid == "tinsel");
@@ -136,7 +136,7 @@ void CEActionsSmartphone::initInstanceGame() {
// See if a right click mapping could be needed
if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_tinsel ||
- is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
+ is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise)
_right_click_needed = true;
// Initialize keys for different actions
@@ -168,8 +168,8 @@ void CEActionsSmartphone::initInstanceGame() {
// Skip
_action_enabled[SMARTPHONE_ACTION_SKIP] = true;
if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_tinsel ||
- is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker ||
- is_groovie || is_cruise || is_made)
+ is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker ||
+ is_groovie || is_cruise || is_made)
_key_action[SMARTPHONE_ACTION_SKIP].setKey(VK_ESCAPE);
else
_key_action[SMARTPHONE_ACTION_SKIP].setKey(KEY_ALL_SKIP);
@@ -204,81 +204,92 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) {
if (!pushed) {
switch (action) {
- case SMARTPHONE_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(false);
- return true;
- case SMARTPHONE_ACTION_LEFTCLICK:
- _CESystem->add_left_click(false);
- return true;
- case SMARTPHONE_ACTION_SAVE:
- case SMARTPHONE_ACTION_SKIP:
- case SMARTPHONE_ACTION_MULTI:
- EventsBuffer::simulateKey(&_key_action[action], false);
- return true;
- }
- return false;
- }
-
- switch (action) {
- case SMARTPHONE_ACTION_SAVE:
- case SMARTPHONE_ACTION_SKIP:
- case SMARTPHONE_ACTION_MULTI:
- if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") {
- // FIXME: This is a temporary solution. The engine should handle its own menus.
- // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience
- GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save"));
- if (alert.runModal() == GUI::kMessageOK)
- _key_action[action].setKey(SDLK_l);
- else
- _key_action[action].setKey(SDLK_s);
- }
- EventsBuffer::simulateKey(&_key_action[action], true);
- return true;
case SMARTPHONE_ACTION_RIGHTCLICK:
- _CESystem->add_right_click(true);
+ //_CESystem->add_right_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(false);
return true;
case SMARTPHONE_ACTION_LEFTCLICK:
- _CESystem->add_left_click(true);
- return true;
- case SMARTPHONE_ACTION_UP:
- _CESystem->move_cursor_up();
- return true;
- case SMARTPHONE_ACTION_DOWN:
- _CESystem->move_cursor_down();
- return true;
- case SMARTPHONE_ACTION_LEFT:
- _CESystem->move_cursor_left();
- return true;
- case SMARTPHONE_ACTION_RIGHT:
- _CESystem->move_cursor_right();
- return true;
- case SMARTPHONE_ACTION_ZONE:
- _CESystem->switch_zone();
+ //_CESystem->add_left_click(false);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(false);
return true;
- case SMARTPHONE_ACTION_BINDKEYS:
- if (!keydialogrunning) {
- keydialogrunning = true;
- GUI::KeysDialog *keysDialog = new GUI::KeysDialog();
- keysDialog->runModal();
- delete keysDialog;
- keydialogrunning = false;
- }
- return true;
- case SMARTPHONE_ACTION_KEYBOARD:
- _CESystem->swap_smartphone_keyboard();
- return true;
- case SMARTPHONE_ACTION_ROTATE:
- _CESystem->smartphone_rotate_display();
- return true;
- case SMARTPHONE_ACTION_QUIT:
- if (!quitdialog) {
- quitdialog = true;
- GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No"));
- if (alert.runModal() == GUI::kMessageOK)
- _mainSystem->quit();
- quitdialog = false;
- }
+ case SMARTPHONE_ACTION_SAVE:
+ case SMARTPHONE_ACTION_SKIP:
+ case SMARTPHONE_ACTION_MULTI:
+ EventsBuffer::simulateKey(&_key_action[action], false);
return true;
+ }
+ return false;
+ }
+
+ switch (action) {
+ case SMARTPHONE_ACTION_SAVE:
+ case SMARTPHONE_ACTION_SKIP:
+ case SMARTPHONE_ACTION_MULTI:
+ if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") {
+ // FIXME: This is a temporary solution. The engine should handle its own menus.
+ // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience
+ GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save"));
+ if (alert.runModal() == GUI::kMessageOK)
+ _key_action[action].setKey(SDLK_l);
+ else
+ _key_action[action].setKey(SDLK_s);
+ }
+ EventsBuffer::simulateKey(&_key_action[action], true);
+ return true;
+ case SMARTPHONE_ACTION_RIGHTCLICK:
+ //_CESystem->add_right_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(true);
+ return true;
+ case SMARTPHONE_ACTION_LEFTCLICK:
+ //_CESystem->add_left_click(true);
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(true);
+ return true;
+ case SMARTPHONE_ACTION_UP:
+ //_CESystem->move_cursor_up();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_up();
+ return true;
+ case SMARTPHONE_ACTION_DOWN:
+ //_CESystem->move_cursor_down();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_down();
+ return true;
+ case SMARTPHONE_ACTION_LEFT:
+ //_CESystem->move_cursor_left();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_left();
+ return true;
+ case SMARTPHONE_ACTION_RIGHT:
+ //_CESystem->move_cursor_right();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_right();
+ return true;
+ case SMARTPHONE_ACTION_ZONE:
+ //_CESystem->switch_zone();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->switch_zone();
+ return true;
+ case SMARTPHONE_ACTION_BINDKEYS:
+ if (!keydialogrunning) {
+ keydialogrunning = true;
+ GUI::KeysDialog *keysDialog = new GUI::KeysDialog();
+ keysDialog->runModal();
+ delete keysDialog;
+ keydialogrunning = false;
+ }
+ return true;
+ case SMARTPHONE_ACTION_KEYBOARD:
+ //_CESystem->swap_smartphone_keyboard();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_smartphone_keyboard();
+ return true;
+ case SMARTPHONE_ACTION_ROTATE:
+ //_CESystem->smartphone_rotate_display();
+ ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->smartphone_rotate_display();
+ return true;
+ case SMARTPHONE_ACTION_QUIT:
+ if (!quitdialog) {
+ quitdialog = true;
+ GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No"));
+ if (alert.runModal() == GUI::kMessageOK)
+ _mainSystem->quit();
+ quitdialog = false;
+ }
+ return true;
}
return false;
diff --git a/backends/platform/wince/CEDevice.cpp b/backends/platform/wince/CEDevice.cpp
index d94ce6cde7..ffe2523b47 100644
--- a/backends/platform/wince/CEDevice.cpp
+++ b/backends/platform/wince/CEDevice.cpp
@@ -29,22 +29,22 @@
#include "backends/platform/wince/wince-sdl.h"
-static void (WINAPI* _SHIdleTimerReset)(void) = NULL;
-static HANDLE (WINAPI* _SetPowerRequirement)(PVOID,int,ULONG,PVOID,ULONG) = NULL;
-static DWORD (WINAPI* _ReleasePowerRequirement)(HANDLE) = NULL;
+static void (WINAPI *_SHIdleTimerReset)(void) = NULL;
+static HANDLE(WINAPI *_SetPowerRequirement)(PVOID, int, ULONG, PVOID, ULONG) = NULL;
+static DWORD (WINAPI *_ReleasePowerRequirement)(HANDLE) = NULL;
static HANDLE _hPowerManagement = NULL;
static DWORD _lastTime = 0;
static DWORD REG_bat = 0, REG_ac = 0, REG_disp = 0, bat_timeout = 0;
static bool REG_tampered = false;
#ifdef __GNUC__
extern "C" void WINAPI SystemIdleTimerReset(void);
-#define SPI_SETBATTERYIDLETIMEOUT 251
-#define SPI_GETBATTERYIDLETIMEOUT 252
+#define SPI_SETBATTERYIDLETIMEOUT 251
+#define SPI_GETBATTERYIDLETIMEOUT 252
#endif
#define TIMER_TRIGGER 9000
-DWORD CEDevice::reg_access(TCHAR *key, TCHAR *val, DWORD data) {
+DWORD CEDevice::reg_access(const TCHAR *key, const TCHAR *val, DWORD data) {
HKEY regkey;
DWORD tmpval, cbdata;
@@ -70,7 +70,7 @@ DWORD CEDevice::reg_access(TCHAR *key, TCHAR *val, DWORD data) {
void CEDevice::backlight_xchg() {
HANDLE h;
- REG_bat = reg_access(TEXT("ControlPanel\\BackLight"), TEXT("BatteryTimeout"), REG_bat);
+ REG_bat = reg_access(TEXT("ControlPanel\\BackLight"), (const TCHAR *)TEXT("BatteryTimeout"), REG_bat);
REG_ac = reg_access(TEXT("ControlPanel\\BackLight"), TEXT("ACTimeout"), REG_ac);
REG_disp = reg_access(TEXT("ControlPanel\\Power"), TEXT("Display"), REG_disp);
@@ -85,20 +85,19 @@ void CEDevice::init() {
// 2003+ power management code borrowed from MoDaCo & Betaplayer. Thanks !
HINSTANCE dll = LoadLibrary(TEXT("aygshell.dll"));
if (dll) {
- *(FARPROC*)&_SHIdleTimerReset = GetProcAddress(dll, MAKEINTRESOURCE(2006));
+ _SHIdleTimerReset = (void (*)())GetProcAddress(dll, MAKEINTRESOURCE(2006));
}
dll = LoadLibrary(TEXT("coredll.dll"));
if (dll) {
- *(FARPROC*)&_SetPowerRequirement = GetProcAddress(dll, TEXT("SetPowerRequirement"));
- *(FARPROC*)&_ReleasePowerRequirement = GetProcAddress(dll, TEXT("ReleasePowerRequirement"));
-
+ _SetPowerRequirement = (HANDLE (*)(PVOID, int, ULONG, PVOID, ULONG))GetProcAddress(dll, TEXT("SetPowerRequirement"));
+ _ReleasePowerRequirement = (DWORD (*)(HANDLE))GetProcAddress(dll, TEXT("ReleasePowerRequirement"));
}
if (_SetPowerRequirement)
_hPowerManagement = _SetPowerRequirement((PVOID) TEXT("BKL1:"), 0, 1, (PVOID) NULL, 0);
_lastTime = GetTickCount();
// older devices
- REG_bat = REG_ac = REG_disp = 2 * 60 * 60 * 1000; // 2hrs should do it
+ REG_bat = REG_ac = REG_disp = 2 * 60 * 60 * 1000; // 2hrs should do it
backlight_xchg();
REG_tampered = true;
SystemParametersInfo(SPI_GETBATTERYIDLETIMEOUT, 0, (void *) &bat_timeout, 0);
@@ -127,6 +126,10 @@ bool CEDevice::hasSquareQVGAResolution() {
return (OSystem_WINCE3::getScreenWidth() == 240 && OSystem_WINCE3::getScreenHeight() == 240);
}
+bool CEDevice::hasWideResolution() {
+ return (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640);
+}
+
bool CEDevice::hasPocketPCResolution() {
if (OSystem_WINCE3::isOzone() && hasWideResolution())
return true;
@@ -139,10 +142,6 @@ bool CEDevice::hasDesktopResolution() {
return (OSystem_WINCE3::getScreenWidth() > 320);
}
-bool CEDevice::hasWideResolution() {
- return (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640);
-}
-
bool CEDevice::hasSmartphoneResolution() {
return (OSystem_WINCE3::getScreenWidth() < 240);
}
diff --git a/backends/platform/wince/CEDevice.h b/backends/platform/wince/CEDevice.h
index b2b20d05ce..24dffca0b3 100644
--- a/backends/platform/wince/CEDevice.h
+++ b/backends/platform/wince/CEDevice.h
@@ -43,7 +43,7 @@ public:
static bool isSmartphone();
private:
- static DWORD reg_access(TCHAR *key, TCHAR *val, DWORD data);
+ static DWORD reg_access(const TCHAR *key, const TCHAR *val, DWORD data);
static void backlight_xchg();
};
diff --git a/backends/platform/wince/CEException.cpp b/backends/platform/wince/CEException.cpp
index 421db4960c..08a327136f 100644
--- a/backends/platform/wince/CEException.cpp
+++ b/backends/platform/wince/CEException.cpp
@@ -36,7 +36,7 @@ void CEException::writeBreak(HANDLE file) {
int i;
memset(tempo, 0, sizeof(tempo));
- for (i=0; i<40; i++)
+ for (i = 0; i < 40; i++)
tempo[i] = '-';
writeString(file, tempo);
}
@@ -51,23 +51,23 @@ void CEException::dumpContext(HANDLE file, HANDLE hProcess, CONTEXT *context) {
writeBreak(file);
writeString(file, "Context dump");
sprintf(tempo, "R0=%.8x R1=%.8x R2=%.8x R3=%.8x R4=%.8x", context->R0, context->R1,
- context->R2, context->R3, context->R4);
+ context->R2, context->R3, context->R4);
writeString(file, tempo);
sprintf(tempo, "R5=%.8x R6=%.8x R7=%.8x R8=%.8x R9=%.8x", context->R5, context->R6,
- context->R7, context->R8, context->R9);
+ context->R7, context->R8, context->R9);
writeString(file, tempo);
sprintf(tempo, "R10=%.8x R11=%.8x R12=%.8x", context->R10, context->R11,
- context->R12);
+ context->R12);
writeString(file, tempo);
sprintf(tempo, "Sp=%.8x Lr=%.8x Pc=%.8x Psr=%.8x", context->Sp, context->Lr,
- context->Pc, context->Psr);
+ context->Pc, context->Psr);
writeString(file, tempo);
writeBreak(file);
sprintf(tempo, "Memory dump at %.8x", context->Pc - (sizeof(memoryDump) / 2));
writeString(file, tempo);
if (ReadProcessMemory(hProcess, (LPCVOID)(context->Pc - (sizeof(memoryDump) / 2)), memoryDump, sizeof(memoryDump), &size)) {
- for (i=0; i<size; i+=8) {
+ for (i = 0; i < size; i += 8) {
int j;
char digit[4];
int max;
@@ -75,7 +75,7 @@ void CEException::dumpContext(HANDLE file, HANDLE hProcess, CONTEXT *context) {
if (max > 8)
max = 8;
tempo[0] = '\0';
- for (j=0; j<max; j++) {
+ for (j = 0; j < max; j++) {
sprintf(digit, "%.2x ", memoryDump[i + j]);
strcat(tempo, digit);
}
@@ -121,10 +121,10 @@ void CEException::dumpException(HANDLE file, EXCEPTION_RECORD *exceptionRecord)
break;
}
sprintf(tempo, "Exception %s Flags %.8x Address %.8x", exceptionName, exceptionRecord->ExceptionFlags,
- exceptionRecord->ExceptionAddress);
+ exceptionRecord->ExceptionAddress);
writeString(file, tempo);
if (exceptionRecord->NumberParameters) {
- for (i=0; i<exceptionRecord->NumberParameters; i++) {
+ for (i = 0; i < exceptionRecord->NumberParameters; i++) {
sprintf(tempo, "Parameter %d %.8x", i, exceptionRecord->ExceptionInformation[i]);
writeString(file, tempo);
}
@@ -144,8 +144,8 @@ bool CEException::writeException(TCHAR *path, EXCEPTION_POINTERS *exceptionPoint
GetSystemTime(&systemTime);
wsprintf(dumpFileName, TEXT("%s_%.2d_%.2d_%.4d_%.2d_%.2d_%.2d.txt"),
- path, systemTime.wDay, systemTime.wMonth, systemTime.wYear,
- systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
+ path, systemTime.wDay, systemTime.wMonth, systemTime.wYear,
+ systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
dumpFile = CreateFile(dumpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (dumpFile == INVALID_HANDLE_VALUE)
return false;
diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp
index de1bb2f1f6..8824af732f 100644
--- a/backends/platform/wince/CELauncherDialog.cpp
+++ b/backends/platform/wince/CELauncherDialog.cpp
@@ -48,14 +48,14 @@ using namespace Common;
class CEAboutDialog : public Dialog {
public:
CEAboutDialog()
- : Dialog(10, 60, 300, 77) {
+ : Dialog(10, 60, 300, 77) {
char tempo[100];
// FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
// needs fixing, or remove it!
const int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0);
const int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
- new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME
+ new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME
Common::String videoDriver(_("Using SDL driver "));
SDL_VideoDriverName(tempo, sizeof(tempo));
@@ -106,14 +106,13 @@ void CELauncherDialog::addGame() {
MessageDialog alert(_("Do you want to perform an automatic scan ?"), _("Yes"), _("No"));
if (alert.runModal() == kMessageOK && _browser->runModal() > 0) {
// Clear existing domains
- ConfigManager::DomainMap &domains = (ConfigManager::DomainMap&)ConfMan.getGameDomains();
+ ConfigManager::DomainMap &domains = (ConfigManager::DomainMap &)ConfMan.getGameDomains();
domains.clear();
ConfMan.flushToDisk();
automaticScanDirectory(_browser->getResult());
ConfMan.flushToDisk();
updateListing();
draw();
- }
- else
+ } else
GUILauncherDialog::addGame();
}
diff --git a/backends/platform/wince/CEgui/GUIElement.cpp b/backends/platform/wince/CEgui/GUIElement.cpp
index dd463c22a1..e7ffc8d473 100644
--- a/backends/platform/wince/CEgui/GUIElement.cpp
+++ b/backends/platform/wince/CEgui/GUIElement.cpp
@@ -32,7 +32,7 @@
namespace CEGUI {
GUIElement::GUIElement(int x, int y, int width, int height) :
-_background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) {
+ _background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) {
}
bool GUIElement::setBackground(WORD backgroundReference) {
@@ -45,9 +45,7 @@ bool GUIElement::setBackground(WORD backgroundReference) {
if (!_height && !_width) {
_height = _background->height();
_width = _background->width();
- }
- else
- if (_background->height() != _height || _background->width() != _width) {
+ } else if (_background->height() != _height || _background->width() != _width) {
delete _background;
_background = NULL;
return false;
@@ -74,8 +72,7 @@ bool GUIElement::draw(SDL_Surface *surface) {
_drawn = true;
return true;
- }
- else
+ } else
return false;
}
diff --git a/backends/platform/wince/CEgui/ItemAction.cpp b/backends/platform/wince/CEgui/ItemAction.cpp
index 55805744e6..efbc43ce00 100644
--- a/backends/platform/wince/CEgui/ItemAction.cpp
+++ b/backends/platform/wince/CEgui/ItemAction.cpp
@@ -28,7 +28,7 @@
namespace CEGUI {
ItemAction::ItemAction(WORD reference, GUI::ActionType action) :
-PanelItem(reference) {
+ PanelItem(reference) {
_action = action;
if (!GUI::Actions::Instance()->isEnabled(_action))
_visible = false;
diff --git a/backends/platform/wince/CEgui/ItemSwitch.cpp b/backends/platform/wince/CEgui/ItemSwitch.cpp
index d4648f7556..8eb62bf365 100644
--- a/backends/platform/wince/CEgui/ItemSwitch.cpp
+++ b/backends/platform/wince/CEgui/ItemSwitch.cpp
@@ -40,7 +40,7 @@ void ItemSwitch::init(WORD referenceTrue, WORD referenceFalse) {
}
ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item) :
-PanelItem(referenceTrue) {
+ PanelItem(referenceTrue) {
init(referenceTrue, referenceFalse);
_item = item;
_itemmax = -1;
@@ -49,8 +49,8 @@ PanelItem(referenceTrue) {
}
ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max) :
-PanelItem(referenceTrue) {
- init(referenceTrue, referenceFalse);
+ PanelItem(referenceTrue) {
+ init(referenceTrue, referenceFalse);
_itemmultiple = item;
_itemmax = max;
if (!*item)
diff --git a/backends/platform/wince/CEgui/Panel.cpp b/backends/platform/wince/CEgui/Panel.cpp
index dfdd6526be..576da23029 100644
--- a/backends/platform/wince/CEgui/Panel.cpp
+++ b/backends/platform/wince/CEgui/Panel.cpp
@@ -34,7 +34,7 @@ Panel::Panel(int interleave_first, int interleave) : Toolbar() {
bool Panel::add(const String &name, const PanelItem *item) {
- _itemsMap[name] = (PanelItem*)item;
+ _itemsMap[name] = (PanelItem *)item;
_itemsMap[name]->move(_currentItem, _y + 10);
_itemsMap[name]->setPanel(this);
_currentItem += _interleave;
@@ -47,11 +47,10 @@ bool Panel::draw(SDL_Surface *surface) {
if (!_drawn && _visible) {
GUIElement::draw(surface);
for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) {
- ((GUIElement*)(iterator->_value))->draw(surface);
+ ((GUIElement *)(iterator->_value))->draw(surface);
}
return true;
- }
- else
+ } else
return false;
}
@@ -59,7 +58,7 @@ void Panel::forceRedraw() {
ItemMap::const_iterator iterator;
GUIElement::forceRedraw();
for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator)
- ((GUIElement*)(iterator->_value))->forceRedraw();
+ ((GUIElement *)(iterator->_value))->forceRedraw();
}
bool Panel::action(int x, int y, bool pushed) {
@@ -69,7 +68,7 @@ bool Panel::action(int x, int y, bool pushed) {
return false;
for (iterator = _itemsMap.begin(); !result && iterator != _itemsMap.end(); ++iterator)
- result = ((GUIElement*)(iterator->_value))->action(x, y, pushed);
+ result = ((GUIElement *)(iterator->_value))->action(x, y, pushed);
return result;
}
diff --git a/backends/platform/wince/CEgui/Panel.h b/backends/platform/wince/CEgui/Panel.h
index e6b693360d..1a8a580dba 100644
--- a/backends/platform/wince/CEgui/Panel.h
+++ b/backends/platform/wince/CEgui/Panel.h
@@ -51,7 +51,7 @@ public:
virtual bool action(int x, int y, bool pushed);
private:
- typedef HashMap<String, PanelItem*, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap;
+ typedef HashMap<String, PanelItem *, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap;
ItemMap _itemsMap;
int _interleave;
diff --git a/backends/platform/wince/CEgui/PanelItem.h b/backends/platform/wince/CEgui/PanelItem.h
index 14b62f0f20..9968aa8d5e 100644
--- a/backends/platform/wince/CEgui/PanelItem.h
+++ b/backends/platform/wince/CEgui/PanelItem.h
@@ -36,7 +36,7 @@ namespace CEGUI {
class Panel;
class PanelItem : public GUIElement {
-friend class Panel;
+ friend class Panel;
public:
PanelItem(WORD reference);
virtual ~PanelItem();
diff --git a/backends/platform/wince/CEgui/PanelKeyboard.cpp b/backends/platform/wince/CEgui/PanelKeyboard.cpp
index 5ca125898d..3512b34da3 100644
--- a/backends/platform/wince/CEgui/PanelKeyboard.cpp
+++ b/backends/platform/wince/CEgui/PanelKeyboard.cpp
@@ -30,8 +30,9 @@ namespace CEGUI {
const char KEYBOARD_MAPPING_ALPHA[][14] = { {"abcdefghijklm"}, {"nopqrstuvwxyz"} };
const char KEYBOARD_MAPPING_NUMERIC[][6] = { {"12345"}, {"67890"} };
-const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1,SDLK_ESCAPE}, {224,SDLK_UP}, {32,SDLK_SPACE} },
- { {224,SDLK_LEFT}, {224,SDLK_DOWN}, {224,SDLK_RIGHT} } };
+const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1, SDLK_ESCAPE}, {224, SDLK_UP}, {32, SDLK_SPACE} },
+ { {224, SDLK_LEFT}, {224, SDLK_DOWN}, {224, SDLK_RIGHT} }
+};
PanelKeyboard::PanelKeyboard(WORD reference) : Toolbar() {
setBackground(reference);
@@ -51,21 +52,23 @@ bool PanelKeyboard::action(int x, int y, bool pushed) {
int keyCode = 0;
if (x < 185) {
// Alpha selection
- keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y+20][((x + 10) / 14) - 1];
+ keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y + 20][((x + 10) / 14) - 1];
} else if (x >= 186 && x <= 255) {
// Numeric selection
- keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y+20][((x - 187 + 10) / 14) - 1];
+ keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y + 20][((x - 187 + 10) / 14) - 1];
} else if (x >= 258 && x <= 300) {
// Special keys
- keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][0];
- keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][1];
+ keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y + 20][((x - 259 + 10) / 14) - 1][0];
+ keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y + 20][((x - 259 + 10) / 14) - 1][1];
} else if (x >= 302 && x <= 316) {
- if (y < _y +20) {
+ if (y < _y + 20) {
// Backspace
- keyAscii = VK_BACK; keyCode = keyAscii;
+ keyAscii = VK_BACK;
+ keyCode = keyAscii;
} else {
// Enter
- keyAscii = 13; keyCode = 13;
+ keyAscii = 13;
+ keyCode = 13;
}
}
diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.cpp b/backends/platform/wince/CEgui/SDL_ImageResource.cpp
index 8dad5f0a0c..872b94a442 100644
--- a/backends/platform/wince/CEgui/SDL_ImageResource.cpp
+++ b/backends/platform/wince/CEgui/SDL_ImageResource.cpp
@@ -32,7 +32,7 @@ SDL_ImageResource::SDL_ImageResource() :
_surface(0) {
}
-SDL_Surface* SDL_ImageResource::load(WORD resourceID) {
+SDL_Surface *SDL_ImageResource::load(WORD resourceID) {
HRSRC resource;
HGLOBAL resourceGlobal;
LPVOID resourcePointer;
@@ -62,7 +62,7 @@ SDL_Surface* SDL_ImageResource::load(WORD resourceID) {
return _surface;
}
-SDL_Surface* SDL_ImageResource::get() {
+SDL_Surface *SDL_ImageResource::get() {
return _surface;
}
diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.h b/backends/platform/wince/CEgui/SDL_ImageResource.h
index 5affd5c33c..397ced1434 100644
--- a/backends/platform/wince/CEgui/SDL_ImageResource.h
+++ b/backends/platform/wince/CEgui/SDL_ImageResource.h
@@ -36,8 +36,8 @@ namespace CEGUI {
class SDL_ImageResource {
public:
SDL_ImageResource();
- SDL_Surface* load(WORD resourceID);
- SDL_Surface* get();
+ SDL_Surface *load(WORD resourceID);
+ SDL_Surface *get();
int height();
int width();
virtual ~SDL_ImageResource();
diff --git a/backends/platform/wince/CEgui/ToolbarHandler.cpp b/backends/platform/wince/CEgui/ToolbarHandler.cpp
index 78f69119c3..ed2a72245a 100644
--- a/backends/platform/wince/CEgui/ToolbarHandler.cpp
+++ b/backends/platform/wince/CEgui/ToolbarHandler.cpp
@@ -29,15 +29,15 @@
namespace CEGUI {
ToolbarHandler::ToolbarHandler():
-_current(""), _active(NULL) {
+ _current(""), _active(NULL) {
}
bool ToolbarHandler::add(const String &name, const Toolbar &toolbar) {
- _toolbarMap[name] = (Toolbar*)&toolbar;
+ _toolbarMap[name] = (Toolbar *)&toolbar;
if (!_active) {
- _active = &((Toolbar&)toolbar);
+ _active = &((Toolbar &)toolbar);
_current = name;
}
@@ -53,7 +53,7 @@ bool ToolbarHandler::setActive(const String &name) {
return false;
if (_current == name)
return true;
- _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel)
+ _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel)
_current = name;
_active = _toolbarMap[name];
_active->forceRedraw();
@@ -67,8 +67,7 @@ bool ToolbarHandler::action(int x, int y, bool pushed) {
return _active->action(x / 2, (y - _offset) / 2, pushed);
else
return _active->action(x, y - _offset, pushed);
- }
- else
+ } else
return false;
}
@@ -118,7 +117,7 @@ int ToolbarHandler::getOffset() {
return _offset;
}
-Toolbar* ToolbarHandler::active() {
+Toolbar *ToolbarHandler::active() {
return _active;
}
diff --git a/backends/platform/wince/CEgui/ToolbarHandler.h b/backends/platform/wince/CEgui/ToolbarHandler.h
index e3bf590768..0f794d7d61 100644
--- a/backends/platform/wince/CEgui/ToolbarHandler.h
+++ b/backends/platform/wince/CEgui/ToolbarHandler.h
@@ -57,7 +57,7 @@ public:
virtual ~ToolbarHandler();
private:
- HashMap<String, Toolbar*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap;
+ HashMap<String, Toolbar *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap;
String _current;
Toolbar *_active;
int _offset;
diff --git a/backends/platform/wince/CEkeys/EventsBuffer.cpp b/backends/platform/wince/CEkeys/EventsBuffer.cpp
index c9f4af2304..beea272d2b 100644
--- a/backends/platform/wince/CEkeys/EventsBuffer.cpp
+++ b/backends/platform/wince/CEkeys/EventsBuffer.cpp
@@ -29,55 +29,55 @@
namespace CEKEYS {
- bool EventsBuffer::simulateKey(GUI::Key *key, bool pushed) {
- SDL_Event ev = {0};
-
- if (!key->keycode())
- key->setKey(key->ascii(), key->ascii());
- else if (!key->ascii())
- key->setKey(key->keycode());
-
- ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP);
- ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field
- ev.key.keysym.sym = (SDLKey)key->keycode();
- ev.key.keysym.mod = KMOD_RESERVED;
- return (SDL_PushEvent(&ev) == 0);
- }
-
- bool EventsBuffer::simulateMouseMove(int x, int y) {
- SDL_Event ev = {0};
-
- ev.type = SDL_MOUSEMOTION;
- ev.motion.x = x;
- ev.motion.y = y;
- return (SDL_PushEvent(&ev) == 0);
- }
-
- bool EventsBuffer::simulateMouseLeftClick(int x, int y, bool pushed) {
- SDL_Event ev = {0};
- static bool state = false;
-
- if (pushed == state) return 0;
- state = pushed;
- ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
- ev.button.button = SDL_BUTTON_LEFT;
- ev.button.x = x;
- ev.button.y = y;
- return (SDL_PushEvent(&ev) == 0);
- }
-
- bool EventsBuffer::simulateMouseRightClick(int x, int y, bool pushed) {
- SDL_Event ev = {0};
- static bool state = false;
-
- if (pushed == state) return 0;
- state = pushed;
- ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
- ev.button.button = SDL_BUTTON_RIGHT;
- ev.button.x = x;
- ev.button.y = y;
- return (SDL_PushEvent(&ev) == 0);
- }
+bool EventsBuffer::simulateKey(GUI::Key *key, bool pushed) {
+ SDL_Event ev = {0};
+
+ if (!key->keycode())
+ key->setKey(key->ascii(), key->ascii());
+ else if (!key->ascii())
+ key->setKey(key->keycode());
+
+ ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP);
+ ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field
+ ev.key.keysym.sym = (SDLKey)key->keycode();
+ ev.key.keysym.mod = KMOD_RESERVED;
+ return (SDL_PushEvent(&ev) == 0);
+}
+
+bool EventsBuffer::simulateMouseMove(int x, int y) {
+ SDL_Event ev = {0};
+
+ ev.type = SDL_MOUSEMOTION;
+ ev.motion.x = x;
+ ev.motion.y = y;
+ return (SDL_PushEvent(&ev) == 0);
+}
+
+bool EventsBuffer::simulateMouseLeftClick(int x, int y, bool pushed) {
+ SDL_Event ev = {0};
+ static bool state = false;
+
+ if (pushed == state) return 0;
+ state = pushed;
+ ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
+ ev.button.button = SDL_BUTTON_LEFT;
+ ev.button.x = x;
+ ev.button.y = y;
+ return (SDL_PushEvent(&ev) == 0);
+}
+
+bool EventsBuffer::simulateMouseRightClick(int x, int y, bool pushed) {
+ SDL_Event ev = {0};
+ static bool state = false;
+
+ if (pushed == state) return 0;
+ state = pushed;
+ ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP);
+ ev.button.button = SDL_BUTTON_RIGHT;
+ ev.button.x = x;
+ ev.button.y = y;
+ return (SDL_PushEvent(&ev) == 0);
+}
}
diff --git a/backends/platform/wince/CEkeys/EventsBuffer.h b/backends/platform/wince/CEkeys/EventsBuffer.h
index 22590db03c..9b766c6ca9 100644
--- a/backends/platform/wince/CEkeys/EventsBuffer.h
+++ b/backends/platform/wince/CEkeys/EventsBuffer.h
@@ -34,14 +34,14 @@
namespace CEKEYS {
- class EventsBuffer {
- public:
- static bool simulateKey(GUI::Key *key, bool pushed);
- static bool simulateMouseMove(int x, int y);
- static bool simulateMouseLeftClick(int x, int y, bool pushed);
- static bool simulateMouseRightClick(int x, int y, bool pushed);
-
- };
+class EventsBuffer {
+public:
+ static bool simulateKey(GUI::Key *key, bool pushed);
+ static bool simulateMouseMove(int x, int y);
+ static bool simulateMouseLeftClick(int x, int y, bool pushed);
+ static bool simulateMouseRightClick(int x, int y, bool pushed);
+
+};
}
#endif
diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile
index 8ad134648b..21bff06f95 100644
--- a/backends/platform/wince/Makefile
+++ b/backends/platform/wince/Makefile
@@ -113,7 +113,7 @@ INCLUDES := -I$(srcdir) -I. -I$(srcdir)/engines -Imissing/gcc -Ilibs/include -Il
CFLAGS :=
ifndef UNOPTIMIZED_BUILD
-CFLAGS += -O3 -march=armv4 -mtune=xscale
+CFLAGS += -O3 -fno-inline-functions -march=armv4 -mtune=xscale
endif
LDFLAGS := -Wl,-Map,scummvm.exe.map -Wl,--stack,65536
diff --git a/backends/platform/wince/missing/io.h b/backends/platform/wince/missing/io.h
index 8c66e9405b..96bc6a9ea1 100644
--- a/backends/platform/wince/missing/io.h
+++ b/backends/platform/wince/missing/io.h
@@ -5,9 +5,9 @@
#define strdup _strdup
#ifndef _FILE_DEFINED
- typedef void FILE;
- #define _FILE_DEFINED
+typedef void FILE;
+#define _FILE_DEFINED
#endif
-FILE* wce_fopen(const char* fname, const char* fmode);
+FILE *wce_fopen(const char *fname, const char *fmode);
#define fopen wce_fopen
diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp
index 92af3e6961..c855247ae1 100644
--- a/backends/platform/wince/missing/missing.cpp
+++ b/backends/platform/wince/missing/missing.cpp
@@ -50,7 +50,7 @@ char *strdup(const char *strSource);
// common missing functions required by both gcc and evc
void *bsearch(const void *key, const void *base, size_t nmemb,
- size_t size, int (*compar)(const void *, const void *)) {
+ size_t size, int (*compar)(const void *, const void *)) {
// Perform binary search
size_t lo = 0;
size_t hi = nmemb;
@@ -63,17 +63,17 @@ void *bsearch(const void *key, const void *base, size_t nmemb,
else if (tmp > 0)
lo = mid + 1;
else
- return (void *)p;
+ return const_cast<void *>(p);
}
return NULL;
}
-static char cwd[MAX_PATH+1] = "";
+static char cwd[MAX_PATH + 1] = "";
EXT_C char *getcwd(char *buffer, int maxlen) {
- TCHAR fileUnc[MAX_PATH+1];
- char* plast;
+ TCHAR fileUnc[MAX_PATH + 1];
+ char *plast;
if (cwd[0] == 0) {
GetModuleFileName(NULL, fileUnc, MAX_PATH);
@@ -94,7 +94,7 @@ EXT_C char *getcwd(char *buffer, int maxlen) {
#undef GetCurrentDirectory
#endif
EXT_C void GetCurrentDirectory(int len, char *buf) {
- getcwd(buf,len);
+ getcwd(buf, len);
}
/*
@@ -103,8 +103,8 @@ fully qualified paths refer to root folder rather
than current folder (concept not implemented in CE).
*/
#undef fopen
-EXT_C FILE *wce_fopen(const char* fname, const char* fmode) {
- char fullname[MAX_PATH+1];
+EXT_C FILE *wce_fopen(const char *fname, const char *fmode) {
+ char fullname[MAX_PATH + 1];
if (!fname || fname[0] == '\0')
return NULL;
@@ -118,8 +118,8 @@ EXT_C FILE *wce_fopen(const char* fname, const char* fmode) {
}
/* Remove file by name */
-int remove(const char* path) {
- TCHAR pathUnc[MAX_PATH+1];
+int remove(const char *path) {
+ TCHAR pathUnc[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH);
return !DeleteFile(pathUnc);
}
@@ -128,15 +128,15 @@ int remove(const char* path) {
/* check out file access permissions */
int _access(const char *path, int mode) {
TCHAR fname[MAX_PATH];
- char fullname[MAX_PATH+1];
+ char fullname[MAX_PATH + 1];
if (path[0] != '\\' && path[0] != '/') {
getcwd(fullname, MAX_PATH);
strcat(fullname, "\\");
strcat(fullname, path);
- MultiByteToWideChar(CP_ACP, 0, fullname, -1, fname, sizeof(fname)/sizeof(TCHAR));
+ MultiByteToWideChar(CP_ACP, 0, fullname, -1, fname, sizeof(fname) / sizeof(TCHAR));
} else
- MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname)/sizeof(TCHAR));
+ MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname) / sizeof(TCHAR));
WIN32_FIND_DATA ffd;
HANDLE h = FindFirstFile(fname, &ffd);
@@ -144,10 +144,10 @@ int _access(const char *path, int mode) {
if (h == INVALID_HANDLE_VALUE) {
// WORKAROUND: WinCE 3.0 doesn't find paths ending in '\'
- if (path[strlen(path)-1] == '\\') {
+ if (path[strlen(path) - 1] == '\\') {
char p2[MAX_PATH];
- strncpy(p2, path, strlen(path)-1);
- p2[strlen(path) - 1]= '\0';
+ strncpy(p2, path, strlen(path) - 1);
+ p2[strlen(path) - 1] = '\0';
return _access(p2, mode);
} else
return -1; //Can't find file
@@ -158,7 +158,7 @@ int _access(const char *path, int mode) {
// hits for files that don't exist. TRIPLE checking for the same fname
// seems to weed out those false positives.
// Exhibited in kyra engine.
- HANDLE h = FindFirstFile(fname, &ffd);
+ h = FindFirstFile(fname, &ffd);
FindClose(h);
if (h == INVALID_HANDLE_VALUE)
return -1; //Can't find file
@@ -170,13 +170,13 @@ int _access(const char *path, int mode) {
return 0; //Always return success if target is directory and exists
}
switch (mode) {
- case 00: //Check existence
- return 0;
- case 06: //Check Read & Write permission
- case 02: //Check Write permission
- return ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? -1 : 0;
- case 04: //Check Read permission
- return 0; //Assume always have read permission
+ case 00: //Check existence
+ return 0;
+ case 06: //Check Read & Write permission
+ case 02: //Check Write permission
+ return ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? -1 : 0;
+ case 04: //Check Read permission
+ return 0; //Assume always have read permission
}
//Bad mode value supplied, return failure
return -1;
@@ -188,7 +188,7 @@ int _access(const char *path, int mode) {
char *strdup(const char *strSource) {
char *buffer;
size_z len = strlen(strSource) + 1;
- buffer = (char*)malloc(len);
+ buffer = (char *)malloc(len);
if (buffer)
memcpy(buffer, strSource, len);
return buffer;
@@ -199,25 +199,25 @@ char *strdup(const char *strSource) {
#ifndef __MINGW32CE__
int islower(int c) {
- return (c>='a' && c<='z');
+ return (c >= 'a' && c <= 'z');
}
int isspace(int c) {
- return (c==' ' || c=='\f' || c=='\n' || c=='\r' || c=='\t' || c=='\v');
+ return (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v');
}
int isalpha(int c) {
- return ((c>='a' && c<='z') || (c>='A' && c<='Z'));
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
}
int isalnum(int c) {
- return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'));
+ return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'));
}
int isprint(int c) {
//static const char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~";
//return (isalnum(c) || strchr(punct, c));
- return (32 <= c && c <= 126); // based on BSD manpage
+ return (32 <= c && c <= 126); // based on BSD manpage
}
#endif
diff --git a/backends/platform/wince/missing/time.h b/backends/platform/wince/missing/time.h
index f2bc5e4f89..a0ba6c246e 100644
--- a/backends/platform/wince/missing/time.h
+++ b/backends/platform/wince/missing/time.h
@@ -6,8 +6,7 @@
#include <stdlib.h>
#ifndef __MINGW32CE__
-struct tm
-{
+struct tm {
short tm_year;
short tm_mon;
short tm_mday;
@@ -23,8 +22,8 @@ struct tm
#define EXT_C
#endif
-EXT_C time_t time(time_t* dummy);
-EXT_C struct tm* localtime(time_t* dummy);
+EXT_C time_t time(time_t *dummy);
+EXT_C struct tm *localtime(time_t *dummy);
unsigned int clock();
diff --git a/backends/platform/wince/portdefs.h b/backends/platform/wince/portdefs.h
index cbf2006be2..8ad643946f 100644
--- a/backends/platform/wince/portdefs.h
+++ b/backends/platform/wince/portdefs.h
@@ -34,10 +34,10 @@ int isprint(int c);
int isspace(int c);
char *strrchr(const char *s, int c);
char *strdup(const char *s);
-int _stricmp( const char *string1, const char *string2 );
-int stricmp( const char *string1, const char *string2 );
-void assert( void* expression );
-void assert( int expression );
+int _stricmp(const char *string1, const char *string2);
+int stricmp(const char *string1, const char *string2);
+void assert(void *expression);
+void assert(int expression);
long int strtol(const char *nptr, char **endptr, int base);
char *_strdup(const char *s);
char *strpbrk(const char *s, const char *accept);
@@ -47,20 +47,20 @@ char *strpbrk(const char *s, const char *accept);
#ifdef _WIN32_WCE
#ifndef __GNUC__
- void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *));
- char *getcwd(char *buf, int size);
- typedef int ptrdiff_t;
- void GetCurrentDirectory(int len, char *buf);
- #define INVALID_FILE_ATTRIBUTES 0xffffffff
+void *bsearch(const void *, const void *, size_t, size_t, int (*x)(const void *, const void *));
+char *getcwd(char *buf, int size);
+typedef int ptrdiff_t;
+void GetCurrentDirectory(int len, char *buf);
+#define INVALID_FILE_ATTRIBUTES 0xffffffff
#else
- #include <math.h>
- #undef GetCurrentDirectory
- extern "C" void GetCurrentDirectory(int len, char *buf);
- #define stricmp _stricmp
- #define strnicmp _strnicmp
- #define snprintf _snprintf
- #define strdup _strdup
- #define fopen wce_fopen
+#include <math.h>
+#undef GetCurrentDirectory
+extern "C" void GetCurrentDirectory(int len, char *buf);
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+#define snprintf _snprintf
+#define strdup _strdup
+#define fopen wce_fopen
#endif
#include <windows.h>
@@ -75,12 +75,12 @@ char *strpbrk(const char *s, const char *accept);
//#include <direct.h>
#ifdef __MINGW32CE__
- void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *));
+void *bsearch(const void *, const void *, size_t, size_t, int (*x)(const void *, const void *));
#endif
int remove(const char *path);
int _access(const char *path, int mode);
-void drawError(char*);
+void drawError(char *);
#define vsnprintf _vsnprintf
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index ade90b2dfb..b829686cb0 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -23,6 +23,7 @@
*
*/
+
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
@@ -43,13 +44,12 @@
#include "audio/mixer_intern.h"
#include "audio/fmopl.h"
-#include "backends/timer/default/default-timer.h"
+#include "backends/timer/sdl/sdl-timer.h"
#include "gui/Actions.h"
#include "gui/KeysDialog.h"
#include "gui/message.h"
-#include "backends/platform/wince/resource.h"
#include "backends/platform/wince/CEActionsPocket.h"
#include "backends/platform/wince/CEActionsSmartphone.h"
#include "backends/platform/wince/CEgui/ItemAction.h"
@@ -60,39 +60,22 @@
#include "backends/platform/wince/CEException.h"
#include "backends/platform/wince/CEScaler.h"
-#ifdef USE_VORBIS
-#ifndef USE_TREMOR
-#include <vorbis/vorbisfile.h>
-#else
-#include <tremor/ivorbisfile.h>
-#endif
-#endif
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/mixer/wincesdl/wincesdl-mixer.h"
#ifdef DYNAMIC_MODULES
#include "backends/plugins/win32/win32-provider.h"
#endif
#ifdef __GNUC__
-extern "C" _CRTIMP FILE* __cdecl _wfreopen (const wchar_t*, const wchar_t*, FILE*);
+extern "C" _CRTIMP FILE *__cdecl _wfreopen(const wchar_t *, const wchar_t *, FILE *);
#endif
-#define SAMPLES_PER_SEC_OLD 11025
-#define SAMPLES_PER_SEC_NEW 22050
-
using namespace CEGUI;
// ********************************************************************************************
-// Internal GUI names
-
-#define NAME_MAIN_PANEL "MainPanel"
-#define NAME_PANEL_KEYBOARD "Keyboard"
-#define NAME_ITEM_OPTIONS "Options"
-#define NAME_ITEM_SKIP "Skip"
-#define NAME_ITEM_SOUND "Sound"
-#define NAME_ITEM_ORIENTATION "Orientation"
-#define NAME_ITEM_BINDKEYS "Bindkeys"
-
// stdin/err redirection
#define STDOUT_FNAME "\\scummvm_stdout.txt"
#define STDERR_FNAME "\\scummvm_stderr.txt"
@@ -106,34 +89,6 @@ bool OSystem_WINCE3::_soundMaster = true;
bool _isSmartphone = false;
bool _hasSmartphoneResolution = false;
-// Graphics mode consts
-
-// Low end devices 240x320
-
-static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = {
- {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
- {0, 0, 0}
-};
-
-// High end device 480x640
-
-static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = {
- {"1x", _s("Normal (no scaling)"), GFX_NORMAL},
- {"2x", "2x", GFX_DOUBLESIZE},
-#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :)
- {"2xsai", "2xSAI", GFX_2XSAI},
- {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI},
- {"supereagle", "SuperEagle", GFX_SUPEREAGLE},
-#endif
- {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X},
-#ifndef _MSC_VER
- {"hq2x", "HQ2x", GFX_HQ2X},
- {"tv2x", "TV2x", GFX_TV2X},
-#endif
- {"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
- {0, 0, 0}
-};
-
#define DEFAULT_CONFIG_FILE "scummvm.ini"
// ********************************************************************************************
@@ -144,7 +99,7 @@ bool isSmartphone() {
}
const TCHAR *ASCIItoUnicode(const char *str) {
- static TCHAR ustr[MAX_PATH]; // size good enough
+ static TCHAR ustr[MAX_PATH]; // size good enough
MultiByteToWideChar(CP_ACP, 0, str, strlen(str) + 1, ustr, sizeof(ustr) / sizeof(TCHAR));
return ustr;
@@ -173,7 +128,7 @@ int SDL_main(int argc, char **argv) {
// thanks to joostp and DJWillis
extern void (*__CTOR_LIST__)();
void (**constructor)() = &__CTOR_LIST__;
- constructor++; // First item in list of constructors has special meaning (platform dependent), ignore it.
+ constructor++; // First item in list of constructors has special meaning (platform dependent), ignore it.
while (*constructor) {
(*constructor)();
constructor++;
@@ -238,10 +193,10 @@ int SDL_main(int argc, char **argv) {
res = scummvm_main(argc, argv);
// Free OSystem
- delete (OSystem_WINCE3 *)g_system;
+ delete(OSystem_WINCE3 *)g_system;
#if !defined(DEBUG) && !defined(__GNUC__)
}
- __except (handleException(GetExceptionInformation())) {
+ __except(handleException(GetExceptionInformation())) {
}
#endif
@@ -264,22 +219,22 @@ int console_main(int argc, char *argv[]) {
char *bufp, *appname;
appname = argv[0];
- if ( (bufp=strrchr(argv[0], '\\')) != NULL )
+ if ((bufp = strrchr(argv[0], '\\')) != NULL)
appname = bufp + 1;
- else if ( (bufp=strrchr(argv[0], '/')) != NULL )
+ else if ((bufp = strrchr(argv[0], '/')) != NULL)
appname = bufp + 1;
- if ( (bufp=strrchr(appname, '.')) == NULL )
+ if ((bufp = strrchr(appname, '.')) == NULL)
n = strlen(appname);
else
- n = (bufp-appname);
+ n = (bufp - appname);
bufp = (char *) alloca(n + 1);
strncpy(bufp, appname, n);
bufp[n] = '\0';
appname = bufp;
- if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
+ if (SDL_Init(SDL_INIT_NOPARACHUTE) < 0) {
error("WinMain() error: %d", SDL_GetError());
return(FALSE);
}
@@ -344,31 +299,31 @@ int dynamic_modules_main(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int
int nLen;
if (wcsncmp(szCmdLine, TEXT("\\"), 1)) {
- nLen = wcslen(szCmdLine)+128+1;
- bufp = (wchar_t *) alloca(nLen*2);
- wcscpy (bufp, TEXT("\""));
- GetModuleFileName(NULL, bufp+1, 128-3);
- wcscpy (bufp+wcslen(bufp), TEXT("\" "));
- wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
+ nLen = wcslen(szCmdLine) + 128 + 1;
+ bufp = (wchar_t *) alloca(nLen * 2);
+ wcscpy(bufp, TEXT("\""));
+ GetModuleFileName(NULL, bufp + 1, 128 - 3);
+ wcscpy(bufp + wcslen(bufp), TEXT("\" "));
+ wcsncpy(bufp + wcslen(bufp), szCmdLine, nLen - wcslen(bufp));
} else
bufp = szCmdLine;
- nLen = wcslen(bufp)+1;
+ nLen = wcslen(bufp) + 1;
cmdline = (char *) alloca(nLen);
WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
// Parse command line into argv and argc
argc = ParseCommandLine(cmdline, NULL);
- argv = (char **) alloca((argc+1)*(sizeof *argv));
+ argv = (char **) alloca((argc + 1) * (sizeof * argv));
ParseCommandLine(cmdline, argv);
// fix gdb-emulator combo
while (argc > 1 && !strstr(argv[0], ".exe")) {
OutputDebugString(TEXT("SDL: gdb argv[0] fixup\n"));
- *(argv[1]-1) = ' ';
+ *(argv[1] - 1) = ' ';
int i;
- for (i=1; i<argc; i++)
- argv[i] = argv[i+1];
+ for (i = 1; i < argc; i++)
+ argv[i] = argv[i + 1];
argc--;
}
@@ -380,7 +335,6 @@ int dynamic_modules_main(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int
// ********************************************************************************************
-
// ********************************************************************************************
void pumpMessages() {
@@ -407,47 +361,53 @@ static Uint32 timer_handler_wrapper(Uint32 interval) {
}
void OSystem_WINCE3::initBackend() {
- // Instantiate our own sound mixer
- // mixer init is rerun when a game engine is selected.
- setupMixer();
+
+ assert(!_inited);
+
+ // Create the backend custom managers
+ if (_eventSource == 0)
+ _eventSource = new WINCESdlEventSource();
+
+ if (_mixerManager == 0) {
+ _mixerManager = new WINCESdlMixerManager();
+
+ // Setup and start mixer
+ _mixerManager->init();
+ }
+
+ if (_graphicsManager == 0)
+ _graphicsManager = new WINCESdlGraphicsManager(_eventSource);
+
+ ((WINCESdlEventSource *)_eventSource)->init((WINCESdlGraphicsManager *)_graphicsManager);
// Create the timer. CE SDL does not support multiple timers (SDL_AddTimer).
// We work around this by using the SetTimer function, since we only use
// one timer in scummvm (for the time being)
_timer = _int_timer = new DefaultTimerManager();
- _timerID = NULL; // OSystem_SDL will call removetimer with this, it's ok
+ //_timerID = NULL; // OSystem_SDL will call removetimer with this, it's ok
SDL_SetTimer(10, &timer_handler_wrapper);
// Chain init
OSystem_SDL::initBackend();
- // Query SDL for screen size and init screen dependent stuff
- OSystem_WINCE3::initScreenInfos();
- _isSmartphone = CEDevice::isSmartphone();
- create_toolbar();
- _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone();
- if (_hasSmartphoneResolution)
- _panelVisible = false; // init correctly in smartphones
-
// Initialize global key mapping
GUI::Actions::init();
GUI_Actions::Instance()->initInstanceMain(this);
- if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version
+ if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version
warning("Setting default action mappings");
- GUI_Actions::Instance()->saveMapping(); // write defaults
+ GUI_Actions::Instance()->saveMapping(); // write defaults
}
- loadDeviceConfiguration();
+ // Call parent implementation of this method
+ //OSystem_SDL::initBackend();
+
+ _inited = true;
}
int OSystem_WINCE3::getScreenWidth() {
return _platformScreenWidth;
}
-int OSystem_WINCE3::getScreenHeight() {
- return _platformScreenHeight;
-}
-
void OSystem_WINCE3::initScreenInfos() {
// sdl port ensures that we use correctly full screen
_isOzone = 0;
@@ -457,6 +417,10 @@ void OSystem_WINCE3::initScreenInfos() {
_platformScreenHeight = r[0]->h;
}
+int OSystem_WINCE3::getScreenHeight() {
+ return _platformScreenHeight;
+}
+
bool OSystem_WINCE3::isOzone() {
return _isOzone;
}
@@ -473,496 +437,37 @@ Common::String OSystem_WINCE3::getDefaultConfigFileName() {
OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(),
- _orientationLandscape(0), _newOrientation(0), _panelInitialized(false), _canBeAspectScaled(false),
- _panelVisible(true), _panelStateForced(false), _forceHideMouse(false), _unfilteredkeys(false),
- _freeLook(false), _forcePanelInvisible(false), _toolbarHighDrawn(false), _zoomUp(false), _zoomDown(false),
- _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false), _noDoubleTapRMB(false),
- _saveToolbarState(false), _saveActiveToolbar(NAME_MAIN_PANEL), _rbutton(false), _hasfocus(true),
- _usesEmulatedMouse(false), _mouseBackupOld(NULL), _mouseBackupToolbar(NULL), _mouseBackupDim(0)
-{
- memset(&_mouseCurState, 0, sizeof(_mouseCurState));
- if (_isSmartphone) {
- _mouseCurState.x = 20;
- _mouseCurState.y = 20;
- }
-
+ _forcePanelInvisible(false) {
+ // Initialze File System Factory
+ _fsFactory = new WindowsFilesystemFactory();
_mixer = 0;
- _screen = NULL;
}
-void OSystem_WINCE3::swap_panel_visibility() {
- //if (!_forcePanelInvisible && !_panelStateForced) {
- if (_zoomDown || _zoomUp) return;
-
- if (_panelVisible) {
- if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD)
- _panelVisible = !_panelVisible;
- else
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
- } else {
- _toolbarHandler.setActive(NAME_MAIN_PANEL);
- _panelVisible = !_panelVisible;
- }
- _toolbarHandler.setVisible(_panelVisible);
- _toolbarHighDrawn = false;
-
- if (_videoMode.screenHeight > 240)
- addDirtyRect(0, 400, 640, 80);
- else
- addDirtyRect(0, 200, 320, 40);
-
- if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
- internUpdateScreen();
- else {
- update_scalers();
- hotswapGFXMode();
- }
- //}
+OSystem_WINCE3::~OSystem_WINCE3() {
+ delete _fsFactory;
+ delete _mixer;
}
-void OSystem_WINCE3::swap_panel() {
- _toolbarHighDrawn = false;
- //if (!_panelStateForced) {
- if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible)
- _toolbarHandler.setActive(NAME_MAIN_PANEL);
- else
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
-
- if (_videoMode.screenHeight > 240)
- addDirtyRect(0, 400, 640, 80);
- else
- addDirtyRect(0, 200, 320, 40);
-
- _toolbarHandler.setVisible(true);
- if (!_panelVisible) {
- _panelVisible = true;
- update_scalers();
- hotswapGFXMode();
- }
- //}
-}
-
-void OSystem_WINCE3::swap_smartphone_keyboard() {
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
- _panelVisible = !_panelVisible;
- _toolbarHandler.setVisible(_panelVisible);
- if (_videoMode.screenHeight > 240)
- addDirtyRect(0, 0, 640, 80);
- else
- addDirtyRect(0, 0, 320, 40);
- internUpdateScreen();
-}
-
-void OSystem_WINCE3::smartphone_rotate_display() {
- _orientationLandscape = _newOrientation = _orientationLandscape == 1 ? 2 : 1;
- ConfMan.setInt("landscape", _orientationLandscape);
- ConfMan.flushToDisk();
- hotswapGFXMode();
+FilesystemFactory *OSystem_WINCE3::getFilesystemFactory() {
+ return _fsFactory;
}
void OSystem_WINCE3::swap_sound_master() {
_soundMaster = !_soundMaster;
- if (_toolbarHandler.activeName() == NAME_MAIN_PANEL)
- _toolbarHandler.forceRedraw(); // redraw sound icon
-}
-
-void OSystem_WINCE3::add_right_click(bool pushed) {
- int x, y;
- retrieve_mouse_location(x, y);
- EventsBuffer::simulateMouseRightClick(x, y, pushed);
-}
-
-void OSystem_WINCE3::swap_mouse_visibility() {
- _forceHideMouse = !_forceHideMouse;
- if (_forceHideMouse)
- undrawMouse();
-}
-
-void OSystem_WINCE3::swap_freeLook() {
- _freeLook = !_freeLook;
-}
-void OSystem_WINCE3::swap_zoom_up() {
- if (_zoomUp) {
- // restore visibility
- _toolbarHandler.setVisible(_saveToolbarZoom);
- // restore scaler
- _scaleFactorYd = 2;
- _scalerProc = DownscaleAllByHalf;
- _zoomUp = false;
- _zoomDown = false;
- } else {
- // only active if running on a PocketPC
- if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
- return;
- if (_scalerProc == DownscaleAllByHalf) {
- _saveToolbarZoom = _toolbarHandler.visible();
- _toolbarHandler.setVisible(false);
- // set zoom scaler
- _scaleFactorYd = 1;
- _scalerProc = DownscaleHorizByHalf;
- }
+ //WINCESdlGraphicsManager _graphicsManager
- _zoomDown = false;
- _zoomUp = true;
- }
- // redraw whole screen
- addDirtyRect(0, 0, 640, 480);
- internUpdateScreen();
+ if (((WINCESdlGraphicsManager *)_graphicsManager)->_toolbarHandler.activeName() == NAME_MAIN_PANEL)
+ ((WINCESdlGraphicsManager *)_graphicsManager)->_toolbarHandler.forceRedraw(); // redraw sound icon
}
-void OSystem_WINCE3::swap_zoom_down() {
- if (_zoomDown) {
- // restore visibility
- _toolbarHandler.setVisible(_saveToolbarZoom);
- // restore scaler
- _scaleFactorYd = 2;
- _scalerProc = DownscaleAllByHalf;
- _zoomDown = false;
- _zoomUp = false;
- } else {
- // only active if running on a PocketPC
- if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf)
- return;
- if (_scalerProc == DownscaleAllByHalf) {
- _saveToolbarZoom = _toolbarHandler.visible();
- _toolbarHandler.setVisible(false);
- // set zoom scaler
- _scaleFactorYd = 1;
- _scalerProc = DownscaleHorizByHalf;
- }
-
- _zoomUp = false;
- _zoomDown = true;
- }
- // redraw whole screen
- addDirtyRect(0, 0, 640, 480);
- internUpdateScreen();
-}
-
-// Smartphone actions
-void OSystem_WINCE3::initZones() {
- int i;
-
- _currentZone = 0;
- for (i = 0; i < TOTAL_ZONES; i++) {
- _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)) * _scaleFactorXm / _scaleFactorXd;
- _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)) * _scaleFactorYm / _scaleFactorYd;
- }
-}
-
-void OSystem_WINCE3::loadDeviceConfigurationElement(String element, int &value, int defaultValue) {
- value = ConfMan.getInt(element, ConfMan.kApplicationDomain);
- if (!value) {
- value = defaultValue;
- ConfMan.setInt(element, value, ConfMan.kApplicationDomain);
- }
-}
-
-void OSystem_WINCE3::loadDeviceConfiguration() {
- loadDeviceConfigurationElement("repeatTrigger", _keyRepeatTrigger, 200);
- loadDeviceConfigurationElement("repeatX", _repeatX, 4);
- loadDeviceConfigurationElement("repeatY", _repeatY, 4);
- loadDeviceConfigurationElement("stepX1", _stepX1, 2);
- loadDeviceConfigurationElement("stepX2", _stepX2, 10);
- loadDeviceConfigurationElement("stepX3", _stepX3, 40);
- loadDeviceConfigurationElement("stepY1", _stepY1, 2);
- loadDeviceConfigurationElement("stepY2", _stepY2, 10);
- loadDeviceConfigurationElement("stepY3", _stepY3, 20);
- ConfMan.flushToDisk();
-}
-
-void OSystem_WINCE3::add_left_click(bool pushed) {
- int x, y;
- retrieve_mouse_location(x, y);
- EventsBuffer::simulateMouseLeftClick(x, y, pushed);
-}
-
-void OSystem_WINCE3::move_cursor_up() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatY)
- y -= _stepY3;
- else if (_keyRepeat)
- y -= _stepY2;
- else
- y -= _stepY1;
-
- if (y < 0)
- y = 0;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::move_cursor_down() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatY)
- y += _stepY3;
- else if (_keyRepeat)
- y += _stepY2;
- else
- y += _stepY1;
-
- if (y > _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd)
- y = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::move_cursor_left() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatX)
- x -= _stepX3;
- else if (_keyRepeat)
- x -= _stepX2;
- else
- x -= _stepX1;
-
- if (x < 0)
- x = 0;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::move_cursor_right() {
- int x, y;
- _usesEmulatedMouse = true;
- retrieve_mouse_location(x, y);
- if (_keyRepeat > _repeatX)
- x += _stepX3;
- else if (_keyRepeat)
- x += _stepX2;
- else
- x += _stepX1;
-
- if (x > _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd)
- x = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
-
- EventsBuffer::simulateMouseMove(x, y);
-}
-
-void OSystem_WINCE3::switch_zone() {
- int x, y;
- int i;
- retrieve_mouse_location(x, y);
-
- for (i = 0; i < TOTAL_ZONES; i++)
- if (x >= _zones[i].x && y >= _zones[i].y &&
- x <= _zones[i].x + _zones[i].width && y <= _zones[i].y + _zones[i].height) {
- _mouseXZone[i] = x;
- _mouseYZone[i] = y;
- break;
- }
- _currentZone = i + 1;
- if (_currentZone >= TOTAL_ZONES)
- _currentZone = 0;
-
- EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]);
-}
-
-void OSystem_WINCE3::create_toolbar() {
- PanelKeyboard *keyboard;
-
- // Add the keyboard
- keyboard = new PanelKeyboard(PANEL_KEYBOARD);
- _toolbarHandler.add(NAME_PANEL_KEYBOARD, *keyboard);
- _toolbarHandler.setVisible(false);
-}
-
-void OSystem_WINCE3::setupMixer() {
- SDL_AudioSpec desired;
- int thread_priority;
-
- uint32 sampleRate = compute_sample_rate();
- if (sampleRate == 0)
- warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work");
- else if (_mixer && _mixer->getOutputRate() == sampleRate) {
- debug(1, "Skipping sound mixer re-init: samplerate is good");
- return;
- }
-
- memset(&desired, 0, sizeof(desired));
- desired.freq = sampleRate;
- desired.format = AUDIO_S16SYS;
- desired.channels = 2;
- desired.samples = 128;
- desired.callback = private_sound_proc;
- desired.userdata = this;
-
- // Create the mixer instance
- if (_mixer == 0)
- _mixer = new Audio::MixerImpl(this, sampleRate);
-
- // Add sound thread priority
- if (!ConfMan.hasKey("sound_thread_priority"))
- thread_priority = THREAD_PRIORITY_NORMAL;
- else
- thread_priority = ConfMan.getInt("sound_thread_priority");
-
- desired.thread_priority = thread_priority;
-
- SDL_CloseAudio();
- if (SDL_OpenAudio(&desired, NULL) != 0) {
- warning("Could not open audio device: %s", SDL_GetError());
- _mixer->setReady(false);
-
- } else {
- debug(1, "Sound opened OK, mixing at %d Hz", sampleRate);
-
- // Re-create mixer to match the output rate
- int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
- int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
- int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
- int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
- delete _mixer;
- _mixer = new Audio::MixerImpl(this, sampleRate);
- _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1);
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3);
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4);
- _mixer->setReady(true);
- SDL_PauseAudio(0);
- }
-}
-
-void OSystem_WINCE3::private_sound_proc(void *param, byte *buf, int len) {
- OSystem_WINCE3 *this_ = (OSystem_WINCE3 *)param;
- assert(this_);
-
- if (this_->_mixer)
- this_->_mixer->mixCallback(buf, len);
- if (!_soundMaster)
- memset(buf, 0, len);
-}
-
-#ifdef USE_VORBIS
-bool OSystem_WINCE3::checkOggHighSampleRate() {
- char trackFile[255];
- FILE *testFile;
- OggVorbis_File *test_ov_file = new OggVorbis_File;
-
- // FIXME: The following sprintf assumes that "path" is always
- // terminated by a path separator. This is *not* true in general.
- // This code really should check for the path separator, or even
- // better, use the FSNode API.
- sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str());
- // Check if we have an OGG audio track
- testFile = fopen(trackFile, "rb");
- if (testFile) {
- if (!ov_open(testFile, test_ov_file, NULL, 0)) {
- bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050);
- ov_clear(test_ov_file);
- delete test_ov_file;
- return highSampleRate;
- }
- }
-
- // Do not test for OGG samples - too big and too slow anyway :)
-
- delete test_ov_file;
- return false;
-}
-#endif
-
-uint32 OSystem_WINCE3::compute_sample_rate() {
- uint32 sampleRate;
-
- // Force at least medium quality FM synthesis for FOTAQ
- Common::String gameid(ConfMan.get("gameid"));
- if (gameid == "queen") {
- if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) ||
- (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) {
- ConfMan.setBool("FM_medium_quality", true);
- ConfMan.flushToDisk();
- }
- }
- // See if the output frequency is forced by the game
- if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi")
- sampleRate = SAMPLES_PER_SEC_NEW;
- else {
- if (ConfMan.hasKey("high_sample_rate") && ConfMan.getBool("high_sample_rate"))
- sampleRate = SAMPLES_PER_SEC_NEW;
- else
- sampleRate = SAMPLES_PER_SEC_OLD;
- }
-
-#ifdef USE_VORBIS
- // Modify the sample rate on the fly if OGG is involved
- if (sampleRate == SAMPLES_PER_SEC_OLD)
- if (checkOggHighSampleRate())
- sampleRate = SAMPLES_PER_SEC_NEW;
-#endif
-
- return sampleRate;
-}
void OSystem_WINCE3::engineInit() {
check_mappings(); // called here to initialize virtual keys handling
//update_game_settings();
// finalize mixer init
- setupMixer();
-}
-
-const OSystem::GraphicsMode *OSystem_WINCE3::getSupportedGraphicsModes() const {
- if (CEDevice::hasWideResolution())
- return s_supportedGraphicsModesHigh;
- else
- return s_supportedGraphicsModesLow;
-}
-
-bool OSystem_WINCE3::hasFeature(Feature f) {
- return (f == kFeatureVirtualKeyboard);
-}
-
-void OSystem_WINCE3::setFeatureState(Feature f, bool enable) {
- switch (f) {
- case kFeatureFullscreenMode:
- return;
-
- case kFeatureVirtualKeyboard:
- if (_hasSmartphoneResolution)
- return;
- _toolbarHighDrawn = false;
- if (enable) {
- _panelStateForced = true;
- if (!_toolbarHandler.visible()) swap_panel_visibility();
- //_saveToolbarState = _toolbarHandler.visible();
- _saveActiveToolbar = _toolbarHandler.activeName();
- _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
- _toolbarHandler.setVisible(true);
- } else
- if (_panelStateForced) {
- _panelStateForced = false;
- _toolbarHandler.setActive(_saveActiveToolbar);
- //_toolbarHandler.setVisible(_saveToolbarState);
- }
- return;
-
- case kFeatureDisableKeyFiltering:
- if (_hasSmartphoneResolution)
- _unfilteredkeys = enable;
- return;
-
- default:
- OSystem_SDL::setFeatureState(f, enable);
- }
-}
-
-bool OSystem_WINCE3::getFeatureState(Feature f) {
- switch (f) {
- case kFeatureFullscreenMode:
- return false;
- case kFeatureVirtualKeyboard:
- return (_panelStateForced);
- default:
- return OSystem_SDL::getFeatureState(f);
- }
+ _mixerManager->init();
}
void OSystem_WINCE3::check_mappings() {
@@ -974,7 +479,7 @@ void OSystem_WINCE3::check_mappings() {
return;
GUI_Actions::Instance()->initInstanceGame();
- instance = (CEActionsPocket*)GUI_Actions::Instance();
+ instance = (CEActionsPocket *)GUI_Actions::Instance();
// Some games need to map the right click button, signal it here if it wasn't done
if (instance->needsRightClickMapping()) {
@@ -1014,1472 +519,39 @@ void OSystem_WINCE3::check_mappings() {
// Extra warning for Zak Mc Kracken
if (strncmp(gameid.c_str(), "zak", 3) == 0 &&
- !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) {
+ !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) {
GUI::MessageDialog alert(_("Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"));
alert.runModal();
}
}
-void OSystem_WINCE3::update_game_settings() {
- Common::String gameid(ConfMan.get("gameid"));
-
- // Finish panel initialization
- if (!_panelInitialized && !gameid.empty()) {
- Panel *panel;
- _panelInitialized = true;
- // Add the main panel
- panel = new Panel(0, 32);
- panel->setBackground(IMAGE_PANEL);
- // Save
- panel->add(NAME_ITEM_OPTIONS, new ItemAction(ITEM_OPTIONS, POCKET_ACTION_SAVE));
- // Skip
- panel->add(NAME_ITEM_SKIP, new ItemAction(ITEM_SKIP, POCKET_ACTION_SKIP));
- // sound
- panel->add(NAME_ITEM_SOUND, new ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &_soundMaster));
- // bind keys
- panel->add(NAME_ITEM_BINDKEYS, new ItemAction(ITEM_BINDKEYS, POCKET_ACTION_BINDKEYS));
- // portrait/landscape - screen dependent
- // FIXME : will still display the portrait/landscape icon when using a scaler (but will be disabled)
- if (ConfMan.hasKey("landscape")) {
- if (ConfMan.get("landscape")[0] > 57) {
- _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
- //ConfMan.removeKey("landscape", "");
- ConfMan.setInt("landscape", _orientationLandscape);
- } else
- _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
- } else {
- _newOrientation = _orientationLandscape = 0;
- }
- panel->add(NAME_ITEM_ORIENTATION, new ItemSwitch(ITEM_VIEW_LANDSCAPE, ITEM_VIEW_PORTRAIT, &_newOrientation, 2));
- _toolbarHandler.add(NAME_MAIN_PANEL, *panel);
- _toolbarHandler.setActive(NAME_MAIN_PANEL);
- _toolbarHandler.setVisible(true);
-
- if (_videoMode.mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) {
- setGraphicsMode(GFX_NORMAL);
- hotswapGFXMode();
- }
-
- if (_hasSmartphoneResolution)
- panel->setVisible(false);
-
- _saveToolbarState = true;
- }
-
- if (ConfMan.hasKey("no_doubletap_rightclick"))
- _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick");
-}
-
-void OSystem_WINCE3::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
- if (_hasSmartphoneResolution && h == 240)
- h = 200; // mainly for the launcher
-
- if (_isSmartphone && !ConfMan.hasKey("landscape")) {
- ConfMan.setInt("landscape", 1);
- ConfMan.flushToDisk();
- }
-
- _canBeAspectScaled = false;
- if (w == 320 && h == 200 && !_hasSmartphoneResolution) {
- _canBeAspectScaled = true;
- h = 240; // use the extra 40 pixels height for the toolbar
- }
-
- if (h == 400) // touche engine fixup
- h += 80;
-
- if (!_hasSmartphoneResolution) {
- if (h == 240)
- _toolbarHandler.setOffset(200);
- else
- _toolbarHandler.setOffset(400);
- } else {
- if (h == 240)
- _toolbarHandler.setOffset(200);
- else // 176x220
- _toolbarHandler.setOffset(0);
- }
-
- if (w != (uint) _videoMode.screenWidth || h != (uint) _videoMode.screenHeight)
- _scalersChanged = false;
-
- _videoMode.overlayWidth = w;
- _videoMode.overlayHeight = h;
-
- OSystem_SDL::initSize(w, h, format);
-
- if (_scalersChanged) {
- unloadGFXMode();
- loadGFXMode();
- _scalersChanged = false;
- }
-
- update_game_settings();
-}
-
-
-int OSystem_WINCE3::getDefaultGraphicsMode() const {
- return GFX_NORMAL;
-}
-
void OSystem_WINCE3::setGraphicsModeIntern() {
// Scalers have been pre-selected for the desired mode.
// No further tuning required.
}
-bool OSystem_WINCE3::update_scalers() {
- _videoMode.aspectRatioCorrection = false;
-
- if (CEDevice::hasPocketPCResolution()) {
- if (_videoMode.mode != GFX_NORMAL)
- return false;
-
- if ((!_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth))
- || CEDevice::hasSquareQVGAResolution() ) {
- if (getScreenWidth() != 320) {
- _scaleFactorXm = 3;
- _scaleFactorXd = 4;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = DownscaleHorizByThreeQuarters;
- } else {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = Normal1x;
- }
- } else if ( _orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
- if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 6;
- _scaleFactorYd = 5;
- _scalerProc = Normal1xAspect;
- _videoMode.aspectRatioCorrection = true;
- } else {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = Normal1x;
- }
- } else if (_videoMode.screenWidth == 640 && !(isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
- _scaleFactorXm = 1;
- _scaleFactorXd = 2;
- _scaleFactorYm = 1;
- _scaleFactorYd = 2;
- _scalerProc = DownscaleAllByHalf;
- } else if (_videoMode.screenWidth == 640 && (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
- _scaleFactorXm = 1;
- _scaleFactorXd = 1;
- _scaleFactorYm = 1;
- _scaleFactorYd = 1;
- _scalerProc = Normal1x;
- }
-
- return true;
- } else if (CEDevice::hasWideResolution()) {
-#ifdef USE_ARM_SCALER_ASM
- if ( _videoMode.mode == GFX_DOUBLESIZE && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth) ) {
- if ( !_panelVisible && !_overlayVisible && _canBeAspectScaled ) {
- _scaleFactorXm = 2;
- _scaleFactorXd = 1;
- _scaleFactorYm = 12;
- _scaleFactorYd = 5;
- _scalerProc = Normal2xAspect;
- _videoMode.aspectRatioCorrection = true;
- } else if ( (_panelVisible || _overlayVisible) && _canBeAspectScaled ) {
- _scaleFactorXm = 2;
- _scaleFactorXd = 1;
- _scaleFactorYm = 2;
- _scaleFactorYd = 1;
- _scalerProc = Normal2x;
- }
- return true;
- }
-#endif
- } else if (CEDevice::hasSmartphoneResolution()) {
- if (_videoMode.mode != GFX_NORMAL)
- return false;
-
- if (_videoMode.screenWidth > 320)
- error("Game resolution not supported on Smartphone");
-#ifdef ARM
- _scaleFactorXm = 11;
- _scaleFactorXd = 16;
-#else
- _scaleFactorXm = 2;
- _scaleFactorXd = 3;
-#endif
- _scaleFactorYm = 7;
- _scaleFactorYd = 8;
- _scalerProc = SmartphoneLandscape;
- initZones();
- return true;
- }
-
- return false;
-}
-
-bool OSystem_WINCE3::setGraphicsMode(int mode) {
-
- Common::StackLock lock(_graphicsMutex);
- int oldScaleFactorXm = _scaleFactorXm;
- int oldScaleFactorXd = _scaleFactorXd;
- int oldScaleFactorYm = _scaleFactorYm;
- int oldScaleFactorYd = _scaleFactorYd;
-
- _scaleFactorXm = -1;
- _scaleFactorXd = -1;
- _scaleFactorYm = -1;
- _scaleFactorYd = -1;
-
- if (ConfMan.hasKey("landscape"))
- if (ConfMan.get("landscape")[0] > 57) {
- _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
- ConfMan.setInt("landscape", _orientationLandscape);
- } else
- _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
- else
- _newOrientation = _orientationLandscape = 0;
-
- if (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640) && mode)
- _scaleFactorXm = -1;
-
- if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape)
- _videoMode.mode = GFX_NORMAL;
- else
- _videoMode.mode = mode;
-
- if (_scaleFactorXm < 0) {
- /* Standard scalers, from the SDL backend */
- switch (_videoMode.mode) {
- case GFX_NORMAL:
- _videoMode.scaleFactor = 1;
- _scalerProc = Normal1x;
- break;
- case GFX_DOUBLESIZE:
- _videoMode.scaleFactor = 2;
- _scalerProc = Normal2x;
- break;
- case GFX_TRIPLESIZE:
- _videoMode.scaleFactor = 3;
- _scalerProc = Normal3x;
- break;
- case GFX_2XSAI:
- _videoMode.scaleFactor = 2;
- _scalerProc = _2xSaI;
- break;
- case GFX_SUPER2XSAI:
- _videoMode.scaleFactor = 2;
- _scalerProc = Super2xSaI;
- break;
- case GFX_SUPEREAGLE:
- _videoMode.scaleFactor = 2;
- _scalerProc = SuperEagle;
- break;
- case GFX_ADVMAME2X:
- _videoMode.scaleFactor = 2;
- _scalerProc = AdvMame2x;
- break;
- case GFX_ADVMAME3X:
- _videoMode.scaleFactor = 3;
- _scalerProc = AdvMame3x;
- break;
-#ifdef USE_HQ_SCALERS
- case GFX_HQ2X:
- _videoMode.scaleFactor = 2;
- _scalerProc = HQ2x;
- break;
- case GFX_HQ3X:
- _videoMode.scaleFactor = 3;
- _scalerProc = HQ3x;
- break;
-#endif
- case GFX_TV2X:
- _videoMode.scaleFactor = 2;
- _scalerProc = TV2x;
- break;
- case GFX_DOTMATRIX:
- _videoMode.scaleFactor = 2;
- _scalerProc = DotMatrix;
- break;
-
- default:
- error("unknown gfx mode %d", mode);
- }
- }
-
- // Check if the scaler can be accepted, if not get back to normal scaler
- if (_videoMode.scaleFactor && ((_videoMode.scaleFactor * _videoMode.screenWidth > getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenWidth > getScreenHeight())
- || (_videoMode.scaleFactor * _videoMode.screenHeight > getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenHeight > getScreenHeight()))) {
- _videoMode.scaleFactor = 1;
- _scalerProc = Normal1x;
- }
-
- // Common scaler system was used
- if (_scaleFactorXm < 0) {
- _scaleFactorXm = _videoMode.scaleFactor;
- _scaleFactorXd = 1;
- _scaleFactorYm = _videoMode.scaleFactor;
- _scaleFactorYd = 1;
- }
-
- _forceFull = true;
-
- if (oldScaleFactorXm != _scaleFactorXm ||
- oldScaleFactorXd != _scaleFactorXd ||
- oldScaleFactorYm != _scaleFactorYm ||
- oldScaleFactorYd != _scaleFactorYd) {
- _scalersChanged = true;
- }
- else
- _scalersChanged = false;
-
-
- return true;
-
-}
-
-bool OSystem_WINCE3::loadGFXMode() {
- int displayWidth;
- int displayHeight;
- unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE;
-
- _videoMode.fullscreen = true; // forced
- _forceFull = true;
-
- _tmpscreen = NULL;
-
- // Recompute scalers if necessary
- update_scalers();
-
- // Create the surface that contains the 8 bit game data
- _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
- if (_screen == NULL)
- error("_screen failed (%s)", SDL_GetError());
-
- // Create the surface that contains the scaled graphics in 16 bit mode
- // Always use full screen mode to have a "clean screen"
- if (!_videoMode.aspectRatioCorrection) {
- displayWidth = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd;
- displayHeight = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd;
- } else {
- displayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- displayHeight = _videoMode.screenHeight* _videoMode.scaleFactor;
- }
-
- switch (_orientationLandscape) {
- case 1:
- flags |= SDL_LANDSCVIDEO;
- break;
- case 2:
- flags |= SDL_INVLNDVIDEO;
- break;
- default:
- flags |= SDL_PORTRTVIDEO;
- }
- _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags);
-
- if (_hwscreen == NULL) {
- warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
- quit();
- }
-
- // see what orientation sdl finally accepted
- if (_hwscreen->flags & SDL_PORTRTVIDEO)
- _orientationLandscape = _newOrientation = 0;
- else if (_hwscreen->flags & SDL_LANDSCVIDEO)
- _orientationLandscape = _newOrientation = 1;
- else
- _orientationLandscape = _newOrientation = 2;
-
- // Create the surface used for the graphics in 16 bit before scaling, and also the overlay
- // Distinguish 555 and 565 mode
- if (_hwscreen->format->Rmask == 0x7C00)
- InitScalers(555);
- else
- InitScalers(565);
- _overlayFormat.bytesPerPixel = _hwscreen->format->BytesPerPixel;
- _overlayFormat.rLoss = _hwscreen->format->Rloss;
- _overlayFormat.gLoss = _hwscreen->format->Gloss;
- _overlayFormat.bLoss = _hwscreen->format->Bloss;
- _overlayFormat.aLoss = _hwscreen->format->Aloss;
- _overlayFormat.rShift = _hwscreen->format->Rshift;
- _overlayFormat.gShift = _hwscreen->format->Gshift;
- _overlayFormat.bShift = _hwscreen->format->Bshift;
- _overlayFormat.aShift = _hwscreen->format->Ashift;
-
- // Need some extra bytes around when using 2xSaI
- _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
-
- if (_tmpscreen == NULL)
- error("_tmpscreen creation failed (%s)", SDL_GetError());
-
- // Overlay
- if (CEDevice::hasDesktopResolution()) {
- _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0);
- if (_overlayscreen == NULL)
- error("_overlayscreen failed (%s)", SDL_GetError());
- _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0);
- if (_tmpscreen2 == NULL)
- error("_tmpscreen2 failed (%s)", SDL_GetError());
- } else {
- _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, 0, 0, 0, 0);
- if (_overlayscreen == NULL)
- error("_overlayscreen failed (%s)", SDL_GetError());
- _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, 0, 0, 0, 0);
- if (_tmpscreen2 == NULL)
- error("_tmpscreen2 failed (%s)", SDL_GetError());
- }
-
- // Toolbar
- _toolbarHighDrawn = false;
- uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16)); // *not* leaking memory here
- _toolbarLow = SDL_CreateRGBSurfaceFrom(toolbar_screen, 320, 40, 16, 320 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
-
- if (_toolbarLow == NULL)
- error("_toolbarLow failed (%s)", SDL_GetError());
-
- if (_videoMode.screenHeight > 240) {
- uint16 *toolbar_screen = (uint16 *)calloc(640 * 80, sizeof(uint16));
- _toolbarHigh = SDL_CreateRGBSurfaceFrom(toolbar_screen, 640, 80, 16, 640 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask);
-
- if (_toolbarHigh == NULL)
- error("_toolbarHigh failed (%s)", SDL_GetError());
- } else
- _toolbarHigh = NULL;
-
-
- // keyboard cursor control, some other better place for it?
- _km.x_max = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd - 1;
- _km.y_max = _videoMode.screenHeight * _scaleFactorXm / _scaleFactorXd - 1;
- _km.delay_time = 25;
- _km.last_time = 0;
-
- return true;
-}
-
-void OSystem_WINCE3::unloadGFXMode() {
- if (_screen) {
- SDL_FreeSurface(_screen);
- _screen = NULL;
- }
-
- if (_hwscreen) {
- SDL_FreeSurface(_hwscreen);
- _hwscreen = NULL;
- }
-
- if (_tmpscreen) {
- SDL_FreeSurface(_tmpscreen);
- _tmpscreen = NULL;
- }
-}
-
-bool OSystem_WINCE3::hotswapGFXMode() {
- if (!_screen)
- return false;
-
- // Keep around the old _screen & _tmpscreen so we can restore the screen data
- // after the mode switch. (also for the overlay)
- SDL_Surface *old_screen = _screen;
- SDL_Surface *old_tmpscreen = _tmpscreen;
- SDL_Surface *old_overlayscreen = _overlayscreen;
- SDL_Surface *old_tmpscreen2 = _tmpscreen2;
-
- // Release the HW screen surface
- SDL_FreeSurface(_hwscreen);
-
- // Release toolbars
- free(_toolbarLow->pixels);
- SDL_FreeSurface(_toolbarLow);
- if (_toolbarHigh) {
- free(_toolbarHigh->pixels);
- SDL_FreeSurface(_toolbarHigh);
- }
-
- // Setup the new GFX mode
- if (!loadGFXMode()) {
- unloadGFXMode();
-
- _screen = old_screen;
- _overlayscreen = old_overlayscreen;
-
- return false;
- }
-
- // reset palette
- SDL_SetColors(_screen, _currentPalette, 0, 256);
-
- // Restore old screen content
- SDL_BlitSurface(old_screen, NULL, _screen, NULL);
- SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
- if (_overlayVisible) {
- SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
- SDL_BlitSurface(old_tmpscreen2, NULL, _tmpscreen2, NULL);
- }
-
- // Free the old surfaces
- SDL_FreeSurface(old_screen);
- SDL_FreeSurface(old_tmpscreen);
- SDL_FreeSurface(old_overlayscreen);
- SDL_FreeSurface(old_tmpscreen2);
-
- // Blit everything back to the screen
- _toolbarHighDrawn = false;
- internUpdateScreen();
-
- // Make sure that a Common::EVENT_SCREEN_CHANGED gets sent later -> FIXME this crashes when no game has been loaded.
-// _modeChanged = true;
-
- return true;
-}
-
-void OSystem_WINCE3::internUpdateScreen() {
- SDL_Surface *srcSurf, *origSurf;
- static bool old_overlayVisible = false;
- int numRectsOut = 0;
- int16 routx, routy, routw, routh, stretch, shakestretch;
-
- assert(_hwscreen != NULL);
-
- // bail if the application is minimized, be nice to OS
- if (!_hasfocus) {
- Sleep(20);
- return;
- }
-
- // If the shake position changed, fill the dirty area with blackness
- if (_currentShakePos != _newShakePos) {
- SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd, _newShakePos * _scaleFactorYm / _scaleFactorYd};
- if (_videoMode.aspectRatioCorrection)
- blackrect.h = real2Aspect(blackrect.h - 1) + 1;
- SDL_FillRect(_hwscreen, &blackrect, 0);
- _currentShakePos = _newShakePos;
- _forceFull = true;
- }
-
- // Make sure the mouse is drawn, if it should be drawn.
- drawMouse();
-
- // Check whether the palette was changed in the meantime and update the
- // screen surface accordingly.
- if (_paletteDirtyEnd != 0) {
- SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart);
- _paletteDirtyEnd = 0;
- _forceFull = true;
- }
+void OSystem_WINCE3::initSDL() {
+ // Check if SDL has not been initialized
+ if (!_initedSDL) {
+ uint32 sdlFlags = SDL_INIT_EVENTTHREAD;
+ if (ConfMan.hasKey("disable_sdl_parachute"))
+ sdlFlags |= SDL_INIT_NOPARACHUTE;
- if (!_overlayVisible) {
- origSurf = _screen;
- srcSurf = _tmpscreen;
- } else {
- origSurf = _overlayscreen;
- srcSurf = _tmpscreen2;
- }
-
- if (old_overlayVisible != _overlayVisible) {
- old_overlayVisible = _overlayVisible;
- update_scalers();
- }
-
- // Force a full redraw if requested
- if (_forceFull) {
- _numDirtyRects = 1;
-
- _dirtyRectList[0].x = 0;
- if (!_zoomDown)
- _dirtyRectList[0].y = 0;
- else
- _dirtyRectList[0].y = _videoMode.screenHeight / 2;
- _dirtyRectList[0].w = _videoMode.screenWidth;
- if (!_zoomUp && !_zoomDown)
- _dirtyRectList[0].h = _videoMode.screenHeight;
- else
- _dirtyRectList[0].h = _videoMode.screenHeight / 2;
-
- _toolbarHandler.forceRedraw();
- }
-
- // Only draw anything if necessary
- if (_numDirtyRects > 0) {
-
- SDL_Rect *r, *rout;
- SDL_Rect dst;
- uint32 srcPitch, dstPitch;
- SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects;
- bool toolbarVisible = _toolbarHandler.visible();
- int toolbarOffset = _toolbarHandler.getOffset();
-
- for (r = _dirtyRectList; r != last_rect; ++r) {
- dst = *r;
- dst.x++; // Shift rect by one since 2xSai needs to access the data around
- dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
- // NOTE: This is also known as BLACK MAGIC, copied from the sdl backend
- if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
- error("SDL_BlitSurface failed: %s", SDL_GetError());
+ if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) {
+ SDL_VideoInit("windib", 0);
+ sdlFlags ^= SDL_INIT_VIDEO;
}
- SDL_LockSurface(srcSurf);
- SDL_LockSurface(_hwscreen);
-
- srcPitch = srcSurf->pitch;
- dstPitch = _hwscreen->pitch;
-
- for (r = _dirtyRectList, rout = _dirtyRectOut; r != last_rect; ++r) {
-
- // always clamp to enclosing, downsampled-grid-aligned rect in the downscaled image
- if (_scaleFactorXd != 1) {
- stretch = r->x % _scaleFactorXd;
- r->x -= stretch;
- r->w += stretch;
- r->w = (r->x + r->w + _scaleFactorXd - 1) / _scaleFactorXd * _scaleFactorXd - r->x;
- }
- if (_scaleFactorYd != 1) {
- stretch = r->y % _scaleFactorYd;
- r->y -= stretch;
- r->h += stretch;
- r->h = (r->y + r->h + _scaleFactorYd - 1) / _scaleFactorYd * _scaleFactorYd - r->y;
- }
-
- // transform
- shakestretch = _currentShakePos * _scaleFactorYm / _scaleFactorYd;
- routx = r->x * _scaleFactorXm / _scaleFactorXd; // locate position in scaled screen
- routy = r->y * _scaleFactorYm / _scaleFactorYd + shakestretch; // adjust for shake offset
- routw = r->w * _scaleFactorXm / _scaleFactorXd;
- routh = r->h * _scaleFactorYm / _scaleFactorYd - shakestretch;
-
- // clipping destination rectangle inside device screen (more strict, also more tricky but more stable)
- // note that all current scalers do not make dst rect exceed left/right, unless chosen badly (FIXME)
- if (_zoomDown) routy -= 240; // adjust for zoom position
- if (routy + routh < 0) continue;
- if (routy < 0) {
- routh += routy;
- r->y -= routy * _scaleFactorYd / _scaleFactorYm;
- routy = 0;
- r->h = routh * _scaleFactorYd / _scaleFactorYm;
- }
- if (_orientationLandscape) {
- if (routy > _platformScreenWidth) continue;
- if (routy + routh > _platformScreenWidth) {
- routh = _platformScreenWidth - routy;
- r->h = routh * _scaleFactorYd / _scaleFactorYm;
- }
- } else {
- if (routy > _platformScreenHeight) continue;
- if (routy + routh > _platformScreenHeight) {
- routh = _platformScreenHeight - routy;
- r->h = routh * _scaleFactorYd / _scaleFactorYm;
- }
- }
-
- // check if the toolbar is overwritten
- if (toolbarVisible && r->y + r->h >= toolbarOffset)
- _toolbarHandler.forceRedraw();
+ // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers)
+ if (SDL_Init(sdlFlags) == -1)
+ error("Could not initialize SDL: %s", SDL_GetError());
- // blit it (with added voodoo from the sdl backend, shifting the source rect again)
- _scalerProc( (byte *)srcSurf->pixels + (r->x * 2 + 2)+ (r->y + 1) * srcPitch, srcPitch,
- (byte *)_hwscreen->pixels + routx * 2 + routy * dstPitch, dstPitch,
- r->w, r->h - _currentShakePos);
+ // Enable unicode support if possible
+ SDL_EnableUNICODE(1);
- // add this rect to output
- rout->x = routx; rout->y = routy - shakestretch;
- rout->w = routw; rout->h = routh + shakestretch;
- numRectsOut++;
- rout++;
-
- }
- SDL_UnlockSurface(srcSurf);
- SDL_UnlockSurface(_hwscreen);
- }
- // Add the toolbar if needed
- SDL_Rect toolbar_rect[1];
- if (_panelVisible && _toolbarHandler.draw(_toolbarLow, &toolbar_rect[0])) {
- // It can be drawn, scale it
- uint32 srcPitch, dstPitch;
- SDL_Surface *toolbarSurface;
- ScalerProc *toolbarScaler;
-
- if (_videoMode.screenHeight > 240) {
- if (!_toolbarHighDrawn) {
- // Resize the toolbar
- SDL_LockSurface(_toolbarLow);
- SDL_LockSurface(_toolbarHigh);
- Normal2x((byte*)_toolbarLow->pixels, _toolbarLow->pitch, (byte*)_toolbarHigh->pixels, _toolbarHigh->pitch, toolbar_rect[0].w, toolbar_rect[0].h);
- SDL_UnlockSurface(_toolbarHigh);
- SDL_UnlockSurface(_toolbarLow);
- _toolbarHighDrawn = true;
- }
- toolbar_rect[0].w *= 2;
- toolbar_rect[0].h *= 2;
- toolbarSurface = _toolbarHigh;
- }
- else
- toolbarSurface = _toolbarLow;
-
- drawToolbarMouse(toolbarSurface, true); // draw toolbar mouse if applicable
-
- // Apply the appropriate scaler
- SDL_LockSurface(toolbarSurface);
- SDL_LockSurface(_hwscreen);
- srcPitch = toolbarSurface->pitch;
- dstPitch = _hwscreen->pitch;
-
- toolbarScaler = _scalerProc;
- if (_videoMode.scaleFactor == 2)
- toolbarScaler = Normal2x;
- else if (_videoMode.scaleFactor == 3)
- toolbarScaler = Normal3x;
- toolbarScaler((byte *)toolbarSurface->pixels, srcPitch,
- (byte *)_hwscreen->pixels + (_toolbarHandler.getOffset() * _scaleFactorYm / _scaleFactorYd * dstPitch),
- dstPitch, toolbar_rect[0].w, toolbar_rect[0].h);
- SDL_UnlockSurface(toolbarSurface);
- SDL_UnlockSurface(_hwscreen);
-
- // And blit it
- toolbar_rect[0].y = _toolbarHandler.getOffset();
- toolbar_rect[0].x = toolbar_rect[0].x * _scaleFactorXm / _scaleFactorXd;
- toolbar_rect[0].y = toolbar_rect[0].y * _scaleFactorYm / _scaleFactorYd;
- toolbar_rect[0].w = toolbar_rect[0].w * _scaleFactorXm / _scaleFactorXd;
- toolbar_rect[0].h = toolbar_rect[0].h * _scaleFactorYm / _scaleFactorYd;
-
- SDL_UpdateRects(_hwscreen, 1, toolbar_rect);
-
- drawToolbarMouse(toolbarSurface, false); // undraw toolbar mouse
- }
-
- // Finally, blit all our changes to the screen
- if (numRectsOut > 0)
- SDL_UpdateRects(_hwscreen, numRectsOut, _dirtyRectOut);
-
- _numDirtyRects = 0;
- _forceFull = false;
-}
-
-Graphics::Surface *OSystem_WINCE3::lockScreen() {
- // Make sure mouse pointer is not painted over the playfield at the time of locking
- undrawMouse();
- return OSystem_SDL::lockScreen();
-}
-
-void OSystem_WINCE3::unlockScreen() {
- OSystem_SDL::unlockScreen();
-}
-
-bool OSystem_WINCE3::saveScreenshot(const char *filename) {
- assert(_hwscreen != NULL);
-
- Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
- SDL_SaveBMP(_hwscreen, filename);
- return true;
-}
-
-void OSystem_WINCE3::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
- assert (_transactionMode == kTransactionNone);
-
- if (_overlayscreen == NULL)
- return;
-
- // Clip the coordinates
- if (x < 0) {
- w += x;
- buf -= x;
- x = 0;
- }
-
- if (y < 0) {
- h += y; buf -= y * pitch;
- y = 0;
+ _initedSDL = true;
}
-
- if (w > _videoMode.overlayWidth - x) {
- w = _videoMode.overlayWidth - x;
- }
-
- if (h > _videoMode.overlayHeight - y) {
- h = _videoMode.overlayHeight - y;
- }
-
- if (w <= 0 || h <= 0)
- return;
-
- // Mark the modified region as dirty
- addDirtyRect(x, y, w, h);
-
- undrawMouse();
-
- if (SDL_LockSurface(_overlayscreen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
- do {
- memcpy(dst, buf, w * 2);
- dst += _overlayscreen->pitch;
- buf += pitch;
- } while (--h);
-
- SDL_UnlockSurface(_overlayscreen);
-}
-
-void OSystem_WINCE3::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
- assert (_transactionMode == kTransactionNone);
- assert(src);
-
- if (_screen == NULL)
- return;
-
- Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
-
- /* Clip the coordinates */
- if (x < 0) {
- w += x;
- src -= x;
- x = 0;
- }
-
- if (y < 0) {
- h += y;
- src -= y * pitch;
- y = 0;
- }
-
- if (w > _videoMode.screenWidth - x) {
- w = _videoMode.screenWidth - x;
- }
-
- if (h > _videoMode.screenHeight - y) {
- h = _videoMode.screenHeight - y;
- }
-
- if (w <= 0 || h <= 0)
- return;
-
- addDirtyRect(x, y, w, h);
-
- undrawMouse();
-
- // Try to lock the screen surface
- if (SDL_LockSurface(_screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
-
- if (_videoMode.screenWidth == pitch && pitch == w) {
- memcpy(dst, src, h*w);
- } else {
- do {
- memcpy(dst, src, w);
- src += pitch;
- dst += _videoMode.screenWidth;
- } while (--h);
- }
-
- // Unlock the screen surface
- SDL_UnlockSurface(_screen);
-}
-
-void OSystem_WINCE3::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
-
- undrawMouse();
- if (w == 0 || h == 0)
- return;
-
- _mouseCurState.w = w;
- _mouseCurState.h = h;
-
- _mouseHotspotX = hotspot_x;
- _mouseHotspotY = hotspot_y;
-
- _mouseKeyColor = keycolor;
-
- free(_mouseData);
-
- _mouseData = (byte *) malloc(w * h);
- memcpy(_mouseData, buf, w * h);
-
- if (w > _mouseBackupDim || h > _mouseBackupDim) {
- // mouse has been undrawn, adjust sprite backup area
- free(_mouseBackupOld);
- free(_mouseBackupToolbar);
- uint16 tmp = (w > h) ? w : h;
- _mouseBackupOld = (byte *) malloc(tmp * tmp * 2); // can hold 8bpp (playfield) or 16bpp (overlay) data
- _mouseBackupToolbar = (uint16 *) malloc(tmp * tmp * 2); // 16 bpp
- _mouseBackupDim = tmp;
- }
-}
-
-void OSystem_WINCE3::setMousePos(int x, int y) {
- if (x != _mouseCurState.x || y != _mouseCurState.y) {
- undrawMouse();
- _mouseCurState.x = x;
- _mouseCurState.y = y;
- updateScreen();
- }
-}
-
-
-void OSystem_WINCE3::internDrawMouse() {
- if (!_mouseNeedsRedraw || !_mouseVisible || !_mouseData)
- return;
-
- int x = _mouseCurState.x - _mouseHotspotX;
- int y = _mouseCurState.y - _mouseHotspotY;
- int w = _mouseCurState.w;
- int h = _mouseCurState.h;
- byte color;
- const byte *src = _mouseData; // Image representing the mouse
- int width;
-
- // clip the mouse rect, and adjust the src pointer accordingly
- if (x < 0) {
- w += x;
- src -= x;
- x = 0;
- }
- if (y < 0) {
- h += y;
- src -= y * _mouseCurState.w;
- y = 0;
- }
-
- if (w > _videoMode.screenWidth - x)
- w = _videoMode.screenWidth - x;
- if (h > _videoMode.screenHeight - y)
- h = _videoMode.screenHeight - y;
-
- // Quick check to see if anything has to be drawn at all
- if (w <= 0 || h <= 0)
- return;
-
- // Draw the mouse cursor; backup the covered area in "bak"
- if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- // Mark as dirty
- addDirtyRect(x, y, w, h);
-
- if (!_overlayVisible) {
- byte *bak = _mouseBackupOld; // Surface used to backup the area obscured by the mouse
- byte *dst; // Surface we are drawing into
-
- dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
- while (h > 0) {
- width = w;
- while (width > 0) {
- *bak++ = *dst;
- color = *src++;
- if (color != _mouseKeyColor) // transparent, don't draw
- *dst = color;
- dst++;
- width--;
- }
- src += _mouseCurState.w - w;
- bak += _mouseBackupDim - w;
- dst += _videoMode.screenWidth - w;
- h--;
- }
-
- } else {
- uint16 *bak = (uint16 *)_mouseBackupOld; // Surface used to backup the area obscured by the mouse
- byte *dst; // Surface we are drawing into
-
- dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2;
- while (h > 0) {
- width = w;
- while (width > 0) {
- *bak++ = *(uint16 *)dst;
- color = *src++;
- if (color != 0xFF) // 0xFF = transparent, don't draw
- *(uint16 *)dst = SDL_MapRGB(_overlayscreen->format, _currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
- dst += 2;
- width--;
- }
- src += _mouseCurState.w - w;
- bak += _mouseBackupDim - w;
- dst += _overlayscreen->pitch - w * 2;
- h--;
- }
- }
-
- SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
-
- // Finally, set the flag to indicate the mouse has been drawn
- _mouseNeedsRedraw = false;
-}
-
-void OSystem_WINCE3::undrawMouse() {
- assert (_transactionMode == kTransactionNone);
-
- if (_mouseNeedsRedraw)
- return;
-
- int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
- int old_mouse_y = _mouseCurState.y - _mouseHotspotY;
- int old_mouse_w = _mouseCurState.w;
- int old_mouse_h = _mouseCurState.h;
-
- // clip the mouse rect, and adjust the src pointer accordingly
- if (old_mouse_x < 0) {
- old_mouse_w += old_mouse_x;
- old_mouse_x = 0;
- }
- if (old_mouse_y < 0) {
- old_mouse_h += old_mouse_y;
- old_mouse_y = 0;
- }
-
- if (old_mouse_w > _videoMode.screenWidth - old_mouse_x)
- old_mouse_w = _videoMode.screenWidth - old_mouse_x;
- if (old_mouse_h > _videoMode.screenHeight - old_mouse_y)
- old_mouse_h = _videoMode.screenHeight - old_mouse_y;
-
- // Quick check to see if anything has to be drawn at all
- if (old_mouse_w <= 0 || old_mouse_h <= 0)
- return;
-
-
- if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- int y;
- if (!_overlayVisible) {
- byte *dst, *bak = _mouseBackupOld;
-
- // No need to do clipping here, since drawMouse() did that already
- dst = (byte *)_screen->pixels + old_mouse_y * _videoMode.screenWidth + old_mouse_x;
- for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _videoMode.screenWidth)
- memcpy(dst, bak, old_mouse_w);
- } else {
- byte *dst;
- uint16 *bak = (uint16 *)_mouseBackupOld;
-
- // No need to do clipping here, since drawMouse() did that already
- dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2;
- for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _overlayscreen->pitch)
- memcpy(dst, bak, old_mouse_w << 1);
- }
-
- addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
-
- SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
-
- _mouseNeedsRedraw = true;
-}
-
-bool OSystem_WINCE3::showMouse(bool visible) {
- if (_mouseVisible == visible)
- return visible;
-
- if (visible == false)
- undrawMouse();
-
- bool last = _mouseVisible;
- _mouseVisible = visible;
- _mouseNeedsRedraw = true;
-
- return last;
-}
-
-void OSystem_WINCE3::drawToolbarMouse(SDL_Surface *surf, bool draw) {
-
- if (!_mouseData || !_usesEmulatedMouse)
- return;
-
- int x = _mouseCurState.x - _mouseHotspotX;
- int y = _mouseCurState.y - _mouseHotspotY - _toolbarHandler.getOffset();
- int w = _mouseCurState.w;
- int h = _mouseCurState.h;
- byte color;
- const byte *src = _mouseData;
- int width;
-
- // clip
- if (x < 0) {
- w += x;
- src -= x;
- x = 0;
- }
- if (y < 0) {
- h += y;
- src -= y * _mouseCurState.w;
- y = 0;
- }
- if (w > surf->w - x)
- w = surf->w - x;
- if (h > surf->h - y)
- h = surf->h - y;
- if (w <= 0 || h <= 0)
- return;
-
- if (SDL_LockSurface(surf) == -1)
- error("SDL_LockSurface failed at internDrawToolbarMouse: %s", SDL_GetError());
-
- uint16 *bak = _mouseBackupToolbar; // toolbar surfaces are 16bpp
- uint16 *dst;
- dst = (uint16 *)surf->pixels + y * surf->w + x;
-
- if (draw) { // blit it
- while (h > 0) {
- width = w;
- while (width > 0) {
- *bak++ = *dst;
- color = *src++;
- if (color != _mouseKeyColor) // transparent color
- *dst = 0xFFFF;
- dst++;
- width--;
- }
- src += _mouseCurState.w - w;
- bak += _mouseBackupDim - w;
- dst += surf->w - w;
- h--;
- }
- } else { // restore bg
- for (y = 0; y < h; ++y, bak += _mouseBackupDim, dst += surf->w)
- memcpy(dst, bak, w << 1);
- }
-
- SDL_UnlockSurface(surf);
-}
-
-void OSystem_WINCE3::blitCursor() {
-}
-
-void OSystem_WINCE3::showOverlay() {
- assert (_transactionMode == kTransactionNone);
-
- if (_overlayVisible)
- return;
-
- undrawMouse();
- _overlayVisible = true;
- update_scalers();
- clearOverlay();
-}
-
-void OSystem_WINCE3::hideOverlay() {
- assert (_transactionMode == kTransactionNone);
-
- if (!_overlayVisible)
- return;
-
- undrawMouse();
- _overlayVisible = false;
- clearOverlay();
- _forceFull = true;
-}
-
-void OSystem_WINCE3::drawMouse() {
- if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset() && !_usesEmulatedMouse) && !_forceHideMouse)
- internDrawMouse();
-}
-
-void OSystem_WINCE3::fillMouseEvent(Common::Event &event, int x, int y) {
- event.mouse.x = x;
- event.mouse.y = y;
-
- // Update the "keyboard mouse" coords
- _km.x = event.mouse.x;
- _km.y = event.mouse.y;
-
- // Adjust for the screen scaling
- if (_zoomDown)
- event.mouse.y += 240;
-
- event.mouse.x = event.mouse.x * _scaleFactorXd / _scaleFactorXm;
- event.mouse.y = event.mouse.y * _scaleFactorYd / _scaleFactorYm;
-}
-
-void OSystem_WINCE3::retrieve_mouse_location(int &x, int &y) {
- x = _mouseCurState.x;
- y = _mouseCurState.y;
-
- x = x * _scaleFactorXm / _scaleFactorXd;
- y = y * _scaleFactorYm / _scaleFactorYd;
-
- if (_zoomDown)
- y -= 240;
-}
-
-void OSystem_WINCE3::warpMouse(int x, int y) {
- if (_mouseCurState.x != x || _mouseCurState.y != y) {
- SDL_WarpMouse(x * _scaleFactorXm / _scaleFactorXd, y * _scaleFactorYm / _scaleFactorYd);
-
- // SDL_WarpMouse() generates a mouse movement event, so
- // set_mouse_pos() would be called eventually. However, the
- // cannon script in CoMI calls this function twice each time
- // the cannon is reloaded. Unless we update the mouse position
- // immediately the second call is ignored, causing the cannon
- // to change its aim.
-
- setMousePos(x, y);
- }
-}
-
-void OSystem_WINCE3::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
-
- if (_forceFull || _paletteDirtyEnd)
- return;
-
- OSystem_SDL::addDirtyRect(x, y, w, h, false);
-}
-
-static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) {
- if (GUI::Actions::Instance()->mappingActive())
- return key;
-
- if (unfilter) {
- switch (key) {
- case SDLK_ESCAPE:
- return SDLK_BACKSPACE;
- case SDLK_F8:
- return SDLK_ASTERISK;
- case SDLK_F9:
- return SDLK_HASH;
- default:
- return key;
- }
- }
-
- if (key >= SDLK_KP0 && key <= SDLK_KP9) {
- return key - SDLK_KP0 + '0';
- } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
- return key;
- } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
- return 0;
- }
- return key;
-}
-
-bool OSystem_WINCE3::pollEvent(Common::Event &event) {
- SDL_Event ev;
- ev.type = SDL_NOEVENT;
- DWORD currentTime;
- bool keyEvent = false;
- int deltaX, deltaY;
-
- memset(&event, 0, sizeof(Common::Event));
-
- handleKbdMouse();
-
- // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED
- if (_modeChanged) {
- _modeChanged = false;
- event.type = Common::EVENT_SCREEN_CHANGED;
- _screenChangeCount++;
- return true;
- }
-
- CEDevice::wakeUp();
-
- currentTime = GetTickCount();
-
- while (SDL_PollEvent(&ev)) {
- switch (ev.type) {
- case SDL_KEYDOWN:
- debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
- // KMOD_RESERVED is used if the key has been injected by an external buffer
- if (ev.key.keysym.mod != KMOD_RESERVED && !_unfilteredkeys) {
- keyEvent = true;
- _lastKeyPressed = ev.key.keysym.sym;
- _keyRepeatTime = currentTime;
- _keyRepeat = 0;
-
- if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true))
- return true;
- }
-
- if (GUI_Actions::Instance()->mappingActive())
- event.kbd.flags = 0xFF;
- else if (ev.key.keysym.sym == SDLK_PAUSE) {
- _lastKeyPressed = 0;
- event.type = Common::EVENT_PREDICTIVE_DIALOG;
- return true;
- } event.type = Common::EVENT_KEYDOWN;
- if (!_unfilteredkeys)
- event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
- else
- event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
- event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
-
- if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
- event.kbd.ascii ^= 0x20;
- event.kbd.flags = Common::KBD_SHIFT;
- }
-
- return true;
-
- case SDL_KEYUP:
- debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym));
- // KMOD_RESERVED is used if the key has been injected by an external buffer
- if (ev.key.keysym.mod != KMOD_RESERVED && !_unfilteredkeys) {
- keyEvent = true;
- _lastKeyPressed = 0;
-
- if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false))
- return true;
- }
-
- if (GUI_Actions::Instance()->mappingActive())
- event.kbd.flags = 0xFF;
- else if (ev.key.keysym.sym == SDLK_PAUSE) {
- _lastKeyPressed = 0;
- return false; // chew up the show agi dialog key up event
- }
-
- event.type = Common::EVENT_KEYUP;
- if (!_unfilteredkeys)
- event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
- else
- event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
- event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
-
- if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
- event.kbd.ascii ^= 0x20;
- event.kbd.flags = Common::KBD_SHIFT;
- }
-
- return true;
-
- case SDL_MOUSEMOTION:
- event.type = Common::EVENT_MOUSEMOVE;
- fillMouseEvent(event, ev.motion.x, ev.motion.y);
- setMousePos(event.mouse.x, event.mouse.y);
- return true;
-
- case SDL_MOUSEBUTTONDOWN:
- if (ev.button.button == SDL_BUTTON_LEFT)
- event.type = Common::EVENT_LBUTTONDOWN;
- else if (ev.button.button == SDL_BUTTON_RIGHT)
- event.type = Common::EVENT_RBUTTONDOWN;
- else
- break;
- fillMouseEvent(event, ev.button.x, ev.button.y);
-
-
- if (event.mouse.x > _tapX)
- deltaX = event.mouse.x - _tapX;
- else
- deltaX = _tapX - event.mouse.x;
- if (event.mouse.y > _tapY)
- deltaY = event.mouse.y - _tapY;
- else
- deltaY = _tapY - event.mouse.y;
- _closeClick = (deltaX <= 5 && deltaY <= 5);
-
- if (!_isSmartphone) {
- // handle double-taps
- if (_tapTime) { // second tap
- if (_closeClick && (GetTickCount() - _tapTime < 1000)) {
- if (event.mouse.y <= 20 && _panelInitialized) { // top of screen (show panel)
- swap_panel_visibility();
- } else if (!_noDoubleTapRMB) { // right click
- event.type = Common::EVENT_RBUTTONDOWN;
- _rbutton = true;
- }
- }
- _tapTime = 0;
- } else {
- _tapTime = GetTickCount();
- _tapX = event.mouse.x;
- _tapY = event.mouse.y;
- }
- }
-
- if (_freeLook && !_closeClick) {
- _rbutton = false;
- _tapTime = 0;
- _tapX = event.mouse.x;
- _tapY = event.mouse.y;
- event.type = Common::EVENT_MOUSEMOVE;
- setMousePos(event.mouse.x, event.mouse.y);
- }
-
-
- if (_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) {
- if (!_toolbarHandler.drawn()) {
- _toolbarHighDrawn = false;
- internUpdateScreen();
- }
- if (_newOrientation != _orientationLandscape){
- _orientationLandscape = _newOrientation;
- _toolbarHighDrawn = false;
- ConfMan.setInt("landscape", _orientationLandscape);
- ConfMan.flushToDisk();
- hotswapGFXMode();
- }
- return false;
- }
-
- return true;
-
- case SDL_MOUSEBUTTONUP:
- if (ev.button.button == SDL_BUTTON_LEFT)
- event.type = Common::EVENT_LBUTTONUP;
- else if (ev.button.button == SDL_BUTTON_RIGHT)
- event.type = Common::EVENT_RBUTTONUP;
- else
- break;
-
- if (_rbutton) {
- event.type = Common::EVENT_RBUTTONUP;
- _rbutton = false;
- }
-
- fillMouseEvent(event, ev.button.x, ev.button.y);
-
- if (_freeLook && !_closeClick) {
- _tapX = event.mouse.x;
- _tapY = event.mouse.y;
- event.type = Common::EVENT_MOUSEMOVE;
- setMousePos(event.mouse.x, event.mouse.y);
- }
-
- if (_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) {
- if (!_toolbarHandler.drawn()) {
- _toolbarHighDrawn = false;
- internUpdateScreen();
- }
- return false;
-
- }
- return true;
-
- case SDL_VIDEOEXPOSE:
- _forceFull = true;
- break;
-
- case SDL_QUIT:
- event.type = Common::EVENT_QUIT;
- return true;
-
- case SDL_ACTIVEEVENT:
- if (ev.active.state & SDL_APPMOUSEFOCUS)
- debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost");
- if (ev.active.state & SDL_APPINPUTFOCUS)
- debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost");
- if (ev.active.state & SDL_APPACTIVE)
- debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost");
- if (ev.active.state & SDL_APPINPUTFOCUS) {
- _hasfocus = ev.active.gain;
- SDL_PauseAudio(!_hasfocus);
- _forceFull |= _hasfocus;
- }
- break;
- }
- }
-
- // Simulate repeated key for backend
- if (!keyEvent && _lastKeyPressed && currentTime > _keyRepeatTime + _keyRepeatTrigger) {
- _keyRepeatTime = currentTime;
- _keyRepeat++;
- GUI_Actions::Instance()->performMapped(_lastKeyPressed, true);
- }
-
- return false;
}
void OSystem_WINCE3::quit() {
@@ -2497,19 +569,14 @@ void OSystem_WINCE3::getTimeAndDate(TimeDate &t) const {
SYSTEMTIME systime;
GetLocalTime(&systime);
- t.tm_year = systime.wYear - 1900;
- t.tm_mon = systime.wMonth - 1;
- t.tm_mday = systime.wDay;
- t.tm_hour = systime.wHour;
- t.tm_min = systime.wMinute;
- t.tm_sec = systime.wSecond;
+ t.tm_year = systime.wYear - 1900;
+ t.tm_mon = systime.wMonth - 1;
+ t.tm_mday = systime.wDay;
+ t.tm_hour = systime.wHour;
+ t.tm_min = systime.wMinute;
+ t.tm_sec = systime.wSecond;
}
int OSystem_WINCE3::_platformScreenWidth;
int OSystem_WINCE3::_platformScreenHeight;
bool OSystem_WINCE3::_isOzone;
-OSystem_WINCE3::zoneDesc OSystem_WINCE3::_zones[TOTAL_ZONES] = {
- { 0, 0, 320, 145 },
- { 0, 145, 150, 55 },
- { 150, 145, 170, 55 }
-};
diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h
index 6cc6e538e1..d7ede8ca81 100644
--- a/backends/platform/wince/wince-sdl.h
+++ b/backends/platform/wince/wince-sdl.h
@@ -35,7 +35,10 @@
#include "backends/platform/wince/CEkeys/CEKeys.h"
#include "backends/platform/wince/CEDevice.h"
-#define TOTAL_ZONES 3
+#include "backends/graphics/wincesdl/wincesdl-graphics.h"
+#include "backends/events/wincesdl/wincesdl-events.h"
+#include "backends/timer/default/default-timer.h"
+#include "backends/fs/windows/windows-fs-factory.h"
// defines used for implementing the raw frame buffer access method (2003+)
#define GETRAWFRAMEBUFFER 0x00020001
@@ -46,202 +49,45 @@
class OSystem_WINCE3 : public OSystem_SDL {
public:
OSystem_WINCE3();
-
- // Update the dirty areas of the screen
- void internUpdateScreen();
+ virtual ~OSystem_WINCE3();
void setGraphicsModeIntern();
- void initSize(uint w, uint h, const Graphics::PixelFormat *format);
void initBackend();
- // Overloaded from SDL backend (toolbar handling)
- bool pollEvent(Common::Event &event);
- // Overloaded from SDL backend (toolbar handling)
- void drawMouse();
- // Overloaded from SDL backend (mouse and new scaler handling)
- void fillMouseEvent(Common::Event &event, int x, int y);
- // Overloaded from SDL backend (new scaler handling)
- void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false);
- // Overloaded from SDL backend (new scaler handling)
- void warpMouse(int x, int y);
// Overloaded from SDL backend
void quit();
- // Overloaded from SDL backend (master volume and sample rate subtleties)
- void setupMixer();
// Overloaded from OSystem
void engineInit();
void getTimeAndDate(TimeDate &t) const;
virtual Common::String getDefaultConfigFileName();
+ virtual FilesystemFactory *getFilesystemFactory();
-
- // Overloaded from SDL_Common (FIXME)
- void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend
- void undrawMouse();
- void blitCursor();
- bool showMouse(bool visible);
- void setMousePos(int x, int y);
- void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)
- void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
- void showOverlay();
- void hideOverlay();
- Graphics::Surface *lockScreen();
- void unlockScreen();
-
- // GUI and action stuff
- void swap_panel_visibility();
- void swap_panel();
void swap_sound_master();
- void add_right_click(bool pushed);
- void swap_mouse_visibility();
- void swap_freeLook();
- void swap_zoom_up();
- void swap_zoom_down();
- void swap_smartphone_keyboard();
-
-//#ifdef WIN32_PLATFORM_WFSP
- // Smartphone actions
-
- void initZones();
- void loadDeviceConfigurationElement(String element, int &value, int defaultValue);
- void loadDeviceConfiguration();
- void add_left_click(bool pushed);
- void move_cursor_up();
- void move_cursor_down();
- void move_cursor_left();
- void move_cursor_right();
- void switch_zone();
- void smartphone_rotate_display();
-//#endif
static int getScreenWidth();
static int getScreenHeight();
static void initScreenInfos();
static bool isOzone();
-protected:
- bool loadGFXMode();
- void unloadGFXMode();
- bool hotswapGFXMode();
- bool saveScreenshot(const char *filename);
-
+ static bool _soundMaster; // turn off sound after all calculations
+ // static since needed by the SDL callback
- const GraphicsMode *getSupportedGraphicsModes() const;
- bool setGraphicsMode(int mode);
- //int getGraphicsMode() const;
- int getDefaultGraphicsMode() const;
-
- bool hasFeature(Feature f);
- void setFeatureState(Feature f, bool enable);
- bool getFeatureState(Feature f);
-
- void internDrawMouse();
- void drawToolbarMouse(SDL_Surface *surf, bool draw);
+protected:
+ void initSDL();
+ Audio::MixerImpl *_mixer;
+ DefaultTimerManager *_timer;
+ FilesystemFactory *_fsFactory;
private:
-
-#ifdef USE_VORBIS
- bool checkOggHighSampleRate();
-#endif
-
- static void private_sound_proc(void *param, byte *buf, int len);
-
- bool update_scalers();
- void create_toolbar();
- void update_game_settings();
void check_mappings();
- uint32 compute_sample_rate();
-
- void retrieve_mouse_location(int &x, int &y);
-
- CEGUI::ToolbarHandler _toolbarHandler;
- SDL_Surface *_toolbarLow; // toolbar 320x40
- SDL_Surface *_toolbarHigh; // toolbar 640x80
- bool _toolbarHighDrawn; // cache toolbar 640x80
-
- bool _freeLook; // freeLook mode (do not send mouse button events)
-
- bool _forceHideMouse; // force invisible mouse cursor
-
- bool _forcePanelInvisible; // force panel visibility for some cases
- bool _panelVisible; // panel visibility
- bool _panelStateForced; // panel visibility forced by external call
-
- bool _panelInitialized; // only initialize the toolbar once
-
- bool _unfilteredkeys; // discard key mapping temporarily (agi pred. dialog)
- static bool _soundMaster; // turn off sound after all calculations
- // static since needed by the SDL callback
- int _orientationLandscape; // current orientation
- int _newOrientation; // new orientation
-
- bool _saveToolbarState; // save visibility when forced
- String _saveActiveToolbar; // save active toolbar when forced
-
- bool _saveToolbarZoom; // save visibility when zooming
- bool _zoomUp; // zooming up mode
- bool _zoomDown; // zooming down mode
-
- bool _noDoubleTapRMB; // disable double tap -> rmb click
- bool _rbutton; // double tap -> right button simulation
- bool _closeClick; // flag when taps are spatially close together
-
- bool _usesEmulatedMouse; // emulated mousemove ever been used in this session
-
- bool _canBeAspectScaled; // game screen size allows for aspect scaling
-
- int _scaleFactorXm; // scaler X *
- int _scaleFactorXd; // scaler X /
- int _scaleFactorYm; // scaler Y *
- int _scaleFactorYd; // scaler Y /
- SDL_Rect _dirtyRectOut[NUM_DIRTY_RECT];
- bool _scalersChanged;
- bool _hasfocus; // scummvm has the top window
+ bool _forcePanelInvisible; // force panel visibility for some cases
static int _platformScreenWidth;
static int _platformScreenHeight;
- static bool _isOzone; // true if running on Windows 2003 SE
-
- // Keyboard tap
- int _tapX;
- int _tapY;
- long _tapTime;
-
- // Mouse
- int _mouseHotspotX, _mouseHotspotY;
- byte *_mouseBackupOld;
- uint16 *_mouseBackupToolbar;
- uint16 _mouseBackupDim;
-
- // Smartphone specific variables
-
- int _lastKeyPressed; // last key pressed
- int _keyRepeat; // number of time the last key was repeated
- int _keyRepeatTime; // elapsed time since the key was pressed
- int _keyRepeatTrigger; // minimum time to consider the key was repeated
-
- int _repeatX; // repeat trigger for left and right cursor moves
- int _repeatY; // repeat trigger for up and down cursor moves
- int _stepX1; // offset for left and right cursor moves (slowest)
- int _stepX2; // offset for left and right cursor moves (faster)
- int _stepX3; // offset for left and right cursor moves (fastest)
- int _stepY1; // offset for up and down cursor moves (slowest)
- int _stepY2; // offset for up and down cursor moves (faster)
- int _stepY3; // offset for up and down cursor moves (fastest)
-
- int _mouseXZone[TOTAL_ZONES];
- int _mouseYZone[TOTAL_ZONES];
- int _currentZone;
-
- struct zoneDesc {
- int x;
- int y;
- int width;
- int height;
- };
-
- static zoneDesc _zones[TOTAL_ZONES];
+ static bool _isOzone; // true if running on Windows 2003 SE
+
};
#endif
diff --git a/backends/saves/savefile.cpp b/backends/saves/savefile.cpp
index d2fc913f14..7b7d6b0c0c 100644
--- a/backends/saves/savefile.cpp
+++ b/backends/saves/savefile.cpp
@@ -31,8 +31,7 @@
namespace Common {
-bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) {
-
+bool SaveFileManager::copySavefile(const String &oldFilename, const String &newFilename) {
InSaveFile *inFile = 0;
OutSaveFile *outFile = 0;
uint32 size = 0;
@@ -57,9 +56,8 @@ bool SaveFileManager::renameSavefile(const String &oldFilename, const String &ne
if (!error) {
outFile->write(buffer, size);
outFile->finalize();
- if (!outFile->err()) {
- success = removeSavefile(oldFilename);
- }
+
+ success = !outFile->err();
}
}
@@ -71,6 +69,13 @@ bool SaveFileManager::renameSavefile(const String &oldFilename, const String &ne
return success;
}
+bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) {
+ if (!copySavefile(oldFilename, newFilename))
+ return false;
+
+ return removeSavefile(oldFilename);
+}
+
String SaveFileManager::popErrorDesc() {
String err = _errorDesc;
clearError();
diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp
index dd468bbe09..b5060c4c8d 100644
--- a/backends/timer/default/default-timer.cpp
+++ b/backends/timer/default/default-timer.cpp
@@ -34,7 +34,7 @@ struct TimerSlot {
uint32 interval; // in microseconds
uint32 nextFireTime; // in milliseconds
- uint32 nextFireTimeMicro; // mircoseconds part of nextFire
+ uint32 nextFireTimeMicro; // microseconds part of nextFire
TimerSlot *next;
};
diff --git a/backends/timer/default/default-timer.h b/backends/timer/default/default-timer.h
index e7ac3d122f..a4c7385ef9 100644
--- a/backends/timer/default/default-timer.h
+++ b/backends/timer/default/default-timer.h
@@ -40,9 +40,9 @@ private:
public:
DefaultTimerManager();
- ~DefaultTimerManager();
- bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
- void removeTimerProc(TimerProc proc);
+ virtual ~DefaultTimerManager();
+ virtual bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
+ virtual void removeTimerProc(TimerProc proc);
/**
* Timer callback, to be invoked at regular time intervals by the backend.