aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/wince/wince-sdl.cpp
diff options
context:
space:
mode:
authorKostas Nakos2006-07-01 08:13:46 +0000
committerKostas Nakos2006-07-01 08:13:46 +0000
commit6a8749ace05649fdf69593c76a75c322f34a5bfa (patch)
treeda214254c9ca56ded22af377fe0763ad73dd7bb5 /backends/platform/wince/wince-sdl.cpp
parent294dcea3ef063ee4ec95f3f418af4534445da1c6 (diff)
downloadscummvm-rg350-6a8749ace05649fdf69593c76a75c322f34a5bfa.tar.gz
scummvm-rg350-6a8749ace05649fdf69593c76a75c322f34a5bfa.tar.bz2
scummvm-rg350-6a8749ace05649fdf69593c76a75c322f34a5bfa.zip
move ce port to its new home
svn-id: r23366
Diffstat (limited to 'backends/platform/wince/wince-sdl.cpp')
-rw-r--r--backends/platform/wince/wince-sdl.cpp2272
1 files changed, 2272 insertions, 0 deletions
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
new file mode 100644
index 0000000000..b1ad143679
--- /dev/null
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -0,0 +1,2272 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * 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/stdafx.h"
+#include "wince-sdl.h"
+
+#include "common/util.h"
+#include "base/engine.h"
+#include "base/main.h"
+#include "base/plugins.h"
+#include "common/timer.h"
+
+#include "common/config-manager.h"
+
+#include "scumm/scumm.h"
+
+#include "resource.h"
+
+#include "gui/Actions.h"
+#include "CEActionsPocket.h"
+#include "CEActionsSmartphone.h"
+#include "ItemAction.h"
+#include "gui/KeysDialog.h"
+
+#include "gui/message.h"
+
+#include "sound/fmopl.h"
+
+#include "ozone.h"
+#include "CEException.h"
+
+#ifdef USE_VORBIS
+#ifndef USE_TREMOR
+#include <vorbis/vorbisfile.h>
+#else
+#include <tremor/ivorbisfile.h>
+#endif
+#endif
+
+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"
+
+// Given to the true main, needed for backend adaptation
+
+static FILE *stdout_file;
+static FILE *stderr_file;
+
+// Static member inits
+
+bool OSystem_WINCE3::_soundMaster = true;
+OSystem::SoundProc OSystem_WINCE3::_originalSoundProc = NULL;
+
+bool _isSmartphone = false;
+bool _hasSmartphoneResolution = false;
+
+// Graphics mode consts
+
+// Low end devices 240x320
+
+static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = {
+ {"1x", "Normal (no scaling)", GFX_NORMAL},
+ {0, 0, 0}
+};
+
+// High end device 480x640
+
+static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = {
+ {"1x", "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}
+};
+
+
+// ********************************************************************************************
+
+bool isSmartphone() {
+ //return _isSmartphone;
+ return _hasSmartphoneResolution;
+}
+
+// ********************************************************************************************
+
+// MAIN
+
+int handleException(EXCEPTION_POINTERS *exceptionPointers) {
+ CEException::writeException(TEXT("\\scummvmCrash"), exceptionPointers);
+ drawError("Unrecoverable exception occurred - see crash dump in latest \\scummvmCrash file");
+ fclose(stdout_file);
+ fclose(stderr_file);
+ CEDevice::end();
+ SDL_Quit();
+ exit(0);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+OSystem *OSystem_WINCE3_create() {
+ return new OSystem_WINCE3();
+}
+
+int SDL_main(int argc, char **argv) {
+ CEDevice::init();
+ OSystem_WINCE3::initScreenInfos();
+ /* Sanity check */
+//#ifndef WIN32_PLATFORM_WFSP
+// if (CEDevice::hasSmartphoneResolution()) {
+// MessageBox(NULL, TEXT("This build was not compiled with Smartphone support"), TEXT("ScummVM error"), MB_OK | MB_ICONERROR);
+// return 0;
+// }
+//#endif
+ /* Avoid print problems - this file will be put in RAM anyway */
+ stdout_file = fopen("\\scummvm_stdout.txt", "w");
+ stderr_file = fopen("\\scummvm_stderr.txt", "w");
+
+ int res = 0;
+
+#ifndef DEBUG
+ __try {
+#endif
+ g_system = OSystem_WINCE3_create();
+ assert(g_system);
+
+ // Invoke the actual ScummVM main entry point:
+ res = scummvm_main(argc, argv);
+ g_system->quit(); // TODO: Consider removing / replacing this!
+#ifndef DEBUG
+ }
+ __except (handleException(GetExceptionInformation())) {
+ }
+#endif
+
+ return res;
+}
+
+// ********************************************************************************************
+
+
+// ********************************************************************************************
+
+void pumpMessages() {
+ MSG msg;
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+void drawError(char *error) {
+ TCHAR errorUnicode[200];
+ MultiByteToWideChar(CP_ACP, 0, error, strlen(error) + 1, errorUnicode, sizeof(errorUnicode));
+ pumpMessages();
+ MessageBox(GetActiveWindow(), errorUnicode, TEXT("ScummVM error"), MB_OK | MB_ICONERROR);
+ pumpMessages();
+}
+
+// ********************************************************************************************
+
+void OSystem_WINCE3::initBackend()
+{
+ // Initialize global key mapping
+ GUI::Actions::init();
+ GUI_Actions::Instance()->initInstanceMain(this);
+ GUI_Actions::Instance()->loadMapping();
+
+ loadDeviceConfiguration();
+}
+
+int OSystem_WINCE3::getScreenWidth() {
+ return _platformScreenWidth;
+}
+
+int OSystem_WINCE3::getScreenHeight() {
+ return _platformScreenHeight;
+}
+
+void OSystem_WINCE3::initScreenInfos() {
+ /*
+ // Check if we're running Ozone
+ int result;
+ RawFrameBufferInfo frameBufferInfo;
+ HDC hdc = GetDC(NULL);
+ result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&frameBufferInfo);
+ ReleaseDC(NULL, hdc);
+ _isOzone = (result > 0);
+ // And obtain the real screen size
+ _platformScreenWidth = (result > 0 ? frameBufferInfo.cxPixels : GetSystemMetrics(SM_CXSCREEN));
+ _platformScreenHeight = (result > 0 ? frameBufferInfo.cyPixels : GetSystemMetrics(SM_CYSCREEN));
+ */
+
+ // sdl port ensures that we use correctly full screen
+ _isOzone = 0;
+ _platformScreenWidth = GetSystemMetrics(SM_CXSCREEN);
+ _platformScreenHeight = GetSystemMetrics(SM_CYSCREEN);
+}
+
+bool OSystem_WINCE3::isOzone() {
+ return _isOzone;
+}
+
+// ********************************************************************************************
+
+
+OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(),
+ _orientationLandscape(0), _newOrientation(0), _panelInitialized(false),
+ _panelVisible(true), _panelStateForced(false), _forceHideMouse(false),
+ _freeLook(false), _forcePanelInvisible(false), _toolbarHighDrawn(false), _zoomUp(false), _zoomDown(false),
+ _scalersChanged(false), _monkeyKeyboard(false), _lastKeyPressed(0), _tapTime(0),
+ _saveToolbarState(false), _saveActiveToolbar(NAME_MAIN_PANEL), _rbutton(false),
+ _usesEmulatedMouse(false)
+{
+ _isSmartphone = CEDevice::isSmartphone();
+ _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone();
+ memset(&_mouseCurState, 0, sizeof(_mouseCurState));
+ if (_isSmartphone) {
+ _mouseCurState.x = 20;
+ _mouseCurState.y = 20;
+ }
+ if (_hasSmartphoneResolution) _panelVisible = false; // init correctly in smartphones
+ create_toolbar();
+
+
+ // Mouse backup (temporary code)
+ _mouseBackupOld = (byte*)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
+ _mouseBackupToolbar = (uint16*)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
+}
+
+void OSystem_WINCE3::swap_panel_visibility() {
+ //if (!_forcePanelInvisible && !_panelStateForced) {
+ 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);
+
+ if (_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 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 (_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);
+ 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();
+}
+
+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 = PocketPCHalf;
+ _zoomUp = false;
+ }
+ else
+ {
+ // only active if running on a PocketPC
+ if (_scalerProc != PocketPCHalf && _scalerProc != PocketPCHalfZoom)
+ return;
+ if (_scalerProc == PocketPCHalf) {
+ _saveToolbarZoom = _toolbarHandler.visible();
+ _toolbarHandler.setVisible(false);
+ // set zoom scaler
+ _scaleFactorYd = 1;
+ _scalerProc = PocketPCHalfZoom;
+ }
+ else
+ _zoomDown = false;
+
+ _zoomUp = true;
+ }
+ // redraw whole screen
+ addDirtyRect(0, 0, 640, 480);
+ internUpdateScreen();
+}
+
+void OSystem_WINCE3::swap_zoom_down() {
+ if (_zoomDown) {
+ // restore visibility
+ _toolbarHandler.setVisible(_saveToolbarZoom);
+ // restore scaler
+ _scaleFactorYd = 2;
+ _scalerProc = PocketPCHalf;
+ _zoomDown = false;
+ }
+ else
+ {
+ // only active if running on a PocketPC
+ if (_scalerProc != PocketPCHalf && _scalerProc != PocketPCHalfZoom)
+ return;
+ if (_scalerProc == PocketPCHalf) {
+ _saveToolbarZoom = _toolbarHandler.visible();
+ _toolbarHandler.setVisible(false);
+ // set zoom scaler
+ _scaleFactorYd = 1;
+ _scalerProc = PocketPCHalfZoom;
+ }
+ else
+ _zoomUp = false;
+
+ _zoomDown = true;
+ }
+ // redraw whole screen
+ addDirtyRect(0, 0, 640, 480);
+ internUpdateScreen();
+}
+
+//#ifdef WIN32_PLATFORM_WFSP
+// 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 > 240)
+ y = 240;
+
+ 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 > 320)
+ x = 320;
+
+ 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++;
+ if (_currentZone >= TOTAL_ZONES)
+ _currentZone = 0;
+
+ EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]);
+}
+//#endif
+
+
+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::private_sound_proc(void *param, byte *buf, int len) {
+ (*_originalSoundProc)(param, 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;
+
+ 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
+
+void OSystem_WINCE3::get_sample_rate() {
+ // 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" ||
+ strncmp(gameid.c_str(), "sword", 5) == 0 || strncmp(gameid.c_str(), "sky", 3) == 0)
+ _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
+}
+
+int OSystem_WINCE3::getOutputSampleRate() const {
+ return _sampleRate;
+}
+
+void OSystem_WINCE3::setWindowCaption(const char *caption) {
+ check_mappings(); // called here to initialize virtual keys handling
+ //update_game_settings();
+ get_sample_rate(); // called here to initialize mixer
+}
+
+bool OSystem_WINCE3::openCD(int drive) {
+ return false;
+}
+
+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 == kFeatureAutoComputeDirtyRects || 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;
+ default:
+ OSystem_SDL::setFeatureState(f, enable);
+ }
+}
+
+bool OSystem_WINCE3::getFeatureState(Feature f) {
+ switch(f) {
+ case kFeatureFullscreenMode:
+ return false;
+ case kFeatureVirtualKeyboard:
+ return (_panelStateForced);
+ }
+ return OSystem_SDL::getFeatureState(f);
+}
+
+bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {
+ SDL_AudioSpec desired;
+ int thread_priority;
+
+ memset(&desired, 0, sizeof(desired));
+
+ _originalSoundProc = proc;
+ desired.freq = _sampleRate;
+ desired.format = AUDIO_S16SYS;
+ desired.channels = 2;
+ //desired.samples = 2048;
+ desired.samples = 128;
+ desired.callback = private_sound_proc;
+ desired.userdata = param;
+
+ // Add sound thread priority
+ if (!ConfMan.hasKey("sound_thread_priority")) {
+#ifdef SH3
+ thread_priority = THREAD_PRIORITY_NORMAL;
+#else
+ thread_priority = THREAD_PRIORITY_ABOVE_NORMAL;
+#endif
+ }
+ else
+ thread_priority = ConfMan.getInt("sound_thread_priority");
+
+ desired.thread_priority = thread_priority;
+
+ if (SDL_OpenAudio(&desired, NULL) != 0) {
+ return false;
+ }
+ SDL_PauseAudio(0);
+ return true;
+}
+
+void OSystem_WINCE3::check_mappings() {
+ CEActionsPocket *instance;
+
+ Common::String gameid(ConfMan.get("gameid"));
+
+ if (gameid.empty() || GUI_Actions::Instance()->initialized())
+ return;
+
+ GUI_Actions::Instance()->initInstanceGame();
+ 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()) {
+ GUI::KeysDialog *keysDialog = new GUI::KeysDialog("Map right click action");
+ while (!instance->getMapping(POCKET_ACTION_RIGHTCLICK)) {
+ keysDialog->runModal();
+ if (!instance->getMapping(POCKET_ACTION_RIGHTCLICK)) {
+ GUI::MessageDialog alert("You must map a key to the 'Right Click' action to play this game");
+ alert.runModal();
+ }
+ }
+ delete keysDialog;
+ }
+
+ // Map the "hide toolbar" action if needed
+ if (instance->needsHideToolbarMapping()) {
+ GUI::KeysDialog *keysDialog = new GUI::KeysDialog("Map hide toolbar action");
+ while (!instance->getMapping(POCKET_ACTION_HIDE)) {
+ keysDialog->runModal();
+ if (!instance->getMapping(POCKET_ACTION_HIDE)) {
+ GUI::MessageDialog alert("You must map a key to the 'Hide toolbar' action to play this game");
+ alert.runModal();
+ }
+ }
+ delete keysDialog;
+ }
+
+ // Map the "zoom" actions if needed
+ if (instance->needsZoomMapping()) {
+ GUI::KeysDialog *keysDialog = new GUI::KeysDialog("Map Zoom Up action (optional)");
+ keysDialog->runModal();
+ delete keysDialog;
+ keysDialog = new GUI::KeysDialog("Map Zoom Down action (optional)");
+ keysDialog->runModal();
+ delete keysDialog;
+ }
+
+ // Extra warning for Zak Mc Kracken
+ if (strncmp(gameid.c_str(), "zak", 3) == 0 &&
+ !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 (_screenWidth <= 320 && (isOzone() || !CEDevice::hasDesktopResolution())) {
+ if (ConfMan.hasKey("landscape"))
+ if (ConfMan.get("landscape")[0] > 57) {
+ _newOrientation = _orientationLandscape = ConfMan.getBool("landscape");
+ //ConfMan.removeKey("landscape", String::emptyString);
+ 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);
+
+ // Keyboard is active for Monkey 1 or 2 initial copy-protection
+ if (strncmp(gameid.c_str(), "monkey", 6) == 0) {
+ _monkeyKeyboard = true;
+ _toolbarHandler.setActive(NAME_PANEL_KEYBOARD);
+ }
+
+ if (_mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) {
+ setGraphicsMode(GFX_NORMAL);
+ hotswapGFXMode();
+ }
+
+ if (_hasSmartphoneResolution)
+ panel->setVisible(false);
+
+ _saveToolbarState = true;
+
+ // Set Smush Force Redraw rate for Full Throttle
+ if (!ConfMan.hasKey("Smush_force_redraw")) {
+ ConfMan.setInt("Smush_force_redraw", 30);
+ ConfMan.flushToDisk();
+ }
+ }
+
+ get_sample_rate();
+}
+
+void OSystem_WINCE3::initSize(uint w, uint h) {
+
+ if (_hasSmartphoneResolution && h == 240)
+ h = 200; // mainly for the launcher
+
+ if (_isSmartphone && !ConfMan.hasKey("landscape"))
+ {
+ ConfMan.setInt("landscape", 1);
+ ConfMan.flushToDisk();
+ }
+
+ switch (_transactionMode) {
+ case kTransactionActive:
+ _transactionDetails.w = w;
+ _transactionDetails.h = h;
+ _transactionDetails.sizeChanged = true;
+ _transactionDetails.needUnload = true;
+ return;
+ case kTransactionCommit:
+ break;
+ default:
+ break;
+ }
+
+ if (w == 320 && h == 200 && !_hasSmartphoneResolution)
+ h = 240; // use the extra 40 pixels height for the toolbar
+
+ 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) _screenWidth || h != (uint) _screenHeight)
+ _scalersChanged = false;
+
+ _overlayWidth = w;
+ _overlayHeight = h;
+
+ OSystem_SDL::initSize(w, h);
+
+ if (_scalersChanged) {
+ unloadGFXMode();
+ loadGFXMode();
+ _scalersChanged = false;
+ }
+
+ update_game_settings();
+}
+
+
+int OSystem_WINCE3::getDefaultGraphicsMode() const {
+ return GFX_NORMAL;
+}
+
+bool OSystem_WINCE3::update_scalers() {
+
+ if (_mode != GFX_NORMAL)
+ return false;
+
+ if (CEDevice::hasPocketPCResolution()) {
+ if (!_orientationLandscape && (_screenWidth == 320 || !_screenWidth)) {
+ _scaleFactorXm = 3;
+ _scaleFactorXd = 4;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = PocketPCPortrait;
+ _modeFlags = 0;
+ }
+ if ( _orientationLandscape && (_screenWidth == 320 || !_screenWidth)) {
+ if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 6;
+ _scaleFactorYd = 5;
+ _scalerProc = PocketPCLandscapeAspect;
+ _modeFlags = 0;
+ } else {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ _modeFlags = 0;
+ }
+ }
+ if (_screenWidth == 640 && !(isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 2;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 2;
+ _scalerProc = PocketPCHalf;
+ _modeFlags = 0;
+ }
+ if (_screenWidth == 640 && (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
+ _scaleFactorXm = 1;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = 1;
+ _scaleFactorYd = 1;
+ _scalerProc = Normal1x;
+ _modeFlags = 0;
+ }
+
+ return true;
+ }
+
+//#ifdef WIN32_PLATFORM_WFSP
+ if (CEDevice::hasSmartphoneResolution()) {
+ if (_screenWidth > 320)
+ error("Game resolution not supported on Smartphone");
+ _scaleFactorXm = 2;
+ _scaleFactorXd = 3;
+ _scaleFactorYm = 7;
+ _scaleFactorYd = 8;
+ _scalerProc = SmartphoneLandscape;
+ _modeFlags = 0;
+ initZones();
+ return true;
+ }
+//#endif
+
+ return false;
+}
+
+bool OSystem_WINCE3::setGraphicsMode(int mode) {
+
+ switch (_transactionMode) {
+ case kTransactionActive:
+ _transactionDetails.mode = mode;
+ _transactionDetails.modeChanged = true;
+ return true;
+ case kTransactionCommit:
+ break;
+ default:
+ break;
+ }
+
+ 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.removeKey("landscape", String::emptyString);
+ ConfMan.setInt("landscape", _orientationLandscape);
+ } else
+ _newOrientation = _orientationLandscape = ConfMan.getInt("landscape");
+ else
+ _newOrientation = _orientationLandscape = 0;
+
+ update_scalers();
+
+ // FIXME
+ if (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640) && mode)
+ _scaleFactorXm = -1;
+
+ if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape)
+ _mode = GFX_NORMAL;
+ else
+ _mode = mode;
+
+ if (_scaleFactorXm < 0) {
+ /* Standard scalers, from the SDL backend */
+ switch(_mode) {
+ case GFX_NORMAL:
+ _scaleFactor = 1;
+ _scalerProc = Normal1x;
+ break;
+ case GFX_DOUBLESIZE:
+ _scaleFactor = 2;
+ _scalerProc = Normal2x;
+ break;
+ case GFX_TRIPLESIZE:
+ _scaleFactor = 3;
+ _scalerProc = Normal3x;
+ break;
+ case GFX_2XSAI:
+ _scaleFactor = 2;
+ _scalerProc = _2xSaI;
+ break;
+ case GFX_SUPER2XSAI:
+ _scaleFactor = 2;
+ _scalerProc = Super2xSaI;
+ break;
+ case GFX_SUPEREAGLE:
+ _scaleFactor = 2;
+ _scalerProc = SuperEagle;
+ break;
+ case GFX_ADVMAME2X:
+ _scaleFactor = 2;
+ _scalerProc = AdvMame2x;
+ break;
+ case GFX_ADVMAME3X:
+ _scaleFactor = 3;
+ _scalerProc = AdvMame3x;
+ break;
+ case GFX_HQ2X:
+ _scaleFactor = 2;
+ _scalerProc = HQ2x;
+ break;
+ case GFX_HQ3X:
+ _scaleFactor = 3;
+ _scalerProc = HQ3x;
+ break;
+ case GFX_TV2X:
+ _scaleFactor = 2;
+ _scalerProc = TV2x;
+ break;
+ case GFX_DOTMATRIX:
+ _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 (_scaleFactor && ((_scaleFactor * _screenWidth > getScreenWidth() &&
+ _scaleFactor * _screenWidth > getScreenHeight())
+ || (_scaleFactor * _screenHeight > getScreenWidth() &&
+ _scaleFactor * _screenHeight > getScreenHeight()))) {
+ _scaleFactor = 1;
+ _scalerProc = Normal1x;
+ }
+
+ // Common scaler system was used
+ if (_scaleFactorXm < 0) {
+ _scaleFactorXm = _scaleFactor;
+ _scaleFactorXd = 1;
+ _scaleFactorYm = _scaleFactor;
+ _scaleFactorYd = 1;
+ }
+
+ _forceFull = true;
+
+ if (oldScaleFactorXm != _scaleFactorXm ||
+ oldScaleFactorXd != _scaleFactorXd ||
+ oldScaleFactorYm != _scaleFactorYm ||
+ oldScaleFactorYd != _scaleFactorYd) {
+ _scalersChanged = true;
+ }
+ else
+ _scalersChanged = false;
+
+
+ return true;
+
+}
+
+void OSystem_WINCE3::loadGFXMode() {
+ int displayWidth;
+ int displayHeight;
+ unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE;
+
+ _fullscreen = true; // forced
+ _forceFull = true;
+ _modeFlags |= DF_UPDATE_EXPAND_1_PIXEL;
+
+ _tmpscreen = NULL;
+
+ // Recompute scalers if necessary
+ update_scalers();
+
+ //
+ // Create the surface that contains the 8 bit game data
+ _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth, _screenHeight, 8, 0, 0, 0, 0);
+ if (_screen == NULL)
+ error("_screen failed");
+
+ //
+ // Create the surface that contains the scaled graphics in 16 bit mode
+ //
+
+ // Always use full screen mode to have a "clean screen"
+ displayWidth = _screenWidth * _scaleFactorXm / _scaleFactorXd;
+ displayHeight = _screenHeight * _scaleFactorYm / _scaleFactorYd;
+
+ // FIXME
+ if (displayWidth <= GetSystemMetrics(SM_CXSCREEN)) { // no rotation
+ displayWidth = GetSystemMetrics(SM_CXSCREEN);
+ displayHeight = GetSystemMetrics(SM_CYSCREEN);
+ } else if (displayHeight > GetSystemMetrics(SM_CXSCREEN)) // rotating, clip height
+ displayHeight = GetSystemMetrics(SM_CXSCREEN);
+
+ if (_orientationLandscape == 2) flags |= SDL_FLIPVIDEO;
+ _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags);
+
+ if (_hwscreen == NULL) {
+ // DON'T use error(), as this tries to bring up the debug
+ // console, which WON'T WORK now that _hwscreen is hosed.
+
+ // FIXME: We should be able to continue the game without
+ // shutting down or bringing up the debug console, but at
+ // this point we've already screwed up all our member vars.
+ // We need to find a way to call SDL_VideoModeOK *before*
+ // that happens and revert to all the old settings if we
+ // can't pull off the switch to the new settings.
+ //
+ // Fingolfin says: the "easy" way to do that is not to modify
+ // the member vars before we are sure everything is fine. Think
+ // of "transactions, commit, rollback" style... we use local vars
+ // in place of the member vars, do everything etc. etc.. In case
+ // of a failure, rollback is trivial. Only if everything worked fine
+ // do we "commit" the changed values to the member vars.
+ warning("SDL_SetVideoMode says we can't switch to that mode");
+ quit();
+ }
+
+ //
+ // 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);
+ initCEScaler();
+
+ // Need some extra bytes around when using 2xSaI
+ _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ _screenWidth + 3,
+ _screenHeight + 3,
+ 16,
+ _hwscreen->format->Rmask,
+ _hwscreen->format->Gmask,
+ _hwscreen->format->Bmask,
+ _hwscreen->format->Amask);
+
+ if (_tmpscreen == NULL)
+ error("_tmpscreen failed");
+
+
+
+ // Overlay
+ if (CEDevice::hasDesktopResolution()) {
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth * _scaleFactorXm / _scaleFactorXd, _overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0);
+ if (_overlayscreen == NULL)
+ error("_overlayscreen failed");
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0);
+ if (_tmpscreen2 == NULL)
+ error("_tmpscreen2 failed");
+ } else {
+ _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight, 16, 0, 0, 0, 0);
+ if (_overlayscreen == NULL)
+ error("_overlayscreen failed");
+ _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth + 3, _overlayHeight + 3, 16, 0, 0, 0, 0);
+ if (_tmpscreen2 == NULL)
+ error("_tmpscreen2 failed");
+ }
+
+ // Toolbar
+ uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16));
+ _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");
+
+ if (_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");
+ }
+ else
+ _toolbarHigh = NULL;
+
+
+ // keyboard cursor control, some other better place for it?
+ _km.x_max = _screenWidth * _scaleFactorXm / _scaleFactorXd - 1;
+ _km.y_max = _screenHeight * _scaleFactorXm / _scaleFactorXd - 1;
+ _km.delay_time = 25;
+ _km.last_time = 0;
+}
+
+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;
+ }
+}
+
+void OSystem_WINCE3::hotswapGFXMode() {
+ if (!_screen)
+ return;
+
+ // 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
+ loadGFXMode();
+
+ // 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 to the screen
+ internUpdateScreen();
+
+ // Make sure that an EVENT_SCREEN_CHANGED gets sent later
+ _modeChanged = true;
+}
+
+void OSystem_WINCE3::update_keyboard() {
+ // Update the forced keyboard for Monkey Island copy protection
+ if (_monkeyKeyboard && !_isSmartphone)
+ if (!_panelVisible || _toolbarHandler.activeName() != NAME_PANEL_KEYBOARD)
+ swap_panel();
+ if (_monkeyKeyboard && Scumm::g_scumm->VAR_ROOM != 0xff && Scumm::g_scumm && Scumm::g_scumm->VAR(Scumm::g_scumm->VAR_ROOM) != 108 &&
+ Scumm::g_scumm->VAR(Scumm::g_scumm->VAR_ROOM) != 90) {
+ // Switch back to the normal panel now that the keyboard is not used anymore
+ _monkeyKeyboard = false;
+ _toolbarHandler.setActive(NAME_MAIN_PANEL);
+ }
+}
+
+void OSystem_WINCE3::internUpdateScreen() {
+ SDL_Surface *srcSurf, *origSurf;
+ static bool old_overlayVisible = false;
+ assert(_hwscreen != NULL);
+
+ update_keyboard();
+
+ // If the shake position changed, fill the dirty area with blackness
+ if (_currentShakePos != _newShakePos) {
+ SDL_Rect blackrect = {0, 0, _screenWidth * _scaleFactorXm / _scaleFactorXd, _newShakePos * _scaleFactorYm / _scaleFactorYd};
+
+ if (_adjustAspectRatio)
+ 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 = _screenHeight / 2;
+ _dirtyRectList[0].w = _screenWidth;
+ if (!_zoomUp && !_zoomDown)
+ _dirtyRectList[0].h = _screenHeight;
+ else
+ _dirtyRectList[0].h = _screenHeight / 2;
+
+ _toolbarHandler.forceRedraw();
+ }
+ //else
+ // undrawMouse();
+
+ // Only draw anything if necessary
+ if (_numDirtyRects > 0) {
+
+ SDL_Rect *r;
+ SDL_Rect dst;
+ uint32 srcPitch, dstPitch;
+ SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects;
+ bool toolbarVisible = _toolbarHandler.visible();
+ int toolbarOffset = _toolbarHandler.getOffset();
+
+ if (_scalerProc == Normal1x && !_adjustAspectRatio && 0) {
+ for (r = _dirtyRectList; r != last_rect; ++r) {
+ dst = *r;
+
+ // Check if the toolbar is overwritten
+ if (!_forceFull && toolbarVisible && r->y + r->h >= toolbarOffset) {
+ _toolbarHandler.forceRedraw();
+ }
+
+ if (_overlayVisible) {
+ // FIXME: I don't understand why this is necessary...
+ dst.x--;
+ dst.y--;
+ }
+ dst.y += _currentShakePos;
+ if (SDL_BlitSurface(origSurf, r, _hwscreen, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+ } else {
+ for (r = _dirtyRectList; r != last_rect; ++r) {
+ dst = *r;
+ dst.x++; // Shift rect by one since 2xSai needs to acces the data around
+ dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
+ 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; r != last_rect; ++r) {
+ register int dst_y = r->y + _currentShakePos;
+ register int dst_h = 0;
+ register int orig_dst_y = 0;
+
+ // Check if the toolbar is overwritten
+ if (!_forceFull && toolbarVisible && r->y + r->h >= toolbarOffset) {
+ _toolbarHandler.forceRedraw();
+ }
+
+ if (dst_y < _screenHeight) {
+ dst_h = r->h;
+ if (dst_h > _screenHeight - dst_y)
+ dst_h = _screenHeight - dst_y;
+
+ dst_y *= _scaleFactorYm;
+ dst_y /= _scaleFactorYd;
+
+ if (_adjustAspectRatio) {
+ orig_dst_y = dst_y;
+ dst_y = real2Aspect(dst_y);
+ }
+
+ // clip inside platform screen (landscape,bottom only)
+ if (_orientationLandscape && !_zoomDown && dst_y+dst_h > _screenHeight)
+ dst_h = _screenHeight - dst_y;
+
+ if (!_zoomDown)
+ _scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
+ (byte *)_hwscreen->pixels + (r->x * 2 * _scaleFactorXm / _scaleFactorXd) + dst_y * dstPitch, dstPitch, r->w, dst_h);
+ else {
+ _scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
+ (byte *)_hwscreen->pixels + (r->x * 2 * _scaleFactorXm / _scaleFactorXd) + (dst_y - 240) * dstPitch, dstPitch, r->w, dst_h);
+ }
+
+ }
+
+ r->x = r->x * _scaleFactorXm / _scaleFactorXd;
+ if (!_zoomDown)
+ r->y = dst_y;
+ else
+ r->y = dst_y - 240;
+ r->w = r->w * _scaleFactorXm / _scaleFactorXd;
+ r->h = dst_h * _scaleFactorYm / _scaleFactorYd;
+
+ /*if (_adjustAspectRatio && orig_dst_y / _scaleFactor < _screenHeight)
+ r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y);
+ */
+ }
+ SDL_UnlockSurface(srcSurf);
+ SDL_UnlockSurface(_hwscreen);
+ }
+
+ // Readjust the dirty rect list in case we are doing a full update.
+ // This is necessary if shaking is active.
+ if (_forceFull) {
+ _dirtyRectList[0].y = 0;
+ _dirtyRectList[0].h = (_adjustAspectRatio ? 240 : (_zoomUp || _zoomDown ? _screenHeight / 2 : _screenHeight)) * _scaleFactorYm / _scaleFactorYd;
+ if (_orientationLandscape)
+ {
+ if (_dirtyRectList[0].h > _platformScreenWidth)
+ _dirtyRectList[0].h = _platformScreenWidth; // clip
+ } else {
+ if (_dirtyRectList[0].h > _platformScreenHeight)
+ _dirtyRectList[0].h = _platformScreenHeight; // clip
+ }
+ }
+ }
+ // 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;
+
+ if (_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;
+ }
+ else
+ _toolbarHighDrawn = false;
+ 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;
+ _scalerProc((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
+ }
+
+
+ //drawMouse();
+
+ // Finally, blit all our changes to the screen
+ if (_numDirtyRects > 0)
+ SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+
+ _numDirtyRects = 0;
+ _forceFull = false;
+}
+
+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;
+}
+
+// FIXME
+// Reuse static or proper mapping
+
+static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode)
+{
+ if (GUI::Actions::Instance()->mappingActive())
+ return key;
+
+ if (key >= SDLK_F1 && key <= SDLK_F9) {
+ return key - SDLK_F1 + 315;
+ } else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
+ return key - SDLK_KP0 + '0';
+ } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
+ return key;
+ } else if (unicode) {
+ return unicode;
+ } else if (key >= 'a' && key <= 'z' && mod & KMOD_SHIFT) {
+ return key & ~0x20;
+ } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
+ return 0;
+ }
+ return key;
+}
+
+void OSystem_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;
+ }
+
+ if (w > _overlayWidth - x) {
+ w = _overlayWidth - x;
+ }
+
+ if (h > _overlayHeight - y) {
+ h = _overlayHeight - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Mark the modified region as dirty
+ _cksumValid = false;
+ 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
+
+ if (((long)src & 3) == 0 && pitch == _screenWidth && x == 0 && y == 0 &&
+ w == _screenWidth && h == _screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
+ /* Special, optimized case for full screen updates.
+ * It tries to determine what areas were actually changed,
+ * and just updates those, on the actual display. */
+ addDirtyRgnAuto(src);
+ } else {
+ /* Clip the coordinates */
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ src -= y * pitch;
+ y = 0;
+ }
+
+ if (w > _screenWidth - x) {
+ w = _screenWidth - x;
+ }
+
+ if (h > _screenHeight - y) {
+ h = _screenHeight - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ _cksumValid = false;
+ 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 * _screenWidth + x;
+
+ if (_screenWidth == pitch && pitch == w) {
+ memcpy(dst, src, h*w);
+ } else {
+ do {
+ memcpy(dst, src, w);
+ src += pitch;
+ dst += _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, byte keycolor, int cursorTargetScale) {
+
+ undrawMouse();
+ if (w == 0 || h == 0)
+ return;
+
+ assert(w <= MAX_MOUSE_W);
+ assert(h <= MAX_MOUSE_H);
+ _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);
+}
+
+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 (_mouseDrawn || !_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
+
+ // 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 > _screenWidth - x)
+ w = _screenWidth - x;
+ if (h > _screenHeight - y)
+ h = _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 * _screenWidth + x;
+ while (h > 0) {
+ int 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 += MAX_MOUSE_W - w;
+ dst += _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) {
+ int width = w;
+ while (width > 0) {
+ *bak++ = *(uint16 *)dst;
+ color = *src++;
+ if (color != 0xFF) // 0xFF = transparent, don't draw
+ *(uint16 *)dst = RGBToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
+ dst += 2;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += MAX_MOUSE_W - w;
+ dst += _overlayscreen->pitch - w * 2;
+ h--;
+ }
+ }
+
+ SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
+
+ // Finally, set the flag to indicate the mouse has been drawn
+ _mouseDrawn = true;
+}
+
+void OSystem_WINCE3::undrawMouse() {
+ assert (_transactionMode == kTransactionNone || _transactionMode == kTransactionCommit);
+
+ if (!_mouseDrawn)
+ return;
+ _mouseDrawn = false;
+
+ 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 addjust 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 > _screenWidth - old_mouse_x)
+ old_mouse_w = _screenWidth - old_mouse_x;
+ if (old_mouse_h > _screenHeight - old_mouse_y)
+ old_mouse_h = _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 x, 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 * _screenWidth + old_mouse_x;
+ for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _screenWidth) {
+ for (x = 0; x < old_mouse_w; ++x) {
+ dst[x] = bak[x];
+ }
+ }
+
+ } 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 += MAX_MOUSE_W, dst += _overlayscreen->pitch) {
+ for (x = 0; x < old_mouse_w; ++x) {
+ *((uint16 *)dst + x) = bak[x];
+ }
+ }
+ }
+
+ addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
+
+ SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen);
+}
+
+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;
+
+ // 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) {
+ int width = w;
+ while (width > 0) {
+ *bak++ = *dst;
+ color = *src++;
+ if (color != _mouseKeyColor) // transparent color
+ *dst = 0xFFFF;
+ dst++;
+ width--;
+ }
+ src += _mouseCurState.w - w;
+ bak += MAX_MOUSE_W - w;
+ dst += surf->w - w;
+ h--;
+ }
+ } else { // restore bg
+ for (int y = 0; y < h; ++y, bak += MAX_MOUSE_W, dst += surf->w)
+ for (int x = 0; x < w; ++x)
+ dst[x] = bak[x];
+ }
+
+ SDL_UnlockSurface(surf);
+}
+
+void OSystem_WINCE3::blitCursor() {
+}
+
+void OSystem_WINCE3::showOverlay() {
+ assert (_transactionMode == kTransactionNone);
+
+ undrawMouse();
+
+ _overlayVisible = true;
+ clearOverlay();
+}
+
+void OSystem_WINCE3::hideOverlay() {
+ assert (_transactionMode == kTransactionNone);
+
+ undrawMouse();
+
+ _overlayVisible = false;
+ clearOverlay();
+ _forceFull = true;
+}
+
+void OSystem_WINCE3::drawMouse() {
+ // FIXME
+ if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset()) && !_forceHideMouse)
+ internDrawMouse();
+}
+
+void OSystem_WINCE3::fillMouseEvent(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) {
+
+ // Align on boundaries
+ if (_scaleFactorXd > 1) {
+ while (x % _scaleFactorXd) {
+ x--;
+ w++;
+ }
+ while (w % _scaleFactorXd) w++;
+ }
+
+ if (_scaleFactorYd > 1) {
+ while (y % _scaleFactorYd) {
+ y--;
+ h++;
+ }
+ while (h % _scaleFactorYd) h++;
+ }
+
+ if (_scalerProc == PocketPCHalfZoom) {
+ // Restrict rect if we're zooming
+ if (_zoomUp) {
+ if (y + h >= 240) {
+ if (y >= 240)
+ return;
+ else
+ h = 240 - y;
+ }
+ }
+ else
+ if (_zoomDown) {
+ if (y + h >= 240) {
+ if (y < 240) {
+ h = 240 - y;
+ y = 240;
+ }
+ }
+ else
+ return;
+ }
+ }
+
+ OSystem_SDL::addDirtyRect(x, y, w, h, false);
+}
+
+// FIXME
+// See if some SDL mapping can be useful for HPCs
+
+bool OSystem_WINCE3::pollEvent(Event &event) {
+ SDL_Event ev;
+ byte b = 0;
+ Event temp_event;
+ DWORD currentTime;
+ bool keyEvent = false;
+
+ memset(&temp_event, 0, sizeof(Event));
+ memset(&event, 0, sizeof(Event));
+
+ handleKbdMouse();
+
+ // If the screen mode changed, send an EVENT_SCREEN_CHANGED
+ if (_modeChanged) {
+ _modeChanged = false;
+ event.type = EVENT_SCREEN_CHANGED;
+ return true;
+ }
+
+ CEDevice::wakeUp();
+
+ //if (_isSmartphone)
+ currentTime = GetTickCount();
+
+ while(SDL_PollEvent(&ev)) {
+ switch(ev.type) {
+ case SDL_KEYDOWN:
+ // KMOD_RESERVED is used if the key has been injected by an external buffer
+ if (ev.key.keysym.mod != KMOD_RESERVED) {
+ //if (_isSmartphone) {
+ 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;
+ }
+
+ event.type = EVENT_KEYDOWN;
+ event.kbd.keycode = ev.key.keysym.sym;
+ event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
+
+ if (GUI_Actions::Instance()->mappingActive())
+ event.kbd.flags = 0xFF;
+
+ return true;
+
+ case SDL_KEYUP:
+ // KMOD_RESERVED is used if the key has been injected by an external buffer
+ if (ev.key.keysym.mod != KMOD_RESERVED) {
+ //if (_isSmartphone) {
+ keyEvent = true;
+ _lastKeyPressed = 0;
+ //}
+
+ if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false))
+ return true;
+ }
+
+ event.type = EVENT_KEYUP;
+ event.kbd.keycode = ev.key.keysym.sym;
+ event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
+
+ if (GUI_Actions::Instance()->mappingActive())
+ event.kbd.flags = 0xFF;
+
+ return true;
+
+ case SDL_MOUSEMOTION:
+ event.type = 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)
+ temp_event.type = EVENT_LBUTTONDOWN;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ temp_event.type = EVENT_RBUTTONDOWN;
+ else
+ break;
+
+ fillMouseEvent(temp_event, ev.button.x, ev.button.y);
+
+ if (!_isSmartphone) {
+ // Already tap initiated ?
+ if (_tapTime) {
+ int deltaX;
+ int deltaY;
+ if (temp_event.mouse.x > _tapX)
+ deltaX = temp_event.mouse.x - _tapX;
+ else
+ deltaX = _tapX - temp_event.mouse.x;
+ if (temp_event.mouse.y > _tapY)
+ deltaY = temp_event.mouse.y - _tapY;
+ else
+ deltaY = _tapY - temp_event.mouse.y;
+ if (deltaX <= 5 && deltaY <= 5 && (GetTickCount() - _tapTime < 1000)) {
+ if (temp_event.mouse.y <= 20 && _panelInitialized) { // panel double tap?
+ swap_panel_visibility();
+ } else { // simulate right click
+ temp_event.type = EVENT_RBUTTONDOWN;
+ _rbutton = true;
+ }
+ }
+ _tapTime = 0;
+ } else {
+ _tapTime = GetTickCount();
+ _tapX = temp_event.mouse.x;
+ _tapY = temp_event.mouse.y;
+ }
+ }
+
+ if (_toolbarHandler.action(temp_event.mouse.x, temp_event.mouse.y, true)) {
+ if (!_toolbarHandler.drawn())
+ internUpdateScreen();
+ if (_newOrientation != _orientationLandscape && _mode == GFX_NORMAL) {
+ _orientationLandscape = _newOrientation;
+ ConfMan.setInt("landscape", _orientationLandscape);
+ ConfMan.flushToDisk();
+ setGraphicsMode(GFX_NORMAL);
+ hotswapGFXMode();
+ }
+ }
+ else {
+ if (!_freeLook)
+ memcpy(&event, &temp_event, sizeof(Event));
+ }
+
+ return true;
+
+ case SDL_MOUSEBUTTONUP:
+ if (ev.button.button == SDL_BUTTON_LEFT)
+ temp_event.type = EVENT_LBUTTONUP;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ temp_event.type = EVENT_RBUTTONUP;
+ else
+ break;
+
+ if (_rbutton) {
+ temp_event.type = EVENT_RBUTTONUP;
+ _rbutton = false;
+ }
+
+ fillMouseEvent(temp_event, ev.button.x, ev.button.y);
+
+ if (_toolbarHandler.action(temp_event.mouse.x, temp_event.mouse.y, false)) {
+ if (!_toolbarHandler.drawn())
+ internUpdateScreen();
+ }
+ else {
+ if (!_freeLook)
+ memcpy(&event, &temp_event, sizeof(Event));
+ }
+
+ return true;
+
+ case SDL_VIDEOEXPOSE:
+ _forceFull = true;
+ break;
+
+ case SDL_QUIT:
+ event.type = EVENT_QUIT;
+ return true;
+ }
+ }
+
+ // Simulate repeated key for Smartphones
+
+ if (!keyEvent) {
+ //if (_isSmartphone) {
+ if (_lastKeyPressed) {
+ if (currentTime > _keyRepeatTime + _keyRepeatTrigger) {
+ _keyRepeatTime = currentTime;
+ _keyRepeat++;
+ GUI_Actions::Instance()->performMapped(_lastKeyPressed, true);
+ }
+ }
+ //}
+ }
+
+ return false;
+}
+
+void OSystem_WINCE3::quit() {
+ fclose(stdout_file);
+ fclose(stderr_file);
+ if (gDebugLevel <= 0) {
+ DeleteFile(TEXT("\\scummvm_stdout.txt"));
+ DeleteFile(TEXT("\\scummvm_stderr.txt"));
+ }
+ CEDevice::end();
+ OSystem_SDL::quit();
+}
+
+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 }
+};