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/wincesdl/wincesdl-events.cpp332
-rw-r--r--backends/events/wincesdl/wincesdl-events.h73
-rw-r--r--backends/graphics/opengl/gltexture.cpp2
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp151
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp17
-rw-r--r--backends/graphics/sdl/sdl-graphics.cpp21
-rw-r--r--backends/graphics/wincesdl/wincesdl-graphics.cpp1639
-rw-r--r--backends/graphics/wincesdl/wincesdl-graphics.h206
-rw-r--r--backends/midi/alsa.cpp52
-rw-r--r--backends/mixer/wincesdl/wincesdl-mixer.cpp183
-rw-r--r--backends/mixer/wincesdl/wincesdl-mixer.h53
-rw-r--r--backends/module.mk3
-rw-r--r--backends/platform/android/android.cpp1450
-rw-r--r--backends/platform/android/android.h225
-rw-r--r--backends/platform/android/android.mk5
-rw-r--r--backends/platform/android/asset-archive.cpp35
-rw-r--r--backends/platform/android/asset-archive.h5
-rw-r--r--backends/platform/android/events.cpp661
-rw-r--r--backends/platform/android/gfx.cpp810
-rw-r--r--backends/platform/android/jni.cpp602
-rw-r--r--backends/platform/android/jni.h151
-rw-r--r--backends/platform/android/module.mk7
-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.java14
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVM.java698
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java406
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java10
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java201
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Unpacker.java1
-rw-r--r--backends/platform/android/texture.cpp571
-rw-r--r--backends/platform/android/texture.h331
-rw-r--r--backends/platform/android/video.cpp342
-rw-r--r--backends/platform/android/video.h209
-rw-r--r--backends/platform/sdl/sdl.cpp21
-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/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
93 files changed, 7354 insertions, 5444 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/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/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 beac2f6d3e..9a2efe3eec 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -136,6 +136,8 @@ int OpenGLGraphicsManager::getDefaultGraphicsMode() const {
bool OpenGLGraphicsManager::setGraphicsMode(int mode) {
assert(_transactionMode == kTransactionActive);
+ setScale(2);
+
if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
return true;
@@ -166,11 +168,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,7 +308,7 @@ int16 OpenGLGraphicsManager::getWidth() {
void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
assert(colors);
-
+
#ifdef USE_RGB_COLOR
assert(_screenFormat.bytesPerPixel == 1);
#endif
@@ -324,7 +324,7 @@ 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
@@ -341,9 +341,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 +367,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 +393,9 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) {
pixels[i] = col;
}
}
-
+#else
+ memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
+#endif
_screenNeedsRedraw = true;
}
@@ -558,7 +561,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
@@ -754,11 +758,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,7 +778,6 @@ 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) {
@@ -779,16 +788,42 @@ void OpenGLGraphicsManager::refreshCursor() {
}
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 +846,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);
@@ -873,6 +909,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 +1004,7 @@ void OpenGLGraphicsManager::internUpdateScreen() {
refreshOverlay();
// Draw the overlay
- _overlayTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight);
+ _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight);
}
if (_cursorVisible) {
@@ -1059,10 +1100,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 +1118,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 +1139,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 +1150,38 @@ 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));
+
#ifdef USE_OSD
if (!_osdTexture)
_osdTexture = new GLTexture(2, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
@@ -1166,32 +1229,20 @@ uint OpenGLGraphicsManager::getAspectRatio() {
}
void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
- if (_videoMode.mode == OpenGL::GFX_NORMAL) {
- if (_videoMode.hardwareWidth != _videoMode.overlayWidth)
- x = x * _videoMode.overlayWidth / _videoMode.hardwareWidth;
- if (_videoMode.hardwareHeight != _videoMode.overlayHeight)
- y = y * _videoMode.overlayHeight / _videoMode.hardwareHeight;
-
- if (!_overlayVisible) {
- x /= _videoMode.scaleFactor;
- y /= _videoMode.scaleFactor;
- }
+ if (_overlayVisible)
+ return;
- } else {
+ if (_videoMode.mode == OpenGL::GFX_NORMAL) {
+ x /= _videoMode.scaleFactor;
+ y /= _videoMode.scaleFactor;
+ } else if (!_overlayVisible) {
x -= _displayX;
y -= _displayY;
- if (_overlayVisible) {
- if (_displayWidth != _videoMode.overlayWidth)
- x = x * _videoMode.overlayWidth / _displayWidth;
- if (_displayHeight != _videoMode.overlayHeight)
- y = y * _videoMode.overlayHeight / _displayHeight;
- } else {
- if (_displayWidth != _videoMode.screenWidth)
- x = x * _videoMode.screenWidth / _displayWidth;
- if (_displayHeight != _videoMode.screenHeight)
- y = y * _videoMode.screenHeight / _displayHeight;
- }
+ if (_displayWidth != _videoMode.screenWidth)
+ x = x * _videoMode.screenWidth / _displayWidth;
+ if (_displayHeight != _videoMode.screenHeight)
+ y = y * _videoMode.screenHeight / _displayHeight;
}
}
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index c7ce0aa7de..cbc152a4a3 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -121,6 +121,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
@@ -344,13 +345,10 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
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;
+ _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
int screenAspectRatio = _videoMode.screenWidth * 10000 / _videoMode.screenHeight;
int desiredAspectRatio = getAspectRatio();
@@ -365,6 +363,9 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
// the width is modified it can break the overlay.
if (_videoMode.hardwareHeight > _videoMode.overlayHeight)
_videoMode.overlayHeight = _videoMode.hardwareHeight;
+ } else {
+ _videoMode.overlayWidth = _videoMode.hardwareWidth;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight;
}
_screenResized = false;
@@ -376,11 +377,15 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() {
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- if (_videoMode.fullscreen)
+ if (_videoMode.fullscreen) {
if (!setupFullscreenMode())
// Failed setuping a fullscreen mode
return false;
+ _videoMode.overlayWidth = _videoMode.hardwareWidth;
+ _videoMode.overlayHeight = _videoMode.hardwareHeight;
+ }
+
uint32 flags = SDL_OPENGL;
if (_videoMode.fullscreen)
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 09c4f39636..c0d93b3bf2 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -165,13 +165,6 @@ 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;
- }
-#endif
-
#ifdef USE_SDL_DEBUG_FOCUSRECT
if (ConfMan.hasKey("use_sdl_debug_focusrect"))
_enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect");
@@ -1248,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
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..feed60eaef 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,7 +67,7 @@ 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();
@@ -83,11 +82,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 +114,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 +208,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 +297,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/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..484f804ee0 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
events/samsungtvsdl/samsungtvsdl-events.o \
events/sdl/sdl-events.o \
events/symbiansdl/symbiansdl-events.o \
+ events/wincesdl/wincesdl-events.o \
fs/abstract-fs.o \
fs/stdiostream.o \
fs/amigaos4/amigaos4-fs-factory.o \
@@ -27,6 +28,7 @@ MODULE_OBJS := \
graphics/openglsdl/openglsdl-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 +46,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/android.cpp b/backends/platform/android/android.cpp
index c49745f8bd..4e1373a1b1 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -25,22 +25,11 @@
#if defined(__ANDROID__)
-#include "backends/base-backend.h"
-#include "base/main.h"
-#include "graphics/surface.h"
-
-#include "backends/platform/android/android.h"
-#include "backends/platform/android/video.h"
-
-#include <jni.h>
-
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
#include <sys/time.h>
+#include <sys/resource.h>
#include <time.h>
+#include <unistd.h>
-#include "common/archive.h"
#include "common/util.h"
#include "common/rect.h"
#include "common/queue.h"
@@ -48,14 +37,12 @@
#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"
+#include "backends/platform/android/jni.h"
+#include "backends/platform/android/android.h"
const char *android_log_tag = "ScummVM";
@@ -68,7 +55,8 @@ extern "C" {
expr, file, line);
}
- void __assert2(const char *file, int line, const char *func, const char *expr) {
+ 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);
@@ -106,235 +94,24 @@ void checkGlError(const char *expr, const char *file, int line) {
}
#endif
-static JavaVM *cached_jvm;
-static jfieldID FID_Event_type;
-static jfieldID FID_Event_synthetic;
-static jfieldID FID_Event_kbd_keycode;
-static jfieldID FID_Event_kbd_ascii;
-static jfieldID FID_Event_kbd_flags;
-static jfieldID FID_Event_mouse_x;
-static jfieldID FID_Event_mouse_y;
-static jfieldID FID_Event_mouse_relative;
-static jfieldID FID_ScummVM_nativeScummVM;
-static jmethodID MID_Object_wait;
-
-JNIEnv *JNU_GetEnv() {
- JNIEnv *env = 0;
-
- jint res = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
-
- if (res != JNI_OK) {
- LOGE("GetEnv() failed: %d", res);
- abort();
- }
-
- return env;
-}
-
-static void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
- jclass cls = env->FindClass(name);
-
- // if cls is 0, an exception has already been thrown
- if (cls != 0)
- env->ThrowNew(cls, msg);
-
- env->DeleteLocalRef(cls);
-}
-
-// floating point. use sparingly
-template <class T>
-static inline T scalef(T in, float numerator, float denominator) {
- return static_cast<float>(in) * numerator / denominator;
-}
-
-static inline GLfixed xdiv(int numerator, int denominator) {
- assert(numerator < (1 << 16));
- return (numerator << 16) / denominator;
-}
-
-#ifdef DYNAMIC_MODULES
-class AndroidPluginProvider : public POSIXPluginProvider {
-protected:
- virtual void addCustomDirectories(Common::FSList &dirs) const;
-};
-#endif
-
-class OSystem_Android : public BaseBackend, public PaletteManager {
-private:
- // back pointer to (java) peer instance
- jobject _back_ptr;
-
- jmethodID MID_displayMessageOnOSD;
- jmethodID MID_setWindowCaption;
- jmethodID MID_initBackend;
- jmethodID MID_audioSampleRate;
- jmethodID MID_showVirtualKeyboard;
- jmethodID MID_getSysArchives;
- jmethodID MID_getPluginDirectories;
- jmethodID MID_setupScummVMSurface;
- jmethodID MID_destroyScummVMSurface;
- jmethodID MID_swapBuffers;
-
- int _screen_changeid;
- int _egl_surface_width;
- int _egl_surface_height;
-
- bool _force_redraw;
-
- // Game layer
- GLESPaletteTexture *_game_texture;
- int _shake_offset;
- Common::Rect _focus_rect;
-
- // Overlay layer
- GLES4444Texture *_overlay_texture;
- bool _show_overlay;
-
- // Mouse layer
- GLESPaletteATexture *_mouse_texture;
- Common::Point _mouse_hotspot;
- int _mouse_targetscale;
- bool _show_mouse;
- bool _use_mouse_palette;
-
- Common::Queue<Common::Event> _event_queue;
- MutexRef _event_queue_lock;
-
- bool _timer_thread_exit;
- pthread_t _timer_thread;
- static void *timerThreadFunc(void *arg);
-
- bool _enable_zoning;
- bool _virtkeybd_on;
-
- Common::SaveFileManager *_savefile;
- Audio::MixerImpl *_mixer;
- Common::TimerManager *_timer;
- FilesystemFactory *_fsFactory;
- Common::Archive *_asset_archive;
- timeval _startTime;
-
- void setupScummVMSurface();
- void destroyScummVMSurface();
- void setupKeymapper();
- void _setCursorPalette(const byte *colors, uint start, uint num);
-
-public:
- OSystem_Android(jobject am);
- virtual ~OSystem_Android();
- bool initJavaHooks(JNIEnv *env, jobject self);
-
- static OSystem_Android *fromJavaObject(JNIEnv *env, jobject obj);
- virtual void initBackend();
- void addPluginDirectories(Common::FSList &dirs) const;
- void enableZoning(bool enable) { _enable_zoning = enable; }
- void setSurfaceSize(int width, int height) {
- _egl_surface_width = width;
- _egl_surface_height = height;
- }
-
- virtual bool hasFeature(Feature f);
- virtual void setFeatureState(Feature f, bool enable);
- virtual bool getFeatureState(Feature f);
- virtual const GraphicsMode *getSupportedGraphicsModes() const;
- virtual int getDefaultGraphicsMode() const;
- bool setGraphicsMode(const char *name);
- virtual bool setGraphicsMode(int mode);
- virtual int getGraphicsMode() const;
- virtual void initSize(uint width, uint height,
- const Graphics::PixelFormat *format);
-
- virtual int getScreenChangeID() const {
- return _screen_changeid;
- }
-
- virtual int16 getHeight();
- virtual int16 getWidth();
-
- virtual PaletteManager *getPaletteManager() {
- return this;
- }
-
-protected:
- // PaletteManager API
- virtual void setPalette(const byte *colors, uint start, uint num);
- virtual void grabPalette(byte *colors, uint start, uint num);
-
-public:
- virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
- virtual void updateScreen();
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
- virtual void setShakePos(int shakeOffset);
- virtual void fillScreen(uint32 col);
- virtual void setFocusRectangle(const Common::Rect& rect);
- virtual void clearFocusRectangle();
-
- virtual void showOverlay();
- virtual void hideOverlay();
- virtual void clearOverlay();
- virtual void grabOverlay(OverlayColor *buf, int pitch);
- virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
- virtual int16 getOverlayHeight();
- virtual int16 getOverlayWidth();
-
- // RGBA 4444
- virtual Graphics::PixelFormat getOverlayFormat() const {
- Graphics::PixelFormat format;
-
- format.bytesPerPixel = 2;
- format.rLoss = 8 - 4;
- format.gLoss = 8 - 4;
- format.bLoss = 8 - 4;
- format.aLoss = 8 - 4;
- format.rShift = 3 * 4;
- format.gShift = 2 * 4;
- format.bShift = 1 * 4;
- format.aShift = 0 * 4;
-
- return format;
- }
-
- virtual bool showMouse(bool visible);
-
- virtual void warpMouse(int x, int y);
- virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format);
- virtual void setCursorPalette(const byte *colors, uint start, uint num);
- virtual void disableCursorPalette(bool disable);
-
- virtual bool pollEvent(Common::Event &event);
- void pushEvent(const Common::Event& event);
- virtual uint32 getMillis();
- virtual void delayMillis(uint msecs);
-
- virtual MutexRef createMutex(void);
- virtual void lockMutex(MutexRef mutex);
- virtual void unlockMutex(MutexRef mutex);
- virtual void deleteMutex(MutexRef mutex);
-
- virtual void quit();
-
- virtual void setWindowCaption(const char *caption);
- virtual void displayMessageOnOSD(const char *msg);
- virtual void showVirtualKeyboard(bool enable);
-
- virtual Common::SaveFileManager *getSavefileManager();
- virtual Audio::Mixer *getMixer();
- virtual void getTimeAndDate(TimeDate &t) const;
- virtual Common::TimerManager *getTimerManager();
- virtual FilesystemFactory *getFilesystemFactory();
- virtual void logMessage(LogMessageType::Type type, const char *message);
- virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
-};
-
-OSystem_Android::OSystem_Android(jobject am) :
- _back_ptr(0),
+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),
_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),
+ _fullscreen(false),
+ _graphicsMode(0),
+ _ar_correction(false),
_show_mouse(false),
_show_overlay(false),
_enable_zoning(false),
@@ -342,876 +119,288 @@ OSystem_Android::OSystem_Android(jobject am) :
_mixer(0),
_timer(0),
_fsFactory(new POSIXFilesystemFactory()),
- _asset_archive(new AndroidAssetArchive(am)),
_shake_offset(0),
- _event_queue_lock(createMutex()) {
+ _event_queue_lock(createMutex()),
+ _touch_pt_down(),
+ _touch_pt_dt(),
+ _eventScaleX(100),
+ _eventScaleY(100),
+ // TODO put these values in some option dlg?
+ _touchpad_mode(true),
+ _touchpad_scale(50),
+ _dpad_scale(4),
+ _trackball_scale(2) {
}
OSystem_Android::~OSystem_Android() {
ENTER();
- delete _game_texture;
- delete _overlay_texture;
- delete _mouse_texture;
-
- destroyScummVMSurface();
-
- JNIEnv *env = JNU_GetEnv();
- //env->DeleteWeakGlobalRef(_back_ptr);
- env->DeleteGlobalRef(_back_ptr);
-
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 == 0) \
- return false; \
- } while (0)
-
- FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V");
- FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V");
- FIND_METHOD(initBackend, "()V");
- FIND_METHOD(audioSampleRate, "()I");
- FIND_METHOD(showVirtualKeyboard, "(Z)V");
- FIND_METHOD(getSysArchives, "()[Ljava/lang/String;");
- FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
- FIND_METHOD(setupScummVMSurface, "()V");
- FIND_METHOD(destroyScummVMSurface, "()V");
- FIND_METHOD(swapBuffers, "()Z");
-
-#undef FIND_METHOD
-
- return true;
-}
-
-static void ScummVM_create(JNIEnv *env, jobject self, jobject am) {
- OSystem_Android *cpp_obj = new OSystem_Android(am);
-
- // Exception already thrown by initJavaHooks?
- if (!cpp_obj->initJavaHooks(env, self))
- return;
-
- env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)cpp_obj);
-
-#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new AndroidPluginProvider());
-#endif
-}
-
-static void ScummVM_nativeDestroy(JNIEnv *env, jobject self) {
- OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
- delete cpp_obj;
-}
-
-static void ScummVM_audioMixCallback(JNIEnv *env, jobject self,
- jbyteArray jbuf) {
- OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
- jsize len = env->GetArrayLength(jbuf);
- jbyte *buf = env->GetByteArrayElements(jbuf, 0);
-
- if (buf == 0) {
- warning("Unable to get Java audio byte array. Skipping");
- return;
- }
-
- Audio::MixerImpl *mixer =
- static_cast<Audio::MixerImpl *>(cpp_obj->getMixer());
- assert(mixer);
- mixer->mixCallback(reinterpret_cast<byte *>(buf), len);
-
- env->ReleaseByteArrayElements(jbuf, buf, 0);
-}
-
-static void ScummVM_setConfManInt(JNIEnv *env, jclass cls,
- jstring key_obj, jint value) {
- ENTER("%p, %d", key_obj, (int)value);
-
- const char *key = env->GetStringUTFChars(key_obj, 0);
-
- if (key == 0)
- return;
-
- ConfMan.setInt(key, value);
-
- env->ReleaseStringUTFChars(key_obj, key);
-}
-
-static void ScummVM_setConfManString(JNIEnv *env, jclass cls, jstring key_obj,
- jstring value_obj) {
- ENTER("%p, %p", key_obj, value_obj);
-
- const char *key = env->GetStringUTFChars(key_obj, 0);
-
- if (key == 0)
- return;
-
- const char *value = env->GetStringUTFChars(value_obj, 0);
-
- if (value == 0) {
- env->ReleaseStringUTFChars(key_obj, key);
- return;
- }
-
- ConfMan.set(key, value);
-
- env->ReleaseStringUTFChars(value_obj, value);
- env->ReleaseStringUTFChars(key_obj, key);
-}
-
void *OSystem_Android::timerThreadFunc(void *arg) {
OSystem_Android *system = (OSystem_Android *)arg;
DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer);
- JNIEnv *env = 0;
- jint res = cached_jvm->AttachCurrentThread(&env, 0);
+ // renice this thread to boost the audio thread
+ if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+ LOGW("couldn't renice the timer thread");
- if (res != JNI_OK) {
- LOGE("AttachCurrentThread() failed: %d", res);
- abort();
- }
+ JNI::attachThread();
struct timespec tv;
tv.tv_sec = 0;
tv.tv_nsec = 100 * 1000 * 1000; // 100ms
while (!system->_timer_thread_exit) {
+ if (JNI::pause) {
+ LOGD("timer thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("timer thread woke up");
+ }
+
timer->handler();
nanosleep(&tv, 0);
}
- res = cached_jvm->DetachCurrentThread();
-
- if (res != JNI_OK) {
- LOGE("DetachCurrentThread() failed: %d", res);
- abort();
- }
+ JNI::detachThread();
return 0;
}
-void OSystem_Android::initBackend() {
- ENTER();
-
- 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, 0);
-
- jint sample_rate = env->CallIntMethod(_back_ptr, MID_audioSampleRate);
- if (env->ExceptionCheck()) {
- warning("Error finding audio sample rate - assuming 11025HZ");
-
- env->ExceptionDescribe();
- env->ExceptionClear();
-
- sample_rate = 11025;
- }
-
- _mixer = new Audio::MixerImpl(this, sample_rate);
- _mixer->setReady(true);
-
- env->CallVoidMethod(_back_ptr, MID_initBackend);
+void *OSystem_Android::audioThreadFunc(void *arg) {
+ JNI::attachThread();
- if (env->ExceptionCheck()) {
- error("Error in Java initBackend");
-
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
-
- _timer_thread_exit = false;
- pthread_create(&_timer_thread, 0, timerThreadFunc, this);
+ OSystem_Android *system = (OSystem_Android *)arg;
+ Audio::MixerImpl *mixer = system->_mixer;
- OSystem::initBackend();
+ uint buf_size = system->_audio_buffer_size;
- setupScummVMSurface();
-}
+ JNIEnv *env = JNI::getEnv();
-void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
- ENTER();
+ jbyteArray bufa = env->NewByteArray(buf_size);
- JNIEnv *env = JNU_GetEnv();
+ bool paused = true;
- jobjectArray array =
- (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getPluginDirectories);
- if (env->ExceptionCheck()) {
- warning("Error finding plugin directories");
+ byte *buf;
+ int offset, left, written;
+ int samples, i;
- env->ExceptionDescribe();
- env->ExceptionClear();
+ struct timespec tv_delay;
+ tv_delay.tv_sec = 0;
+ tv_delay.tv_nsec = 20 * 1000 * 1000;
- return;
- }
+ uint msecs_full = buf_size * 1000 / (mixer->getOutputRate() * 2 * 2);
- jsize size = env->GetArrayLength(array);
- for (jsize i = 0; i < size; ++i) {
- jstring path_obj = (jstring)env->GetObjectArrayElement(array, i);
+ struct timespec tv_full;
+ tv_full.tv_sec = 0;
+ tv_full.tv_nsec = msecs_full * 1000 * 1000;
- if (path_obj == 0)
- continue;
+ bool silence;
+ uint silence_count = 33;
- const char *path = env->GetStringUTFChars(path_obj, 0);
- if (path == 0) {
- warning("Error getting string characters from plugin directory");
+ while (!system->_audio_thread_exit) {
+ if (JNI::pause) {
+ JNI::setAudioStop();
- env->ExceptionClear();
- env->DeleteLocalRef(path_obj);
+ paused = true;
+ silence_count = 33;
- continue;
+ LOGD("audio thread going to sleep");
+ sem_wait(&JNI::pause_sem);
+ LOGD("audio 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("%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;
- }
-}
-
-const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
- static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
- { "default", "Default", 1 },
- { 0, 0, 0 },
- };
-
- return s_supportedGraphicsModes;
-}
-
-
-int OSystem_Android::getDefaultGraphicsMode() const {
- return 1;
-}
-
-bool OSystem_Android::setGraphicsMode(const char *mode) {
- ENTER("%s", mode);
- return true;
-}
-
-bool OSystem_Android::setGraphicsMode(int mode) {
- ENTER("%d", mode);
- return true;
-}
-
-int OSystem_Android::getGraphicsMode() const {
- return 1;
-}
-
-void OSystem_Android::setupScummVMSurface() {
- ENTER();
-
- JNIEnv *env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
-
- if (env->ExceptionCheck())
- return;
-
- // EGL set up with a new surface. Initialise OpenGLES context.
- GLESTexture::initGLExtensions();
-
- // Turn off anything that looks like 3D ;)
- GLCALL(glDisable(GL_CULL_FACE));
- GLCALL(glDisable(GL_DEPTH_TEST));
- GLCALL(glDisable(GL_LIGHTING));
- GLCALL(glDisable(GL_FOG));
- GLCALL(glDisable(GL_DITHER));
-
- GLCALL(glShadeModel(GL_FLAT));
- GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
-
- GLCALL(glEnable(GL_BLEND));
- GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
-
- GLCALL(glEnableClientState(GL_VERTEX_ARRAY));
- GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
-
- GLCALL(glEnable(GL_TEXTURE_2D));
-
- if (!_game_texture)
- _game_texture = new GLESPaletteTexture();
- else
- _game_texture->reinitGL();
-
- if (!_overlay_texture)
- _overlay_texture = new GLES4444Texture();
- else
- _overlay_texture->reinitGL();
-
- if (!_mouse_texture)
- _mouse_texture = new GLESPaletteATexture();
- else
- _mouse_texture->reinitGL();
-
- GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height));
-
- GLCALL(glMatrixMode(GL_PROJECTION));
- GLCALL(glLoadIdentity());
- GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1));
- GLCALL(glMatrixMode(GL_MODELVIEW));
- GLCALL(glLoadIdentity());
-
- clearFocusRectangle();
-}
-
-void OSystem_Android::destroyScummVMSurface() {
- JNIEnv *env = JNU_GetEnv();
- env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
- // Can't use OpenGLES functions after this
-}
-
-void OSystem_Android::initSize(uint width, uint height,
- const Graphics::PixelFormat *format) {
- ENTER("%d, %d, %p", width, height, format);
-
- _game_texture->allocBuffer(width, height);
-
- // Cap at 320x200 or the ScummVM themes abort :/
- GLuint overlay_width = MIN(_egl_surface_width, 320);
- GLuint overlay_height = MIN(_egl_surface_height, 200);
- _overlay_texture->allocBuffer(overlay_width, overlay_height);
-
- // Don't know mouse size yet - it gets reallocated in
- // setMouseCursor. We need the palette allocated before
- // setMouseCursor however, so just take a guess at the desired
- // size (it's small).
- _mouse_texture->allocBuffer(20, 20);
-}
-
-int16 OSystem_Android::getHeight() {
- return _game_texture->height();
-}
-
-int16 OSystem_Android::getWidth() {
- return _game_texture->width();
-}
-
-void OSystem_Android::setPalette(const byte *colors, uint start, uint num) {
- ENTER("%p, %u, %u", colors, start, num);
+ buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0);
+ assert(buf);
- if (!_use_mouse_palette)
- _setCursorPalette(colors, start, num);
+ samples = mixer->mixCallback(buf, buf_size);
- memcpy(_game_texture->palette() + start * 3, colors, num * 3);
-}
-
-void OSystem_Android::grabPalette(byte *colors, uint start, uint num) {
- ENTER("%p, %u, %u", colors, start, num);
- memcpy(colors, _game_texture->palette_const() + start * 3, num * 3);
-}
-
-void OSystem_Android::copyRectToScreen(const byte *buf, int pitch,
- int x, int y, int w, int h) {
- ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
-
- _game_texture->updateBuffer(x, y, w, h, buf, pitch);
-}
-
-void OSystem_Android::updateScreen() {
- //ENTER();
-
- if (!_force_redraw &&
- !_game_texture->dirty() &&
- !_overlay_texture->dirty() &&
- !_mouse_texture->dirty())
- return;
-
- _force_redraw = false;
-
- GLCALL(glPushMatrix());
-
- if (_shake_offset != 0 ||
- (!_focus_rect.isEmpty() &&
- !Common::Rect(_game_texture->width(),
- _game_texture->height()).contains(_focus_rect))) {
- // These are the only cases where _game_texture doesn't
- // cover the entire screen.
- GLCALL(glClearColorx(0, 0, 0, 1 << 16));
- GLCALL(glClear(GL_COLOR_BUFFER_BIT));
-
- // Move everything up by _shake_offset (game) pixels
- GLCALL(glTranslatex(0, -_shake_offset << 16, 0));
- }
-
- if (_focus_rect.isEmpty()) {
- _game_texture->drawTexture(0, 0,
- _egl_surface_width, _egl_surface_height);
- } else {
- GLCALL(glPushMatrix());
- GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()),
- xdiv(_egl_surface_height, _focus_rect.height()),
- 1 << 16));
- GLCALL(glTranslatex(-_focus_rect.left << 16,
- -_focus_rect.top << 16, 0));
- GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width),
- xdiv(_game_texture->height(), _egl_surface_height),
- 1 << 16));
-
- _game_texture->drawTexture(0, 0,
- _egl_surface_width, _egl_surface_height);
- GLCALL(glPopMatrix());
- }
-
- int cs = _mouse_targetscale;
-
- if (_show_overlay) {
- // ugly, but the modern theme sets a wacko factor, only god knows why
- cs = 1;
-
- GLCALL(_overlay_texture->drawTexture(0, 0,
- _egl_surface_width,
- _egl_surface_height));
- }
-
- if (_show_mouse) {
- GLCALL(glPushMatrix());
+ silence = samples < 1;
- // Scale up ScummVM -> OpenGL (pixel) coordinates
- int texwidth, texheight;
+ // looks stupid, and it is, but currently there's no way to detect
+ // silence-only buffers from the mixer
+ if (!silence) {
+ silence = true;
- if (_show_overlay) {
- texwidth = getOverlayWidth();
- texheight = getOverlayHeight();
- } else {
- texwidth = getWidth();
- texheight = getHeight();
+ for (i = 0; i < samples; i += 2)
+ // SID streams constant crap
+ if (READ_UINT16(buf + i) > 32) {
+ silence = false;
+ break;
+ }
}
- GLCALL(glScalex(xdiv(_egl_surface_width, texwidth),
- xdiv(_egl_surface_height, texheight),
- 1 << 16));
-
- GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16,
- (-_mouse_hotspot.y * cs) << 16,
- 0));
-
- // Note the extra half texel to position the mouse in
- // the middle of the x,y square:
- const Common::Point& mouse = getEventManager()->getMousePos();
- GLCALL(glTranslatex((mouse.x << 16) | 1 << 15,
- (mouse.y << 16) | 1 << 15, 0));
-
- GLCALL(glScalex(cs << 16, cs << 16, 1 << 16));
-
- _mouse_texture->drawTexture();
+ env->ReleasePrimitiveArrayCritical(bufa, buf, 0);
- GLCALL(glPopMatrix());
- }
-
- GLCALL(glPopMatrix());
+ if (silence) {
+ if (!paused)
+ silence_count++;
- JNIEnv *env = JNU_GetEnv();
- if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
- // Context lost -> need to reinit GL
- destroyScummVMSurface();
- setupScummVMSurface();
- }
-}
+ // only pause after a while to prevent toggle mania
+ if (silence_count > 32) {
+ if (!paused) {
+ LOGD("AudioTrack pause");
-Graphics::Surface *OSystem_Android::lockScreen() {
- ENTER();
+ JNI::setAudioPause();
+ paused = true;
+ }
- Graphics::Surface *surface = _game_texture->surface();
- assert(surface->pixels);
+ nanosleep(&tv_full, 0);
- return surface;
-}
+ continue;
+ }
+ }
-void OSystem_Android::unlockScreen() {
- ENTER();
+ if (paused) {
+ LOGD("AudioTrack play");
- assert(_game_texture->dirty());
-}
+ JNI::setAudioPlay();
+ paused = false;
-void OSystem_Android::setShakePos(int shake_offset) {
- ENTER("%d", shake_offset);
+ silence_count = 0;
+ }
- if (_shake_offset != shake_offset) {
- _shake_offset = shake_offset;
- _force_redraw = true;
- }
-}
+ offset = 0;
+ left = buf_size;
+ written = 0;
-void OSystem_Android::fillScreen(uint32 col) {
- ENTER("%u", col);
+ while (left > 0) {
+ written = JNI::writeAudio(env, bufa, offset, left);
- assert(col < 256);
- _game_texture->fillBuffer(col);
-}
+ if (written < 0) {
+ LOGE("AudioTrack error: %d", written);
+ break;
+ }
-void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
- ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom);
+ // buffer full
+ if (written < left)
+ nanosleep(&tv_delay, 0);
- if (_enable_zoning) {
- _focus_rect = rect;
- _force_redraw = true;
- }
-}
+ offset += written;
+ left -= written;
+ }
-void OSystem_Android::clearFocusRectangle() {
- ENTER();
+ if (written < 0)
+ break;
- if (_enable_zoning) {
- _focus_rect = Common::Rect();
- _force_redraw = true;
+ // prepare the next buffer, and run into the blocking AudioTrack.write
}
-}
-void OSystem_Android::showOverlay() {
- ENTER();
+ JNI::setAudioStop();
- _show_overlay = true;
- _force_redraw = true;
-}
+ env->DeleteLocalRef(bufa);
-void OSystem_Android::hideOverlay() {
- ENTER();
+ JNI::detachThread();
- _show_overlay = false;
- _force_redraw = true;
+ return 0;
}
-void OSystem_Android::clearOverlay() {
+void OSystem_Android::initBackend() {
ENTER();
- _overlay_texture->fillBuffer(0);
-
- // Shouldn't need this, but works around a 'blank screen' bug on Nexus1
- updateScreen();
-}
-
-void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
- ENTER("%p, %d", buf, pitch);
-
- // We support overlay alpha blending, so the pixel data here
- // shouldn't actually be used. Let's fill it with zeros, I'm sure
- // it will be fine...
- const Graphics::Surface *surface = _overlay_texture->surface_const();
- assert(surface->bytesPerPixel == sizeof(buf[0]));
-
- int h = surface->h;
-
- do {
- memset(buf, 0, surface->w * sizeof(buf[0]));
-
- // This 'pitch' is pixels not bytes
- buf += pitch;
- } while (--h);
-}
-
-void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch,
- int x, int y, int w, int h) {
- ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
-
- const Graphics::Surface *surface = _overlay_texture->surface_const();
- assert(surface->bytesPerPixel == sizeof(buf[0]));
-
- // This 'pitch' is pixels not bytes
- _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0]));
-
- // Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
- updateScreen();
-}
+ _main_thread = pthread_self();
-int16 OSystem_Android::getOverlayHeight() {
- return _overlay_texture->height();
-}
-
-int16 OSystem_Android::getOverlayWidth() {
- return _overlay_texture->width();
-}
-
-bool OSystem_Android::showMouse(bool visible) {
- ENTER("%d", visible);
-
- _show_mouse = visible;
-
- return true;
-}
-
-void OSystem_Android::warpMouse(int x, int y) {
- ENTER("%d, %d", x, y);
-
- // We use only the eventmanager's idea of the current mouse
- // position, so there is nothing extra to do here.
-}
-
-void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h,
- int hotspotX, int hotspotY,
- uint32 keycolor, int cursorTargetScale,
- const Graphics::PixelFormat *format) {
- ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY,
- keycolor, cursorTargetScale, format);
+ ConfMan.registerDefault("fullscreen", true);
+ ConfMan.registerDefault("aspect_ratio", true);
- assert(keycolor < 256);
+ ConfMan.setInt("autosave_period", 0);
+ ConfMan.setBool("FM_high_quality", false);
+ ConfMan.setBool("FM_medium_quality", true);
- _mouse_texture->allocBuffer(w, h);
+ // TODO hackity hack
+ if (ConfMan.hasKey("multi_midi"))
+ _touchpad_mode = !ConfMan.getBool("multi_midi");
- // Update palette alpha based on keycolor
- byte *palette = _mouse_texture->palette();
- int i = 256;
+ // must happen before creating TimerManager to avoid race in
+ // creating EventManager
+ setupKeymapper();
- do {
- palette[3] = 0xff;
- palette += 4;
- } while (--i);
+ // 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();
- palette = _mouse_texture->palette();
- palette[keycolor * 4 + 3] = 0x00;
+ gettimeofday(&_startTime, 0);
- _mouse_texture->updateBuffer(0, 0, w, h, buf, w);
+ _mixer = new Audio::MixerImpl(this, _audio_sample_rate);
+ _mixer->setReady(true);
- _mouse_hotspot = Common::Point(hotspotX, hotspotY);
- _mouse_targetscale = cursorTargetScale;
-}
+ _timer_thread_exit = false;
+ pthread_create(&_timer_thread, 0, timerThreadFunc, this);
-void OSystem_Android::_setCursorPalette(const byte *colors,
- uint start, uint num) {
- byte *palette = _mouse_texture->palette() + start * 4;
+ _audio_thread_exit = false;
+ pthread_create(&_audio_thread, 0, audioThreadFunc, this);
- do {
- for (int i = 0; i < 3; ++i)
- palette[i] = colors[i];
+ initSurface();
+ initViewport();
- // Leave alpha untouched to preserve keycolor
+ _game_texture = new GLESFakePalette565Texture();
+ _overlay_texture = new GLES4444Texture();
+ _mouse_texture_palette = new GLESPalette5551Texture();
+ _mouse_texture = _mouse_texture_palette;
- palette += 4;
- colors += 3;
- } while (--num);
-}
+ initOverlay();
-void OSystem_Android::setCursorPalette(const byte *colors,
- uint start, uint num) {
- ENTER("%p, %u, %u", colors, start, num);
+ // renice this thread to boost the audio thread
+ if (setpriority(PRIO_PROCESS, 0, 19) < 0)
+ warning("couldn't renice the main thread");
- _setCursorPalette(colors, start, num);
- _use_mouse_palette = true;
+ JNI::setReadyForEvents(true);
}
-void OSystem_Android::disableCursorPalette(bool disable) {
- ENTER("%d", disable);
+void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const {
+ ENTER();
- _use_mouse_palette = !disable;
+ JNI::getPluginDirectories(dirs);
}
-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
+bool OSystem_Android::hasFeature(Feature f) {
+ return (f == kFeatureFullscreenMode ||
+ f == kFeatureAspectRatioCorrection ||
+ f == kFeatureCursorHasPalette ||
+ f == kFeatureVirtualKeyboard ||
+ f == kFeatureOverlaySupportsAlpha);
}
-bool OSystem_Android::pollEvent(Common::Event &event) {
- //ENTER();
-
- lockMutex(_event_queue_lock);
-
- if (_event_queue.empty()) {
- unlockMutex(_event_queue_lock);
- return false;
- }
+void OSystem_Android::setFeatureState(Feature f, bool enable) {
+ ENTER("%d, %d", f, enable);
- 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: {
- // relative mouse hack
- if (event.kbd.flags == 1) {
- // 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, clear relative flag
- tail.kbd.flags = 0;
- 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() {
@@ -1219,7 +408,7 @@ uint32 OSystem_Android::getMillis() {
gettimeofday(&curTime, 0);
- return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + \
+ return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) +
((curTime.tv_usec - _startTime.tv_usec) / 1000));
}
@@ -1229,6 +418,7 @@ void OSystem_Android::delayMillis(uint msecs) {
OSystem::MutexRef OSystem_Android::createMutex() {
pthread_mutexattr_t attr;
+
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
@@ -1267,58 +457,38 @@ void OSystem_Android::deleteMutex(MutexRef mutex) {
void OSystem_Android::quit() {
ENTER();
+ JNI::setReadyForEvents(false);
+
+ _audio_thread_exit = true;
+ pthread_join(_audio_thread, 0);
+
_timer_thread_exit = true;
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("%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);
+ JNI::setWindowCaption(caption);
}
void OSystem_Android::displayMessageOnOSD(const char *msg) {
ENTER("%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);
+ JNI::displayMessageOnOSD(msg);
}
void OSystem_Android::showVirtualKeyboard(bool enable) {
ENTER("%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();
- }
+ JNI::showVirtualKeyboard(enable);
}
Common::SaveFileManager *OSystem_Android::getSavefileManager() {
@@ -1355,37 +525,13 @@ 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;
- }
-
- 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);
- }
+ ENTER("");
- 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:
__android_log_write(ANDROID_LOG_DEBUG, android_log_tag, message);
@@ -1401,177 +547,11 @@ void OSystem_Android::logMessage(LogMessageType::Type type, const char *message)
}
}
-static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) {
- OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self);
-
- const int MAX_NARGS = 32;
- int res = -1;
-
- int argc = env->GetArrayLength(args);
- if (argc > MAX_NARGS) {
- JNU_ThrowByName(env, "java/lang/IllegalArgumentException",
- "too many arguments");
- return 0;
- }
-
- char *argv[MAX_NARGS];
-
- // note use in cleanup loop below
- int nargs;
-
- for (nargs = 0; nargs < argc; ++nargs) {
- jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
-
- if (arg == 0) {
- argv[nargs] = 0;
- } else {
- const char *cstr = env->GetStringUTFChars(arg, 0);
-
- argv[nargs] = const_cast<char *>(cstr);
-
- // exception already thrown?
- if (cstr == 0)
- goto cleanup;
- }
-
- env->DeleteLocalRef(arg);
- }
-
- g_system = cpp_obj;
- assert(g_system);
-
- LOGI("Entering scummvm_main with %d args", argc);
-
- res = scummvm_main(argc, argv);
-
- LOGI("Exiting scummvm_main");
-
- g_system->quit();
-
-cleanup:
- nargs--;
-
- for (int i = 0; i < nargs; ++i) {
- if (argv[i] == 0)
- continue;
-
- jstring arg = (jstring)env->GetObjectArrayElement(args, nargs);
-
- // Exception already thrown?
- if (arg == 0)
- return res;
-
- env->ReleaseStringUTFChars(arg, argv[i]);
- env->DeleteLocalRef(arg);
- }
-
- return res;
-}
-
#ifdef DYNAMIC_MODULES
void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
- OSystem_Android *g_system_android = (OSystem_Android *)g_system;
- g_system_android->addPluginDirectories(dirs);
+ ((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 == 0)
- return JNI_ERR;
-
- if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0)
- return JNI_ERR;
-
- FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J");
- if (FID_ScummVM_nativeScummVM == 0)
- return JNI_ERR;
-
- jclass event = env->FindClass("org/inodes/gus/scummvm/Event");
- if (event == 0)
- return JNI_ERR;
-
- FID_Event_type = env->GetFieldID(event, "type", "I");
- if (FID_Event_type == 0)
- return JNI_ERR;
-
- FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z");
- if (FID_Event_synthetic == 0)
- return JNI_ERR;
-
- FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I");
- if (FID_Event_kbd_keycode == 0)
- return JNI_ERR;
-
- FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I");
- if (FID_Event_kbd_ascii == 0)
- return JNI_ERR;
-
- FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I");
- if (FID_Event_kbd_flags == 0)
- return JNI_ERR;
-
- FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I");
- if (FID_Event_mouse_x == 0)
- return JNI_ERR;
-
- FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I");
- if (FID_Event_mouse_y == 0)
- return JNI_ERR;
-
- FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z");
- if (FID_Event_mouse_relative == 0)
- return JNI_ERR;
-
- cls = env->FindClass("java/lang/Object");
- if (cls == 0)
- return JNI_ERR;
-
- MID_Object_wait = env->GetMethodID(cls, "wait", "()V");
- if (MID_Object_wait == 0)
- return JNI_ERR;
-
- return JNI_VERSION_1_2;
-}
-
#endif
+
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 855fb04b5d..7ff96186f9 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -23,8 +23,23 @@
*
*/
+#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>
@@ -46,7 +61,7 @@ extern const char *android_log_tag;
#ifdef ANDROID_DEBUG_ENTER
#define ENTER(fmt, args...) LOGD("%s(" fmt ")", __FUNCTION__, ##args)
#else
-#define ENTER(fmt, args...) /**/
+#define ENTER(fmt, args...) do { } while (false)
#endif
#ifdef ANDROID_DEBUG_GL
@@ -58,13 +73,215 @@ extern void checkGlError(const char *expr, const char *file, int line);
checkGlError(#x, __FILE__, __LINE__); \
} while (false)
+#define GLTHREADCHECK \
+ do { \
+ assert(pthread_self() == _main_thread); \
+ } while (false)
+
#else
#define GLCALL(x) do { (x); } while (false)
+#define GLTHREADCHECK do { } while (false)
+#endif
+
+#ifdef DYNAMIC_MODULES
+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 _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;
+ GLESPaletteTexture *_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;
+
+ 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
-// Fix JNIEXPORT declaration to actually do something useful
-#undef JNIEXPORT
-#define JNIEXPORT __attribute__ ((visibility("default")))
+ 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_dt;
+ int _eventScaleX;
+ int _eventScaleY;
+ bool _touchpad_mode;
+ int _touchpad_scale;
+ int _trackball_scale;
+ int _dpad_scale;
+
+ 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);
+};
+
+#endif
#endif
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 1bc3c3d21a..cb39f8acfe 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -6,6 +6,7 @@ ANDROID_PLUGIN_VERSIONCODE = 6
JAVA_FILES = \
ScummVM.java \
+ ScummVMEvents.java \
ScummVMApplication.java \
ScummVMActivity.java \
EditableSurfaceView.java \
@@ -163,6 +164,10 @@ release/%.apk: %.apk
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: $(APK_MAIN) $(APK_PLUGINS)
@set -e; for apk in $^; do \
$(ADB) install -r $$apk; \
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index 71ce25aa72..26b1a6ad39 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -36,10 +36,9 @@
#include "common/archive.h"
#include "common/debug.h"
+#include "backends/platform/android/jni.h"
#include "backends/platform/android/asset-archive.h"
-extern JNIEnv *JNU_GetEnv();
-
// Must match android.content.res.AssetManager.ACCESS_*
const jint ACCESS_UNKNOWN = 0;
const jint ACCESS_RANDOM = 1;
@@ -100,7 +99,7 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) :
{
_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");
@@ -124,7 +123,7 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) :
}
JavaInputStream::~JavaInputStream() {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
close(env);
env->DeleteGlobalRef(_buf);
@@ -139,11 +138,11 @@ void JavaInputStream::close(JNIEnv *env) {
}
uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
if (_buflen < jint(dataSize)) {
_buflen = dataSize;
-
+
env->DeleteGlobalRef(_buf);
_buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
}
@@ -171,7 +170,7 @@ uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
}
bool JavaInputStream::seek(int32 offset, int whence) {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
uint32 newpos;
switch (whence) {
@@ -305,7 +304,8 @@ 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);
@@ -318,7 +318,7 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) :
}
AssetFdReadStream::~AssetFdReadStream() {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
env->CallVoidMethod(_assetfd, MID_close);
if (env->ExceptionCheck())
@@ -369,7 +369,7 @@ bool AssetFdReadStream::seek(int32 offset, int whence) {
}
AndroidAssetArchive::AndroidAssetArchive(jobject am) {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
_am = env->NewGlobalRef(am);
jclass cls = env->GetObjectClass(_am);
@@ -377,8 +377,8 @@ AndroidAssetArchive::AndroidAssetArchive(jobject am) {
"(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",
@@ -387,12 +387,12 @@ AndroidAssetArchive::AndroidAssetArchive(jobject am) {
}
AndroidAssetArchive::~AndroidAssetArchive() {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
env->DeleteGlobalRef(_am);
}
bool AndroidAssetArchive::hasFile(const Common::String &name) {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
jstring path = env->NewStringUTF(name.c_str());
jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN);
if (env->ExceptionCheck()) {
@@ -412,7 +412,7 @@ bool AndroidAssetArchive::hasFile(const Common::String &name) {
}
int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
Common::List<Common::String> dirlist;
dirlist.push_back("");
@@ -422,7 +422,8 @@ 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.",
@@ -469,7 +470,7 @@ Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &na
}
Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
- JNIEnv *env = JNU_GetEnv();
+ JNIEnv *env = JNI::getEnv();
jstring jpath = env->NewStringUTF(path.c_str());
// Try openFd() first ...
diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h
index 28e48426e9..6ec86e4cd0 100644
--- a/backends/platform/android/asset-archive.h
+++ b/backends/platform/android/asset-archive.h
@@ -23,6 +23,9 @@
*
*/
+#ifndef _ANDROID_ASSET_H_
+#define _ANDROID_ASSET_H_
+
#if defined(__ANDROID__)
#include <jni.h>
@@ -51,3 +54,5 @@ private:
};
#endif
+#endif
+
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
new file mode 100644
index 0000000000..1715e6a8a7
--- /dev/null
+++ b/backends/platform/android/events.cpp
@@ -0,0 +1,661 @@
+/* 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_DOWN = 2,
+ JE_SCROLL = 3,
+ JE_TAP = 4,
+ JE_DOUBLE_TAP = 5,
+ JE_BALL = 6,
+ JE_QUIT = 0x1000
+};
+
+// action type
+enum {
+ JACTION_DOWN = 0,
+ JACTION_UP = 1,
+ JACTION_MULTIPLE = 2
+};
+
+// 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()));
+ p.y = CLIP(p.y, int16(0), int16(tex->height()));
+}
+
+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;
+
+ default:
+ LOGW("unmapped system key: %d", arg2);
+ return;
+ }
+
+ break;
+
+ case JE_KEY:
+ // five-way first
+ 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.synthetic = true;
+
+ 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(arg5, 1, 8) * _dpad_scale * 100 / s;
+
+ *c += ((arg2 == JKEYCODE_DPAD_UP ||
+ arg2 == JKEYCODE_DPAD_LEFT) ? -1 : 1) * 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;
+ }
+
+ {
+ const Common::Point &m = getEventManager()->getMousePos();
+
+ e.mouse = m;
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+ }
+
+ return;
+ }
+
+ 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)) {
+ LOGE("received invalid keycode: %d", arg2);
+ return;
+ }
+
+ if (arg5 > 0)
+ e.synthetic = true;
+
+ e.kbd.keycode = jkeymap[arg2];
+ e.kbd.ascii = arg3;
+
+ 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_DOWN:
+ _touch_pt_down = getEventManager()->getMousePos();
+ break;
+
+ case JE_SCROLL:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ if (_touchpad_mode) {
+ scaleMouse(e.mouse, arg3 - arg1, arg4 - arg2, 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:
+ 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 = arg1;
+ _touch_pt_dt.y = arg2;
+ break;
+ case JACTION_UP:
+ dptype = Common::EVENT_LBUTTONUP;
+ break;
+ case JACTION_MULTIPLE:
+ // held and moved
+ 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_BALL:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ e.mouse = getEventManager()->getMousePos();
+
+ // already multiplied by 100
+ e.mouse.x += arg1 * _trackball_scale / _eventScaleX;
+ e.mouse.y += arg2 * _trackball_scale / _eventScaleY;
+
+ clipMouse(e.mouse);
+
+ 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) {
+ if (_egl_surface_width > 0 && _egl_surface_height > 0) {
+ // surface still alive but changed
+ _screen_changeid = JNI::surface_changeid;
+ _egl_surface_width = JNI::egl_surface_width;
+ _egl_surface_height = JNI::egl_surface_height;
+
+ initViewport();
+ updateScreenRect();
+ updateEventScale();
+
+ // double buffered, flip twice
+ clearScreen(kClearUpdate, 2);
+
+ event.type = Common::EVENT_SCREEN_CHANGED;
+
+ return true;
+ } else {
+ // new surface
+ initSurface();
+ 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..d7e31fcad7
--- /dev/null
+++ b/backends/platform/android/gfx.cpp
@@ -0,0 +1,810 @@
+/* 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);
+
+ _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);
+ (*texture)->fillBuffer(0);
+}
+#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() {
+ int overlay_width = _egl_surface_width;
+ int overlay_height = _egl_surface_height;
+
+ // the 'normal' theme layout uses a max height of 400 pixels. if the
+ // surface is too big we use only a quarter of the size so that the widgets
+ // don't get too small. if the surface height has less than 800 pixels, this
+ // enforces the 'lowres' layout, which will be scaled back up by factor 2x,
+ // but this looks way better than the 'normal' layout scaled by some
+ // calculated factors
+ if (overlay_height > 480) {
+ overlay_width /= 2;
+ overlay_height /= 2;
+ }
+
+ LOGI("overlay size is %ux%u", overlay_width, overlay_height);
+
+ _overlay_texture->allocBuffer(overlay_width, overlay_height);
+ _overlay_texture->fillBuffer(0);
+ _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);
+ _game_texture->fillBuffer(0);
+#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);
+
+ 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));
+}
+
+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
+ if (_show_overlay && !_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) {
+ 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();
+
+ clearScreen(kClear);
+
+ _show_overlay = false;
+ _force_redraw = true;
+
+ updateEventScale();
+
+ warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
+
+ GLCALL(glEnable(GL_SCISSOR_TEST));
+}
+
+void OSystem_Android::clearOverlay() {
+ ENTER();
+
+ GLTHREADCHECK;
+
+ _overlay_texture->fillBuffer(0);
+
+ // breaks more than it fixes, disabled for now
+ // Shouldn't need this, but works around a 'blank screen' bug on Nexus1
+ //updateScreen();
+}
+
+void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) {
+ ENTER("%p, %d", buf, pitch);
+
+ 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]));
+
+ // Shouldn't need this, but works around a 'blank screen' bug on Nexus1?
+ //updateScreen();
+}
+
+int16 OSystem_Android::getOverlayHeight() {
+ return _overlay_texture->height();
+}
+
+int16 OSystem_Android::getOverlayWidth() {
+ return _overlay_texture->width();
+}
+
+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");
+
+ _mouse_texture_rgb = new GLES5551Texture();
+ _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;
+ WRITE_UINT16(_mouse_texture_palette->palette() + keycolor * 2, 0);
+ }
+
+ if (w == 0 || h == 0) {
+ _show_mouse = false;
+ 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;
+
+ _show_mouse = false;
+
+ 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]));
+
+ WRITE_UINT16(_mouse_texture_palette->palette() + _mouse_keycolor * 2, 0);
+}
+
+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));
+ }
+
+ WRITE_UINT16(_mouse_texture_palette->palette() + _mouse_keycolor * 2, 0);
+ }
+
+ _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..92cb04904c
--- /dev/null
+++ b/backends/platform/android/jni.cpp
@@ -0,0 +1,602 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(__ANDROID__)
+
+#include "base/main.h"
+#include "common/config-manager.h"
+#include "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) {
+ 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 8b120b21ff..2fe4b40585 100644
--- a/backends/platform/android/module.mk
+++ b/backends/platform/android/module.mk
@@ -1,9 +1,12 @@
MODULE := backends/platform/android
MODULE_OBJS := \
- android.o \
+ jni.o \
+ texture.o \
asset-archive.o \
- video.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))
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 c94ab0a3ff..3c91d9f5dc 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java
@@ -28,7 +28,7 @@ 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(LOG_TAG, "Error finding my own info?", e);
return;
@@ -38,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 0e905f43a5..fe225af48b 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -1,446 +1,427 @@
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 {
- protected final static String LOG_TAG = "ScummVM";
+ // 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) {
+ 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) {
- try {
- surfaceLock.acquire();
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "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);
- eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
- EGL10.EGL_NO_CONTEXT, null);
- if (eglContext == EGL10.EGL_NO_CONTEXT)
- throw new RuntimeException("Failed to create context");
- }
+ _egl_context = _egl.eglCreateContext(_egl_display, _egl_config,
+ EGL10.EGL_NO_CONTEXT, null);
- private EGLConfig chooseEglConfig(EGLConfig[] configs) {
- int best = 0;
- int bestScore = -1;
- int[] value = new int[1];
+ if (_egl_context == EGL10.EGL_NO_CONTEXT)
+ throw new Exception(String.format("Failed to create context: 0x%x",
+ _egl.eglGetError()));
+ }
- 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;
- 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;
+ if (_buffer_size < buffer_size_want) {
+ Log.w(LOG_TAG, String.format(
+ "adjusting audio buffer size (was: %d)", _buffer_size));
+
+ _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(LOG_TAG, "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 {
@@ -448,15 +429,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 fae35b6695..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,27 +34,22 @@ 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
@@ -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,336 +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.LOG_TAG, "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(ScummVM.LOG_TAG, "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()
- };
+ });
- 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(ScummVM.LOG_TAG, "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
@@ -463,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..3d3fdeece4
--- /dev/null
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java
@@ -0,0 +1,201 @@
+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_DOWN = 2;
+ public static final int JE_SCROLL = 3;
+ public static final int JE_TAP = 4;
+ public static final int JE_DOUBLE_TAP = 5;
+ public static final int JE_BALL = 6;
+ public static final int JE_QUIT = 0x1000;
+
+ final protected Context _context;
+ final protected ScummVM _scummvm;
+ final protected GestureDetector _gd;
+ final protected int _longPress;
+ final protected int _slop;
+
+ public ScummVMEvents(Context context, ScummVM scummvm) {
+ _context = context;
+ _scummvm = scummvm;
+
+ _gd = new GestureDetector(context, this);
+ _gd.setOnDoubleTapListener(this);
+ _gd.setIsLongpressEnabled(false);
+
+ _longPress = ViewConfiguration.getLongPressTimeout();
+ _slop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+ }
+
+ final public void sendQuitEvent() {
+ _scummvm.pushEvent(JE_QUIT, 0, 0, 0, 0, 0);
+ }
+
+ public boolean onTrackballEvent(MotionEvent e) {
+ _scummvm.pushEvent(JE_BALL, (int)(e.getX() * e.getXPrecision() * 100),
+ (int)(e.getY() * e.getYPrecision() * 100), 0, 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:
+ 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) {
+ KeyCharacterMap m = KeyCharacterMap.load(e.getDeviceId());
+
+ for (KeyEvent s : m.getEvents(e.getCharacters().toCharArray())) {
+ _scummvm.pushEvent(JE_KEY, s.getAction(), s.getKeyCode(),
+ s.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK,
+ s.getMetaState(), s.getRepeatCount());
+ }
+
+ 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) {
+ 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(), _slop);
+
+ 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(), _slop, 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 8811b1f3ae..c4b2ad7f5d 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
@@ -370,3 +370,4 @@ public class Unpacker extends Activity {
}
}
}
+
diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp
new file mode 100644
index 0000000000..691c384a18
--- /dev/null
+++ b/backends/platform/android/texture.cpp
@@ -0,0 +1,571 @@
+/* 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() {
+ 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);
+
+ if (_surface.w == oldw && _surface.h == oldh)
+ return;
+
+ delete[] _buf;
+ delete[] _pixels;
+
+ _pixels = new byte[w * h * _surface.bytesPerPixel];
+ assert(_pixels);
+
+ _surface.pixels = _pixels;
+ _surface.pitch = w * _pixelFormat.bytesPerPixel;
+
+ _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() {
+}
+
+GLESPaletteTexture::GLESPaletteTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat palettePixelFormat) :
+ GLESBaseTexture(glFormat, glType,
+ Graphics::PixelFormat::createFormatCLUT8()),
+ _texture(0)
+{
+ _palettePixelFormat = palettePixelFormat;
+ _paletteSize = _palettePixelFormat.bytesPerPixel * 256;
+}
+
+GLESPaletteTexture::~GLESPaletteTexture() {
+ delete[] _texture;
+}
+
+void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
+ GLuint oldw = _surface.w;
+ GLuint oldh = _surface.h;
+
+ GLESBaseTexture::allocBuffer(w, h);
+
+ if (_surface.w == oldw && _surface.h == oldh)
+ return;
+
+ byte *new_buffer = new byte[_paletteSize +
+ _texture_width * _texture_height];
+ assert(new_buffer);
+
+ if (_texture) {
+ // preserve palette
+ memcpy(new_buffer, _texture, _paletteSize);
+ delete[] _texture;
+ }
+
+ _texture = new_buffer;
+ _surface.pixels = _texture + _paletteSize;
+ _surface.pitch = _texture_width;
+}
+
+void GLESPaletteTexture::fillBuffer(uint32 color) {
+ assert(_surface.pixels);
+ memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h);
+ setDirty();
+}
+
+void GLESPaletteTexture::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 = static_cast<const byte *>(buf);
+ byte *dst = static_cast<byte *>(_surface.getBasePtr(x, y));
+
+ do {
+ memcpy(dst, src, w);
+ dst += _surface.pitch;
+ src += pitch_buf;
+ } while (--h);
+}
+
+void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w,
+ GLshort h) {
+ if (dirty()) {
+ GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
+
+ const size_t texture_size = _paletteSize +
+ _texture_width * _texture_height;
+
+ GLCALL(glCompressedTexImage2D(GL_TEXTURE_2D, 0, _glType,
+ _texture_width, _texture_height,
+ 0, texture_size, _texture));
+ }
+
+ GLESBaseTexture::drawTexture(x, y, w, h);
+}
+
+GLESPalette888Texture::GLESPalette888Texture() :
+ GLESPaletteTexture(GL_RGB, GL_PALETTE8_RGB8_OES,
+ Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)) {
+}
+
+GLESPalette888Texture::~GLESPalette888Texture() {
+}
+
+GLESPalette8888Texture::GLESPalette8888Texture() :
+ GLESPaletteTexture(GL_RGBA, GL_PALETTE8_RGBA8_OES,
+ Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) {
+}
+
+GLESPalette8888Texture::~GLESPalette8888Texture() {
+}
+
+GLESPalette565Texture::GLESPalette565Texture() :
+ GLESPaletteTexture(GL_RGB, GL_PALETTE8_R5_G6_B5_OES,
+ Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) {
+}
+
+GLESPalette565Texture::~GLESPalette565Texture() {
+}
+
+GLESPalette4444Texture::GLESPalette4444Texture() :
+ GLESPaletteTexture(GL_RGBA, GL_PALETTE8_RGBA4_OES,
+ Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) {
+}
+
+GLESPalette4444Texture::~GLESPalette4444Texture() {
+}
+
+GLESPalette5551Texture::GLESPalette5551Texture() :
+ GLESPaletteTexture(GL_RGBA, GL_PALETTE8_RGB5_A1_OES,
+ Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) {
+}
+
+GLESPalette5551Texture::~GLESPalette5551Texture() {
+}
+
+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);
+
+ if (_surface.w == oldw && _surface.h == oldh)
+ 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;
+ _surface.bytesPerPixel = 1;
+ _surface.pitch = w;
+
+ _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() {
+}
+
+#endif
+
diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h
new file mode 100644
index 0000000000..64489da0a4
--- /dev/null
+++ b/backends/platform/android/texture.h
@@ -0,0 +1,331 @@
+/* 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 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 GLESPaletteTexture : public GLESBaseTexture {
+protected:
+ GLESPaletteTexture(GLenum glFormat, GLenum glType,
+ Graphics::PixelFormat palettePixelFormat);
+
+public:
+ virtual ~GLESPaletteTexture();
+
+ 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 _texture;
+ };
+
+ virtual byte *palette() {
+ setDirty();
+ return _texture;
+ };
+
+protected:
+ byte *_texture;
+ size_t _paletteSize;
+};
+
+// RGB888 256-entry paletted texture
+class GLESPalette888Texture : public GLESPaletteTexture {
+public:
+ GLESPalette888Texture();
+ virtual ~GLESPalette888Texture();
+};
+
+// RGBA8888 256-entry paletted texture
+class GLESPalette8888Texture : public GLESPaletteTexture {
+public:
+ GLESPalette8888Texture();
+ virtual ~GLESPalette8888Texture();
+};
+
+// RGB565 256-entry paletted texture
+class GLESPalette565Texture : public GLESPaletteTexture {
+public:
+ GLESPalette565Texture();
+ virtual ~GLESPalette565Texture();
+};
+
+// RGBA4444 256-entry paletted texture
+class GLESPalette4444Texture : public GLESPaletteTexture {
+public:
+ GLESPalette4444Texture();
+ virtual ~GLESPalette4444Texture();
+};
+
+// RGBA5551 256-entry paletted texture
+class GLESPalette5551Texture : public GLESPaletteTexture {
+public:
+ GLESPalette5551Texture();
+ virtual ~GLESPalette5551Texture();
+};
+
+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();
+};
+
+#endif
+#endif
+
diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp
deleted file mode 100644
index f8427c2ac8..0000000000
--- a/backends/platform/android/video.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#if defined(__ANDROID__)
-
-#include "base/main.h"
-#include "graphics/surface.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-#include "common/util.h"
-#include "common/tokenizer.h"
-
-#include "backends/platform/android/android.h"
-#include "backends/platform/android/video.h"
-
-// Unfortunately, Android devices are too varied to make broad assumptions :/
-#define TEXSUBIMAGE_IS_EXPENSIVE 0
-
-// Supported GL extensions
-static bool npot_supported = false;
-#ifdef GL_OES_draw_texture
-static bool draw_tex_supported = false;
-#endif
-
-static inline GLfixed xdiv(int numerator, int denominator) {
- assert(numerator < (1 << 16));
- return (numerator << 16) / denominator;
-}
-
-template <class T>
-static T nextHigher2(T k) {
- if (k == 0)
- return 1;
- --k;
-
- for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1)
- k = k | k >> i;
-
- return k + 1;
-}
-
-void GLESTexture::initGLExtensions() {
- const char *ext_string =
- reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
-
- LOGI("Extensions: %s", ext_string);
-
- Common::StringTokenizer tokenizer(ext_string, " ");
- while (!tokenizer.empty()) {
- Common::String token = tokenizer.nextToken();
-
- if (token == "GL_ARB_texture_non_power_of_two")
- npot_supported = true;
-
-#ifdef GL_OES_draw_texture
- if (token == "GL_OES_draw_texture")
- draw_tex_supported = true;
-#endif
- }
-}
-
-GLESTexture::GLESTexture() :
- _texture_width(0),
- _texture_height(0),
- _all_dirty(true)
-{
- GLCALL(glGenTextures(1, &_texture_name));
-
- // This all gets reset later in allocBuffer:
- _surface.w = 0;
- _surface.h = 0;
- _surface.pitch = _texture_width;
- _surface.pixels = 0;
- _surface.bytesPerPixel = 0;
-}
-
-GLESTexture::~GLESTexture() {
- debug("Destroying texture %u", _texture_name);
- GLCALL(glDeleteTextures(1, &_texture_name));
-}
-
-void GLESTexture::reinitGL() {
- GLCALL(glDeleteTextures(1, &_texture_name));
- GLCALL(glGenTextures(1, &_texture_name));
-
- // bypass allocBuffer() shortcut to reinit the texture properly
- _texture_width = 0;
- _texture_height = 0;
-
- allocBuffer(_surface.w, _surface.h);
- setDirty();
-}
-
-void GLESTexture::allocBuffer(GLuint w, GLuint h) {
- int bpp = bytesPerPixel();
- _surface.w = w;
- _surface.h = h;
- _surface.bytesPerPixel = bpp;
-
- // Already allocated a sufficiently large buffer?
- if (w <= _texture_width && h <= _texture_height)
- return;
-
- if (npot_supported) {
- _texture_width = _surface.w;
- _texture_height = _surface.h;
- } else {
- _texture_width = nextHigher2(_surface.w);
- _texture_height = nextHigher2(_surface.h);
- }
-
- _surface.pitch = _texture_width * bpp;
-
- // Allocate room for the texture now, but pixel data gets uploaded
- // later (perhaps with multiple TexSubImage2D operations).
- GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
- GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, glFormat(),
- _texture_width, _texture_height,
- 0, glFormat(), glType(), 0));
-}
-
-void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
- const void *buf, int pitch) {
- ENTER("%u, %u, %u, %u, %p, %d", x, y, w, h, buf, pitch);
-
- GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
- GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
-
- setDirtyRect(Common::Rect(x, y, x+w, y+h));
-
- if (static_cast<int>(w) * bytesPerPixel() == pitch) {
- GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
- glFormat(), glType(), buf));
- } else {
- // GLES removed the ability to specify pitch, so we
- // have to do this ourselves.
- if (h == 0)
- return;
-
-#if TEXSUBIMAGE_IS_EXPENSIVE
- byte tmpbuf[w * h * bytesPerPixel()];
- const byte *src = static_cast<const byte *>(buf);
- byte *dst = tmpbuf;
- GLuint count = h;
-
- do {
- memcpy(dst, src, w * bytesPerPixel());
- dst += w * bytesPerPixel();
- src += pitch;
- } while (--count);
-
- GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
- glFormat(), glType(), tmpbuf));
-#else
- // This version avoids the intermediate copy at the expense of
- // repeat glTexSubImage2D calls. On some devices this is worse.
- const byte *src = static_cast<const byte *>(buf);
- do {
- GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
- w, 1, glFormat(), glType(), src));
- ++y;
- src += pitch;
- } while (--h);
-#endif
- }
-}
-
-void GLESTexture::fillBuffer(byte x) {
- int rowbytes = _surface.w * bytesPerPixel();
- byte tmpbuf[_surface.h * rowbytes];
- memset(tmpbuf, x, _surface.h * rowbytes);
- updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes);
-}
-
-void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
- GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-
-#ifdef GL_OES_draw_texture
- // Great extension, but only works under specific conditions.
- // Still a work-in-progress - disabled for now.
- if (false && draw_tex_supported && paletteSize() == 0) {
- //GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
- const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h };
-
- GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop));
-
- // Android GLES bug?
- GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff));
-
- GLCALL(glDrawTexiOES(x, y, 0, w, h));
- } else
-#endif
- {
- const GLfixed tex_width = xdiv(_surface.w, _texture_width);
- const GLfixed tex_height = xdiv(_surface.h, _texture_height);
- const GLfixed texcoords[] = {
- 0, 0,
- tex_width, 0,
- 0, tex_height,
- tex_width, tex_height,
- };
-
- GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords));
-
- const GLshort vertices[] = {
- x, y,
- x + w, y,
- x, y + h,
- x + w, y + h,
- };
-
- GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices));
-
- assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords));
- GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2));
- }
-
- _all_dirty = false;
- _dirty_rect = Common::Rect();
-}
-
-GLESPaletteTexture::GLESPaletteTexture() :
- GLESTexture(),
- _texture(0)
-{
-}
-
-GLESPaletteTexture::~GLESPaletteTexture() {
- delete[] _texture;
-}
-
-void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) {
- int bpp = bytesPerPixel();
- _surface.w = w;
- _surface.h = h;
- _surface.bytesPerPixel = bpp;
-
- // Already allocated a sufficiently large buffer?
- if (w <= _texture_width && h <= _texture_height)
- return;
-
- if (npot_supported) {
- _texture_width = _surface.w;
- _texture_height = _surface.h;
- } else {
- _texture_width = nextHigher2(_surface.w);
- _texture_height = nextHigher2(_surface.h);
- }
- _surface.pitch = _texture_width * bpp;
-
- // Texture gets uploaded later (from drawTexture())
-
- byte *new_buffer = new byte[paletteSize() +
- _texture_width * _texture_height * bytesPerPixel()];
- if (_texture) {
- // preserve palette
- memcpy(new_buffer, _texture, paletteSize());
- delete[] _texture;
- }
-
- _texture = new_buffer;
- _surface.pixels = _texture + paletteSize();
-}
-
-void GLESPaletteTexture::fillBuffer(byte x) {
- assert(_surface.pixels);
- memset(_surface.pixels, x, _surface.pitch * _surface.h);
- setDirty();
-}
-
-void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y,
- GLuint w, GLuint h,
- const void *buf, int pitch) {
- _all_dirty = true;
-
- const byte * src = static_cast<const byte *>(buf);
- byte *dst = static_cast<byte *>(_surface.getBasePtr(x, y));
-
- do {
- memcpy(dst, src, w * bytesPerPixel());
- dst += _surface.pitch;
- src += pitch;
- } while (--h);
-}
-
-void GLESPaletteTexture::uploadTexture() const {
- const size_t texture_size =
- paletteSize() + _texture_width * _texture_height * bytesPerPixel();
-
- GLCALL(glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(),
- _texture_width, _texture_height,
- 0, texture_size, _texture));
-}
-
-void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
- if (_all_dirty) {
- GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- GL_NEAREST));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_NEAREST));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE));
- GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE));
- uploadTexture();
- _all_dirty = false;
- }
-
- GLESTexture::drawTexture(x, y, w, h);
-}
-
-#endif
-
diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h
deleted file mode 100644
index da42ea876d..0000000000
--- a/backends/platform/android/video.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#if defined(__ANDROID__)
-
-#include <GLES/gl.h>
-
-#include "graphics/surface.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-
-class GLESTexture {
-public:
- static void initGLExtensions();
-
- GLESTexture();
- virtual ~GLESTexture();
-
- virtual void reinitGL();
- virtual void allocBuffer(GLuint width, GLuint height);
-
- virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
- const void *buf, int pitch);
- virtual void fillBuffer(byte x);
-
- virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
- inline GLuint width() const {
- return _surface.w;
- }
-
- inline GLuint height() const {
- return _surface.h;
- }
-
- inline GLuint texture_name() const {
- return _texture_name;
- }
-
- inline const Graphics::Surface *surface_const() const {
- return &_surface;
- }
-
- inline Graphics::Surface *surface() {
- setDirty();
- return &_surface;
- }
-
- inline bool dirty() const {
- return _all_dirty || !_dirty_rect.isEmpty();
- }
-
- inline void drawTexture() {
- drawTexture(0, 0, _surface.w, _surface.h);
- }
-
-protected:
- virtual byte bytesPerPixel() const = 0;
- virtual GLenum glFormat() const = 0;
- virtual GLenum glType() const = 0;
-
- virtual size_t paletteSize() const {
- return 0;
- }
-
- inline void setDirty() {
- _all_dirty = true;
- _dirty_rect = Common::Rect();
- }
-
- inline void setDirtyRect(const Common::Rect& r) {
- if (!_all_dirty) {
- if (_dirty_rect.isEmpty())
- _dirty_rect = r;
- else
- _dirty_rect.extend(r);
- }
- }
-
- GLuint _texture_name;
- Graphics::Surface _surface;
- GLuint _texture_width;
- GLuint _texture_height;
- bool _all_dirty;
-
- // Covers dirty area
- Common::Rect _dirty_rect;
-};
-
-// RGBA4444 texture
-class GLES4444Texture : public GLESTexture {
-protected:
- virtual byte bytesPerPixel() const {
- return 2;
- }
-
- virtual GLenum glFormat() const {
- return GL_RGBA;
- }
-
- virtual GLenum glType() const {
- return GL_UNSIGNED_SHORT_4_4_4_4;
- }
-};
-
-// RGB565 texture
-class GLES565Texture : public GLESTexture {
-protected:
- virtual byte bytesPerPixel() const {
- return 2;
- }
-
- virtual GLenum glFormat() const {
- return GL_RGB;
- }
-
- virtual GLenum glType() const {
- return GL_UNSIGNED_SHORT_5_6_5;
- }
-};
-
-// RGB888 256-entry paletted texture
-class GLESPaletteTexture : public GLESTexture {
-public:
- GLESPaletteTexture();
- virtual ~GLESPaletteTexture();
-
- virtual void allocBuffer(GLuint width, GLuint height);
- virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
- const void *buf, int pitch);
- virtual void fillBuffer(byte x);
-
- virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
-
- inline void drawTexture() {
- drawTexture(0, 0, _surface.w, _surface.h);
- }
-
- inline const byte *palette_const() const {
- return _texture;
- };
-
- inline byte *palette() {
- setDirty();
- return _texture;
- };
-
-protected:
- virtual byte bytesPerPixel() const {
- return 1;
- }
-
- virtual GLenum glFormat() const {
- return GL_RGB;
- }
-
- virtual GLenum glType() const {
- return GL_PALETTE8_RGB8_OES;
- }
-
- virtual size_t paletteSize() const {
- return 256 * 3;
- }
-
- void uploadTexture() const;
-
- byte *_texture;
-};
-
-// RGBA8888 256-entry paletted texture
-class GLESPaletteATexture : public GLESPaletteTexture {
-protected:
- virtual GLenum glFormat() const {
- return GL_RGBA;
- }
-
- virtual GLenum glType() const {
- return GL_PALETTE8_RGBA8_OES;
- }
-
- virtual size_t paletteSize() const {
- return 256 * 4;
- }
-};
-
-#endif
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index dc91bd9fe7..bddb48ca95 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
@@ -464,6 +468,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 +477,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/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