diff options
author | Kostas Nakos | 2006-07-01 08:13:46 +0000 |
---|---|---|
committer | Kostas Nakos | 2006-07-01 08:13:46 +0000 |
commit | 6a8749ace05649fdf69593c76a75c322f34a5bfa (patch) | |
tree | da214254c9ca56ded22af377fe0763ad73dd7bb5 /backends/platform/wince/wince-sdl.cpp | |
parent | 294dcea3ef063ee4ec95f3f418af4534445da1c6 (diff) | |
download | scummvm-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.cpp | 2272 |
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 } +}; |