diff options
Diffstat (limited to 'backends')
285 files changed, 11531 insertions, 7597 deletions
diff --git a/backends/audiocd/sdl/sdl-audiocd.cpp b/backends/audiocd/sdl/sdl-audiocd.cpp index 4136c34403..82c9549a57 100644 --- a/backends/audiocd/sdl/sdl-audiocd.cpp +++ b/backends/audiocd/sdl/sdl-audiocd.cpp @@ -27,6 +27,7 @@ #if defined(SDL_BACKEND) +#include "common/textconsole.h" #include "backends/audiocd/sdl/sdl-audiocd.h" SdlAudioCDManager::SdlAudioCDManager() diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp index 42ab7b887a..f349cc8005 100644 --- a/backends/base-backend.cpp +++ b/backends/base-backend.cpp @@ -101,7 +101,4 @@ AudioCDManager *BaseBackend::getAudioCDManager() { } void BaseBackend::resetGraphicsScale() { - // As a hack, we use 0 here. Backends should override this method - // and provide their own. - setGraphicsMode(0); } diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h index 06db1dc027..73dc60695b 100644 --- a/backends/events/default/default-events.h +++ b/backends/events/default/default-events.h @@ -31,10 +31,10 @@ namespace Common { #ifdef ENABLE_KEYMAPPER - class Keymapper; +class Keymapper; #endif #ifdef ENABLE_VKEYBD - class VirtualKeyboard; +class VirtualKeyboard; #endif } diff --git a/backends/events/gp2xsdl/gp2xsdl-events.cpp b/backends/events/gp2xsdl/gp2xsdl-events.cpp index 184f1d9b64..86d4de384f 100644 --- a/backends/events/gp2xsdl/gp2xsdl-events.cpp +++ b/backends/events/gp2xsdl/gp2xsdl-events.cpp @@ -18,22 +18,15 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "common/scummsys.h" -#if defined(GP2X) || defined(GP2XWIZ) +#if defined(GP2X_OLD) #include "backends/events/gp2xsdl/gp2xsdl-events.h" -#if defined(GP2X) #include "backends/platform/gp2x/gp2x-hw.h" #include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" -#else -#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" -#endif #include "backends/platform/sdl/sdl.h" @@ -88,7 +81,6 @@ enum { GP2XSdlEventSource::GP2XSdlEventSource() : _buttonStateL(false){ - } void GP2XSdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { @@ -441,7 +433,7 @@ bool GP2XSdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event _km.x_down_count = 0; } #endif - + } else if (ev.jaxis.axis == JOY_YAXIS) { #ifndef JOY_INVERT_Y axis = -axis; @@ -468,5 +460,4 @@ bool GP2XSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) { return false; } - #endif diff --git a/backends/events/gp2xsdl/gp2xsdl-events.h b/backends/events/gp2xsdl/gp2xsdl-events.h index 8ea533d052..0d74c1bcac 100644 --- a/backends/events/gp2xsdl/gp2xsdl-events.h +++ b/backends/events/gp2xsdl/gp2xsdl-events.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #if !defined(BACKEND_EVENTS_SDL_GP2X_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) @@ -29,7 +26,7 @@ #include "backends/events/sdl/sdl-events.h" /** - * SDL events manager for GP2X and GP2XWIZ + * SDL events manager for GP2X */ class GP2XSdlEventSource : public SdlEventSource { public: diff --git a/backends/platform/gph/gph-events.cpp b/backends/events/gph/gph-events.cpp index 2a6237c794..d2b3483f84 100644 --- a/backends/platform/gph/gph-events.cpp +++ b/backends/events/gph/gph-events.cpp @@ -18,19 +18,19 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ +#include "common/scummsys.h" + /* * GPH: Device Specific Event Handling. - * */ -#include "backends/platform/gph/gph-sdl.h" +#if defined(GPH_DEVICE) + +#include "backends/events/gph/gph-events.h" +#include "backends/graphics/gph/gph-graphics.h" #include "backends/platform/gph/gph-hw.h" -#include "graphics/scaler/aspect.h" #include "common/util.h" #include "common/events.h" @@ -78,7 +78,9 @@ int BUTTON_STATE_L = false; BUTTON_SELECT = 62 }; -#else +#endif + +#if defined(GP2XWIZ) /* Wiz: Main Joystick Mappings */ enum { @@ -115,6 +117,42 @@ int BUTTON_STATE_L = false; #endif +#if defined(GP2X) + +enum { + /* DPAD/Stick */ + BUTTON_UP = 0, + BUTTON_UPLEFT = 1, + BUTTON_LEFT = 2, + BUTTON_DOWNLEFT = 3, + BUTTON_DOWN = 4, + BUTTON_DOWNRIGHT = 5, + BUTTON_RIGHT = 6, + BUTTON_UPRIGHT = 7, + /* Joystick Buttons */ + BUTTON_MENU = 8, // Start on F100 GP2X + BUTTON_SELECT = 9, + BUTTON_L = 10, + BUTTON_R = 11, + BUTTON_A = 12, + BUTTON_B = 13, + BUTTON_X = 14, + BUTTON_Y = 15, + BUTTON_VOLUP = 16, + BUTTON_VOLDOWN = 17, + BUTTON_CLICK = 18 +}; + +enum { + /* Unused Joystick Buttons on the GP2X */ + BUTTON_HOME = 51, + BUTTON_HOLD = 52, + BUTTON_HELP = 53, + BUTTON_HELP2 = 54 +}; + +#endif + enum { /* Touchscreen TapMode */ TAPMODE_LEFT = 0, @@ -122,48 +160,34 @@ enum { TAPMODE_HOVER = 2 }; -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { - if (key >= SDLK_F1 && key <= SDLK_F9) { - return key - SDLK_F1 + Common::ASCII_F1; - } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { - return key - SDLK_KP0 + '0'; - } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { - return key; - } else if (unicode) { - return unicode; - } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { - return key & ~0x20; - } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { - return 0; - } - return key; -} - - -void OSystem_GPH::fillMouseEvent(Common::Event &event, int x, int y) { - if (_videoMode.mode == GFX_HALF && !_overlayVisible){ - event.mouse.x = x*2; - event.mouse.y = y*2; - } else { - event.mouse.x = x; - event.mouse.y = y; - } - - // Update the "keyboard mouse" coords - _km.x = x; - _km.y = y; - - // Adjust for the screen scaling - if (!_overlayVisible) { - event.mouse.x /= _videoMode.scaleFactor; - event.mouse.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - event.mouse.y = aspect2Real(event.mouse.y); - } +GPHEventSource::GPHEventSource() + : _buttonStateL(false){ } - -void OSystem_GPH::moveStick() { +//void GPHEventSource::fillMouseEvent(Common::Event &event, int x, int y) { +// if (GPHGraphicsManager::_videoMode.mode == GFX_HALF && !GPHGraphicsManager::_overlayVisible){ +// event.mouse.x = x*2; +// event.mouse.y = y*2; +// } else { +// event.mouse.x = x; +// event.mouse.y = y; +// } +// +// // Update the "keyboard mouse" coords +// _km.x = x; +// _km.y = y; +// +// // Adjust for the screen scaling +// if (!_overlayVisible) { +// event.mouse.x /= _videoMode.scaleFactor; +// event.mouse.y /= _videoMode.scaleFactor; +// if (_videoMode.aspectRatioCorrection) +// event.mouse.y = aspect2Real(event.mouse.y); +// } +//} + + +void GPHEventSource::moveStick() { bool stickBtn[32]; memcpy(stickBtn, _stickBtn, sizeof(stickBtn)); @@ -208,7 +232,7 @@ void OSystem_GPH::moveStick() { /* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */ -bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { +bool GPHEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.button.button == SDL_BUTTON_LEFT){ if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ event.type = Common::EVENT_RBUTTONDOWN; @@ -241,7 +265,7 @@ bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { +bool GPHEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.button.button == SDL_BUTTON_LEFT){ if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ event.type = Common::EVENT_RBUTTONUP; @@ -270,7 +294,7 @@ bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { /* Custom handleJoyButtonDown/handleJoyButtonUp to deal with the joystick buttons on GPH devices */ -bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { +bool GPHEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { _stickBtn[ev.jbutton.button] = 1; event.kbd.flags = 0; @@ -339,11 +363,11 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { if (BUTTON_STATE_L == true) { GPH::ToggleTapMode(); if (GPH::tapmodeLevel == TAPMODE_LEFT) { - displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); } else if (GPH::tapmodeLevel == TAPMODE_RIGHT) { - displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); } else if (GPH::tapmodeLevel == TAPMODE_HOVER) { - displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); } } else { event.kbd.keycode = Common::KEYCODE_SPACE; @@ -363,17 +387,17 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { case BUTTON_VOLUP: WIZ_HW::mixerMoveVolume(2); if (WIZ_HW::volumeLevel == 100) { - displayMessageOnOSD("Maximum Volume"); + g_system->displayMessageOnOSD("Maximum Volume"); } else { - displayMessageOnOSD("Increasing Volume"); + g_system->displayMessageOnOSD("Increasing Volume"); } break; case BUTTON_VOLDOWN: WIZ_HW::mixerMoveVolume(1); if (WIZ_HW::volumeLevel == 0) { - displayMessageOnOSD("Minimal Volume"); + g_system->displayMessageOnOSD("Minimal Volume"); } else { - displayMessageOnOSD("Decreasing Volume"); + g_system->displayMessageOnOSD("Decreasing Volume"); } break; case BUTTON_HOLD: @@ -382,18 +406,18 @@ bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { case BUTTON_HELP2: GPH::ToggleTapMode(); if (GPH::tapmodeLevel == TAPMODE_LEFT) { - displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click"); + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click"); } else if (GPH::tapmodeLevel == TAPMODE_RIGHT) { - displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click"); + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click"); } else if (GPH::tapmodeLevel == TAPMODE_HOVER) { - displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)"); + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)"); } break; } return true; } -bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { +bool GPHEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { _stickBtn[ev.jbutton.button] = 0; event.kbd.flags = 0; @@ -476,6 +500,8 @@ bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_GPH::remapKey(SDL_Event &ev,Common::Event &event) { +bool GPHEventSource::remapKey(SDL_Event &ev,Common::Event &event) { return false; } + +#endif diff --git a/backends/events/gph/gph-events.h b/backends/events/gph/gph-events.h new file mode 100644 index 0000000000..7672bffed2 --- /dev/null +++ b/backends/events/gph/gph-events.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#if !defined(BACKEND_EVENTS_GPH_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_GPH_H + +#include "backends/events/sdl/sdl-events.h" + +/* + * SDL Events manager for GPH devices. + */ + +class GPHEventSource : public SdlEventSource { +public: + GPHEventSource(); + +protected: + bool _stickBtn[32]; + + /** + * Button state for L button modifier + */ + bool _buttonStateL; + + /** + * Handles the stick movement + */ + void moveStick(); + + bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); + bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); + bool remapKey(SDL_Event &ev, Common::Event &event); +}; + +#endif /* BACKEND_EVENTS_GPH_H */ diff --git a/backends/platform/openpandora/op-events.cpp b/backends/events/openpandora/op-events.cpp index 24283aa8ba..381cbf89e9 100644 --- a/backends/platform/openpandora/op-events.cpp +++ b/backends/events/openpandora/op-events.cpp @@ -18,16 +18,19 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ +#include "common/scummsys.h" + /* * OpenPandora: Device Specific Event Handling. * */ +#if defined(OPENPANDORA) + +#include "backends/events/openpandora/op-events.h" +#include "backends/graphics/openpandora/op-graphics.h" #include "backends/platform/openpandora/op-sdl.h" #include "backends/platform/openpandora/op-options.h" @@ -41,81 +44,87 @@ enum { TAPMODE_HOVER = 2 }; +OPEventSource::OPEventSource() + : _buttonStateL(false){ +} + /* On the OpenPandora by default the ABXY and L/R Trigger buttons are returned by SDL as (A): SDLK_HOME (B): SDLK_END (X): SDLK_PAGEDOWN (Y): SDLK_PAGEUP (L): SDLK_RSHIFT (R): SDLK_RCTRL */ -bool OSystem_OP::handleKeyDown(SDL_Event &ev, Common::Event &event) { - switch (ev.key.keysym.sym) { - case SDLK_HOME: - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - return true; - break; - case SDLK_END: - event.type = Common::EVENT_RBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - return true; - break; - case SDLK_PAGEDOWN: - event.type = Common::EVENT_MAINMENU; - return true; - break; - case SDLK_PAGEUP: - OP::ToggleTapMode(); - if (OP::tapmodeLevel == TAPMODE_LEFT) { - displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); - } else if (OP::tapmodeLevel == TAPMODE_RIGHT) { - displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); - } else if (OP::tapmodeLevel == TAPMODE_HOVER) { - displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); - } - break; - case SDLK_RSHIFT: - BUTTON_STATE_L = true; - break; - case SDLK_RCTRL: - break; - default: - return OSystem_SDL::handleKeyDown(ev, event); - break; - } - return false; -} +bool OPEventSource::remapKey(SDL_Event &ev, Common::Event &event) { -bool OSystem_OP::handleKeyUp(SDL_Event &ev, Common::Event &event) { - switch (ev.key.keysym.sym) { - case SDLK_HOME: - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - return true; - break; - case SDLK_END: - event.type = Common::EVENT_RBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - return true; - break; - case SDLK_PAGEDOWN: - event.type = Common::EVENT_MAINMENU; - return true; - break; - case SDLK_PAGEUP: - break; - case SDLK_RSHIFT: - BUTTON_STATE_L = false; - break; - case SDLK_RCTRL: - break; - default: - return OSystem_SDL::handleKeyUp(ev, event); - break; + if (ev.type == SDL_KEYDOWN) { + switch (ev.key.keysym.sym) { + case SDLK_HOME: + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_END: + event.type = Common::EVENT_RBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_PAGEDOWN: + event.type = Common::EVENT_MAINMENU; + return true; + break; + case SDLK_PAGEUP: + OP::ToggleTapMode(); + if (OP::tapmodeLevel == TAPMODE_LEFT) { + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); + } else if (OP::tapmodeLevel == TAPMODE_RIGHT) { + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); + } else if (OP::tapmodeLevel == TAPMODE_HOVER) { + g_system->displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); + } + break; + case SDLK_RSHIFT: + BUTTON_STATE_L = true; + break; + case SDLK_RCTRL: + break; + default: + return false; + break; + } + return false; + } else { + switch (ev.key.keysym.sym) { + case SDLK_HOME: + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_END: + event.type = Common::EVENT_RBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_PAGEDOWN: + event.type = Common::EVENT_MAINMENU; + return true; + break; + case SDLK_PAGEUP: + break; + case SDLK_RSHIFT: + BUTTON_STATE_L = false; + break; + case SDLK_RCTRL: + break; + default: + return false; + break; + } + return false; } return false; } /* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */ -bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { +bool OPEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.button.button == SDL_BUTTON_LEFT){ if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ event.type = Common::EVENT_RBUTTONDOWN; @@ -148,7 +157,7 @@ bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { +bool OPEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.button.button == SDL_BUTTON_LEFT){ if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ event.type = Common::EVENT_RBUTTONUP; @@ -174,3 +183,4 @@ bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { return true; } +#endif diff --git a/backends/events/openpandora/op-events.h b/backends/events/openpandora/op-events.h new file mode 100644 index 0000000000..9aa637992a --- /dev/null +++ b/backends/events/openpandora/op-events.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#if !defined(BACKEND_EVENTS_OP_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_OP_H + +#include "backends/events/sdl/sdl-events.h" + +/** + * Events manager for the OpenPandora. + */ +class OPEventSource : public SdlEventSource { +public: + OPEventSource(); + +protected: + /** Button state for L button modifier */ + bool _buttonStateL; + + bool remapKey(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); +}; + +#endif /* BACKEND_EVENTS_OP_H */ diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index ce846a0836..6e343b63f5 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -31,6 +31,7 @@ #include "backends/platform/sdl/sdl.h" #include "backends/graphics/graphics.h" #include "common/config-manager.h" +#include "common/textconsole.h" // FIXME move joystick defines out and replace with confile file options // we should really allow users to map any key to a joystick button @@ -65,7 +66,7 @@ SdlEventSource::SdlEventSource() // Enable joystick if (SDL_NumJoysticks() > 0) { - printf("Using joystick: %s\n", SDL_JoystickName(0)); + debug("Using joystick: %s", SDL_JoystickName(0)); _joystick = SDL_JoystickOpen(joystick_num); } } diff --git a/backends/events/webossdl/webossdl-events.cpp b/backends/events/webossdl/webossdl-events.cpp new file mode 100644 index 0000000000..24aa5f0abd --- /dev/null +++ b/backends/events/webossdl/webossdl-events.cpp @@ -0,0 +1,245 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef WEBOS + +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +#include "common/scummsys.h" +#include "common/system.h" +#include "sys/time.h" +#include "time.h" + +#include "backends/events/webossdl/webossdl-events.h" +#include "gui/message.h" + +// Inidicates if gesture area is pressed down or not. +static bool gestureDown = false; + +// The timestamp when gesture area was pressed down. +static int gestureDownTime = 0; + +// The timestamp when screen was pressed down. +static int screenDownTime = 0; + +// The timestamp when a possible drag operation was triggered. +static int dragStartTime = 0; + +// The index of the motion pointer. +static int motionPtrIndex = -1; + +// The maximum horizontal motion during dragging (For tap recognition). +static int dragDiffX = 0; + +// The maximum vertical motion during dragging (For tap recognition). +static int dragDiffY = 0; + +// Indicates if we are in drag mode. +static bool dragging = false; + +// The current mouse position on the screen. +static int curX = 0, curY = 0; + +// The time (seconds after 1/1/1970) when program started. +static time_t programStartTime = time(0); + +/** + * Returns the number of passed milliseconds since program start. + * + * @return The number of passed milliseconds. + */ +static time_t getMillis() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (time(0) - programStartTime) * 1000 + tv.tv_usec / 1000; +} + +/** + * WebOS devices only have a Shift key and a CTRL key. There is also an Alt + * key (the orange key) but this is already processed by WebOS to change the + * mode of the keys so ScummVM must not use this key as a modifier. Instead + * pressing down the gesture area is used as Alt key. + * + * @param mod The pressed key modifier as detected by SDL. + * @param event The ScummVM event to setup. + */ +void WebOSSdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, + Common::Event &event) { + event.kbd.flags = 0; + + if (mod & KMOD_SHIFT) + event.kbd.flags |= Common::KBD_SHIFT; + if (mod & KMOD_CTRL) + event.kbd.flags |= Common::KBD_CTRL; + if (gestureDown) + event.kbd.flags |= Common::KBD_ALT; +} + +/** + * Before calling the original SDL implementation this method checks if the + * gesture area is pressed down. + * + * @param ev The SDL event + * @param event The ScummVM event. + * @return True if event was processed, false if not. + */ +bool WebOSSdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) { + // Handle gesture area tap. + if (ev.key.keysym.sym == SDLK_WORLD_71) { + gestureDown = true; + gestureDownTime = getMillis(); + return true; + } + + // Call original SDL key handler. + return SdlEventSource::handleKeyDown(ev, event); +} + +/** + * Before calling the original SDL implementation this method checks if the + * gesture area has been released. + * + * @param ev The SDL event + * @param event The ScummVM event. + * @return True if event was processed, false if not. + */ +bool WebOSSdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) { + // Handle gesture area tap. + if (ev.key.keysym.sym == SDLK_WORLD_71) { + gestureDown = false; + return true; + } + + // Call original SDL key handler. + return SdlEventSource::handleKeyUp(ev, event); +} + +/** + * Handles mouse button press. + * + * @param ev The SDL event + * @param event The ScummVM event. + * @return True if event was processed, false if not. + */ +bool WebOSSdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { + if (motionPtrIndex == -1) { + motionPtrIndex = ev.button.which; + dragDiffX = 0; + dragDiffY = 0; + screenDownTime = getMillis(); + + // Start dragging when pressing the screen shortly after a tap. + if (getMillis() - dragStartTime < 250) { + dragging = true; + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, curX, curY); + } + } + return true; +} + +/** + * Handles mouse button release. + * + * @param ev The SDL event + * @param event The ScummVM event. + * @return True if event was processed, false if not. + */ +bool WebOSSdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { + if (motionPtrIndex == ev.button.which) { + motionPtrIndex = -1; + + // When drag mode was active then simply send a mouse up event + if (dragging) + { + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, curX, curY); + dragging = false; + return true; + } + + // When mouse was moved 5 pixels or less then emulate a mouse button + // click. + if (ABS(dragDiffX) < 6 && ABS(dragDiffY) < 6) + { + int duration = getMillis() - screenDownTime; + + // When screen was pressed for less than 500ms then emulate a + // left mouse click. + if (duration < 500) { + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, curX, curY); + g_system->getEventManager()->pushEvent(event); + event.type = Common::EVENT_LBUTTONDOWN; + dragStartTime = getMillis(); + } + + // When screen was pressed for less than 1000ms then emulate a + // right mouse click. + else if (duration < 1000) { + event.type = Common::EVENT_RBUTTONUP; + fillMouseEvent(event, curX, curY); + g_system->getEventManager()->pushEvent(event); + event.type = Common::EVENT_RBUTTONDOWN; + } + + // When screen was pressed for more than 1000ms then emulate a + // middle mouse click. + else { + event.type = Common::EVENT_MBUTTONUP; + fillMouseEvent(event, curX, curY); + g_system->getEventManager()->pushEvent(event); + event.type = Common::EVENT_MBUTTONDOWN; + } + + } + } + return true; +} + +/** + * Handles mouse motion. + * + * @param ev The SDL event + * @param event The ScummVM event. + * @return True if event was processed, false if not. + */ +bool WebOSSdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) { + if (ev.motion.which == motionPtrIndex) { + int screenX = g_system->getWidth(); + int screenY = g_system->getHeight(); + curX = MIN(screenX, MAX(0, curX + ev.motion.xrel)); + curY = MIN(screenY, MAX(0, curY + ev.motion.yrel)); + dragDiffX += ev.motion.xrel; + dragDiffY += ev.motion.yrel; + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, curX, curY); + } + return true; +} + +#endif diff --git a/backends/events/webossdl/webossdl-events.h b/backends/events/webossdl/webossdl-events.h new file mode 100644 index 0000000000..3a41111cf2 --- /dev/null +++ b/backends/events/webossdl/webossdl-events.h @@ -0,0 +1,44 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(BACKEND_EVENTS_SDL_WEBOS_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_SDL_WEBOS_H + +#include "backends/events/sdl/sdl-events.h" + +/** + * SDL events manager for WebOS + */ +class WebOSSdlEventSource : public SdlEventSource { +protected: + virtual void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event); + virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event); + virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event); +}; + +#endif diff --git a/backends/events/wincesdl/wincesdl-events.cpp b/backends/events/wincesdl/wincesdl-events.cpp new file mode 100644 index 0000000000..2505b0fb31 --- /dev/null +++ b/backends/events/wincesdl/wincesdl-events.cpp @@ -0,0 +1,332 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/scummsys.h" + +#ifdef _WIN32_WCE + +#include "common/config-manager.h" + +#include "backends/events/wincesdl/wincesdl-events.h" +#include "backends/platform/wince/CEActionsPocket.h" +#include "backends/platform/wince/CEActionsSmartphone.h" +#include "backends/platform/wince/CEDevice.h" + +#include "backends/platform/sdl/sdl.h" + +WINCESdlEventSource::WINCESdlEventSource() + : _tapTime(0), _closeClick(false), _rbutton(false), + _freeLook(false), _graphicsMan(0) { +} + +void WINCESdlEventSource::init(WINCESdlGraphicsManager *graphicsMan) { + assert(graphicsMan); + _graphicsMan = graphicsMan; +} + +void WINCESdlEventSource::fillMouseEvent(Common::Event &event, int x, int y) { + event.mouse.x = x; + event.mouse.y = y; + + // Update the "keyboard mouse" coords + _km.x = event.mouse.x; + _km.y = event.mouse.y; + + // Adjust for the screen scaling + if (_graphicsMan->_zoomDown) + event.mouse.y += 240; + + event.mouse.x = event.mouse.x * _graphicsMan->_scaleFactorXd / _graphicsMan->_scaleFactorXm; + event.mouse.y = event.mouse.y * _graphicsMan->_scaleFactorYd / _graphicsMan->_scaleFactorYm; +} + +bool WINCESdlEventSource::pollEvent(Common::Event &event) { + SDL_Event ev; + ev.type = SDL_NOEVENT; + DWORD currentTime; + bool keyEvent = false; + int deltaX, deltaY; + + memset(&event, 0, sizeof(Common::Event)); + + handleKbdMouse(); + + // If the screen changed, send an Common::EVENT_SCREEN_CHANGED + int screenID = _graphicsMan->getScreenChangeID(); + if (screenID != _lastScreenID) { + _lastScreenID = screenID; + event.type = Common::EVENT_SCREEN_CHANGED; + return true; + } + + CEDevice::wakeUp(); + + currentTime = GetTickCount(); + + while (SDL_PollEvent(&ev)) { + switch (ev.type) { + case SDL_KEYDOWN: + debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym)); + // KMOD_RESERVED is used if the key has been injected by an external buffer + if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) { + keyEvent = true; + _graphicsMan->_lastKeyPressed = ev.key.keysym.sym; + _graphicsMan->_keyRepeatTime = currentTime; + _graphicsMan->_keyRepeat = 0; + + if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true)) + return true; + } + + if (GUI_Actions::Instance()->mappingActive()) + event.kbd.flags = 0xFF; + else if (ev.key.keysym.sym == SDLK_PAUSE) { + _graphicsMan->_lastKeyPressed = 0; + event.type = Common::EVENT_PREDICTIVE_DIALOG; + return true; + } + event.type = Common::EVENT_KEYDOWN; + if (!GUI::Actions::Instance()->mappingActive()) + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; + else + event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); + event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); + + if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { + event.kbd.ascii ^= 0x20; + event.kbd.flags = Common::KBD_SHIFT; + } + + return true; + + case SDL_KEYUP: + debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym)); + // KMOD_RESERVED is used if the key has been injected by an external buffer + if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) { + keyEvent = true; + _graphicsMan->_lastKeyPressed = 0; + + if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false)) + return true; + } + + if (GUI_Actions::Instance()->mappingActive()) + event.kbd.flags = 0xFF; + else if (ev.key.keysym.sym == SDLK_PAUSE) { + _graphicsMan->_lastKeyPressed = 0; + return false; // chew up the show agi dialog key up event + } + + event.type = Common::EVENT_KEYUP; + if (!GUI::Actions::Instance()->mappingActive()) + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; + else + event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); + event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); + + if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { + event.kbd.ascii ^= 0x20; + event.kbd.flags = Common::KBD_SHIFT; + } + + return true; + + case SDL_MOUSEMOTION: + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, ev.motion.x, ev.motion.y); + _graphicsMan->setMousePos(event.mouse.x, event.mouse.y); + + return true; + + case SDL_MOUSEBUTTONDOWN: + if (ev.button.button == SDL_BUTTON_LEFT) + event.type = Common::EVENT_LBUTTONDOWN; + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONDOWN; + else + break; + fillMouseEvent(event, ev.button.x, ev.button.y); + + + if (event.mouse.x > _tapX) + deltaX = event.mouse.x - _tapX; + else + deltaX = _tapX - event.mouse.x; + if (event.mouse.y > _tapY) + deltaY = event.mouse.y - _tapY; + else + deltaY = _tapY - event.mouse.y; + _closeClick = (deltaX <= 5 && deltaY <= 5); + + if (!_isSmartphone) { + // handle double-taps + if (_tapTime) { // second tap + if (_closeClick && (GetTickCount() - _tapTime < 1000)) { + if (event.mouse.y <= 20 && + _graphicsMan->_panelInitialized) { + // top of screen (show panel) + _graphicsMan->swap_panel_visibility(); + } else if (!_graphicsMan->_noDoubleTapRMB) { + // right click + event.type = Common::EVENT_RBUTTONDOWN; + _rbutton = true; + } + } + _tapTime = 0; + } else { + _tapTime = GetTickCount(); + _tapX = event.mouse.x; + _tapY = event.mouse.y; + } + } + + if (_freeLook && !_closeClick) { + _rbutton = false; + _tapTime = 0; + _tapX = event.mouse.x; + _tapY = event.mouse.y; + event.type = Common::EVENT_MOUSEMOVE; + _graphicsMan->setMousePos(event.mouse.x, event.mouse.y); + } + + + if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) { + if (!_graphicsMan->_toolbarHandler.drawn()) { + _graphicsMan->_toolbarHighDrawn = false; + _graphicsMan->internUpdateScreen(); + } + if (_graphicsMan->_newOrientation != _graphicsMan->_orientationLandscape) { + _graphicsMan->_orientationLandscape = _graphicsMan->_newOrientation; + _graphicsMan->_toolbarHighDrawn = false; + ConfMan.setInt("landscape", _graphicsMan->_orientationLandscape); + ConfMan.flushToDisk(); + _graphicsMan->hotswapGFXMode(); + } + return false; + } + + return true; + + case SDL_MOUSEBUTTONUP: + if (ev.button.button == SDL_BUTTON_LEFT) + event.type = Common::EVENT_LBUTTONUP; + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONUP; + else + break; + + if (_rbutton) { + event.type = Common::EVENT_RBUTTONUP; + _rbutton = false; + } + + fillMouseEvent(event, ev.button.x, ev.button.y); + + if (_freeLook && !_closeClick) { + _tapX = event.mouse.x; + _tapY = event.mouse.y; + event.type = Common::EVENT_MOUSEMOVE; + _graphicsMan->setMousePos(event.mouse.x, event.mouse.y); + } + + if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) { + if (!_graphicsMan->_toolbarHandler.drawn()) { + _graphicsMan->_toolbarHighDrawn = false; + _graphicsMan->internUpdateScreen(); + } + return false; + + } + return true; + + case SDL_VIDEOEXPOSE: + // HACK: Send a fake event, handled by SdlGraphicsManager + event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose; + break; + + case SDL_QUIT: + event.type = Common::EVENT_QUIT; + return true; + + case SDL_ACTIVEEVENT: + if (ev.active.state & SDL_APPMOUSEFOCUS) + debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost"); + if (ev.active.state & SDL_APPINPUTFOCUS) + debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost"); + if (ev.active.state & SDL_APPACTIVE) + debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost"); + if (ev.active.state & SDL_APPINPUTFOCUS) { + _graphicsMan->_hasfocus = ev.active.gain; + SDL_PauseAudio(!_graphicsMan->_hasfocus); + if (_graphicsMan->_hasfocus) { + event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose; + } + } + break; + } + } + + // Simulate repeated key for backend + if (!keyEvent && _graphicsMan->_lastKeyPressed && (int)currentTime > _graphicsMan->_keyRepeatTime + _graphicsMan->_keyRepeatTrigger) { + _graphicsMan->_keyRepeatTime = currentTime; + _graphicsMan->_keyRepeat++; + GUI_Actions::Instance()->performMapped(_graphicsMan->_lastKeyPressed, true); + } + + return false; +} + +int WINCESdlEventSource::mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) { + if (GUI::Actions::Instance()->mappingActive()) + return key; + + if (unfilter) { + switch (key) { + case SDLK_ESCAPE: + return SDLK_BACKSPACE; + case SDLK_F8: + return SDLK_ASTERISK; + case SDLK_F9: + return SDLK_HASH; + default: + return key; + } + } + + if (key >= SDLK_KP0 && key <= SDLK_KP9) { + return key - SDLK_KP0 + '0'; + } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { + return key; + } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { + return 0; + } + return key; +} + +void WINCESdlEventSource::swap_freeLook() { + _freeLook = !_freeLook; +} + +#endif /* _WIN32_WCE */ diff --git a/backends/events/wincesdl/wincesdl-events.h b/backends/events/wincesdl/wincesdl-events.h new file mode 100644 index 0000000000..f5b1026c46 --- /dev/null +++ b/backends/events/wincesdl/wincesdl-events.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_EVENTS_SDL_WINCE_H +#define BACKENDS_EVENTS_SDL_WINCE_H + +#include "common/scummsys.h" + +#ifdef _WIN32_WCE + +#include "backends/events/sdl/sdl-events.h" +#include "backends/graphics/wincesdl/wincesdl-graphics.h" + +extern bool _isSmartphone; + +class WINCESdlEventSource : public SdlEventSource { +public: + WINCESdlEventSource(); + + void init(WINCESdlGraphicsManager *graphicsMan); + + void loadDeviceConfiguration(); + + // Overloaded from SDL backend (toolbar handling) + bool pollEvent(Common::Event &event); + // Overloaded from SDL backend (mouse and new scaler handling) + void fillMouseEvent(Common::Event &event, int x, int y); + + void swap_freeLook(); + +protected: + +private: + int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter); + + WINCESdlGraphicsManager *_graphicsMan; + + // Keyboard tap + int _tapX; + int _tapY; + long _tapTime; + + bool _closeClick; // flag when taps are spatially close together + bool _rbutton; // double tap -> right button simulation + bool _freeLook; // freeLook mode (do not send mouse button events) + +}; + +#endif + +#endif /* BACKENDS_EVENTS_SDL_WINCE_H */ diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.cpp b/backends/fs/amigaos4/amigaos4-fs-factory.cpp index 2c7dc61278..51c2c294d4 100644 --- a/backends/fs/amigaos4/amigaos4-fs-factory.cpp +++ b/backends/fs/amigaos4/amigaos4-fs-factory.cpp @@ -23,8 +23,9 @@ */ #if defined(__amigaos4__) + #include "backends/fs/amigaos4/amigaos4-fs-factory.h" -#include "backends/fs/amigaos4/amigaos4-fs.cpp" +#include "backends/fs/amigaos4/amigaos4-fs.h" AbstractFSNode *AmigaOSFilesystemFactory::makeRootFileNode() const { return new AmigaOSFilesystemNode(); diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp index 8a57a3cf1c..4f763ef9e8 100644 --- a/backends/fs/amigaos4/amigaos4-fs.cpp +++ b/backends/fs/amigaos4/amigaos4-fs.cpp @@ -23,97 +23,16 @@ */ #if defined(__amigaos4__) -#ifdef __USE_INLINE__ -#undef __USE_INLINE__ -#endif - -#include <proto/exec.h> -#include <proto/dos.h> -#include <stdio.h> - -#ifndef USE_NEWLIB -#include <strings.h> -#endif +#include "backends/fs/amigaos4/amigaos4-fs.h" +#include "backends/fs/stdiostream.h" #include "common/debug.h" #include "common/util.h" -#include "backends/fs/abstract-fs.h" -#include "backends/fs/stdiostream.h" #define ENTER() /* debug(6, "Enter") */ #define LEAVE() /* debug(6, "Leave") */ /** - * Implementation of the ScummVM file system API. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class AmigaOSFilesystemNode : public AbstractFSNode { -protected: - BPTR _pFileLock; - Common::String _sDisplayName; - Common::String _sPath; - bool _bIsDirectory; - bool _bIsValid; - uint32 _nProt; - - /** - * Creates a list with all the volumes present in the root node. - */ - virtual AbstractFSList listVolumes() const; - -public: - /** - * Creates an AmigaOSFilesystemNode with the root node as path. - */ - AmigaOSFilesystemNode(); - - /** - * Creates an AmigaOSFilesystemNode for a given path. - * - * @param path Common::String with the path the new node should point to. - */ - AmigaOSFilesystemNode(const Common::String &p); - - /** - * Creates an AmigaOSFilesystemNode given its lock and display name - * - * @param pLock BPTR to the lock. - * @param pDisplayName name to be used for display, in case not supplied the FilePart() of the filename will be used. - * - * @note This shouldn't even be public as it's only internally, at best it should have been protected if not private - */ - AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0); - - /** - * Copy constructor. - * - * @note Needed because it duplicates the file lock - */ - AmigaOSFilesystemNode(const AmigaOSFilesystemNode &node); - - /** - * Destructor. - */ - virtual ~AmigaOSFilesystemNode(); - - virtual bool exists() const; - virtual Common::String getDisplayName() const { return _sDisplayName; }; - virtual Common::String getName() const { return _sDisplayName; }; - virtual Common::String getPath() const { return _sPath; }; - virtual bool isDirectory() const { return _bIsDirectory; }; - virtual bool isReadable() const; - virtual bool isWritable() const; - - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); -}; - -/** * Returns the last component of a given path. * * @param str Common::String containing the path. @@ -497,11 +416,11 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const { } Common::SeekableReadStream *AmigaOSFilesystemNode::createReadStream() { - return StdioStream::makeFromPath(getPath().c_str(), false); + return StdioStream::makeFromPath(getPath(), false); } Common::WriteStream *AmigaOSFilesystemNode::createWriteStream() { - return StdioStream::makeFromPath(getPath().c_str(), true); + return StdioStream::makeFromPath(getPath(), true); } #endif //defined(__amigaos4__) diff --git a/backends/fs/amigaos4/amigaos4-fs.h b/backends/fs/amigaos4/amigaos4-fs.h new file mode 100644 index 0000000000..83188f89f1 --- /dev/null +++ b/backends/fs/amigaos4/amigaos4-fs.h @@ -0,0 +1,113 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef AMIGAOS_FILESYSTEM_H +#define AMIGAOS_FILESYSTEM_H + +#ifdef __USE_INLINE__ +#undef __USE_INLINE__ +#endif + +#include <proto/exec.h> +#include <proto/dos.h> +#include <stdio.h> + +#ifndef USE_NEWLIB +#include <strings.h> +#endif + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class AmigaOSFilesystemNode : public AbstractFSNode { +protected: + BPTR _pFileLock; + Common::String _sDisplayName; + Common::String _sPath; + bool _bIsDirectory; + bool _bIsValid; + uint32 _nProt; + + /** + * Creates a list with all the volumes present in the root node. + */ + virtual AbstractFSList listVolumes() const; + +public: + /** + * Creates an AmigaOSFilesystemNode with the root node as path. + */ + AmigaOSFilesystemNode(); + + /** + * Creates an AmigaOSFilesystemNode for a given path. + * + * @param path Common::String with the path the new node should point to. + */ + AmigaOSFilesystemNode(const Common::String &p); + + /** + * Creates an AmigaOSFilesystemNode given its lock and display name + * + * @param pLock BPTR to the lock. + * @param pDisplayName name to be used for display, in case not supplied the FilePart() of the filename will be used. + * + * @note This shouldn't even be public as it's only internally, at best it should have been protected if not private + */ + AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0); + + /** + * Copy constructor. + * + * @note Needed because it duplicates the file lock + */ + AmigaOSFilesystemNode(const AmigaOSFilesystemNode &node); + + /** + * Destructor. + */ + virtual ~AmigaOSFilesystemNode(); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { return _sDisplayName; }; + virtual Common::String getName() const { return _sDisplayName; }; + virtual Common::String getPath() const { return _sPath; }; + virtual bool isDirectory() const { return _bIsDirectory; }; + virtual bool isReadable() const; + virtual bool isWritable() const; + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); +}; + + +#endif diff --git a/backends/fs/n64/n64-fs-factory.cpp b/backends/fs/n64/n64-fs-factory.cpp index 7e314693b8..e362e3214a 100644 --- a/backends/fs/n64/n64-fs-factory.cpp +++ b/backends/fs/n64/n64-fs-factory.cpp @@ -25,9 +25,10 @@ #ifdef __N64__ #include <n64utils.h> +#include <romfs.h> #include "backends/fs/n64/n64-fs-factory.h" -#include "backends/fs/n64/n64-fs.cpp" +#include "backends/fs/n64/n64-fs.h" AbstractFSNode *N64FilesystemFactory::makeRootFileNode() const { return new N64FilesystemNode(); diff --git a/backends/fs/n64/n64-fs-factory.h b/backends/fs/n64/n64-fs-factory.h index 915153c6f8..35bad9600a 100644 --- a/backends/fs/n64/n64-fs-factory.h +++ b/backends/fs/n64/n64-fs-factory.h @@ -25,7 +25,6 @@ #ifndef N64_FILESYSTEM_FACTORY_H #define N64_FILESYSTEM_FACTORY_H -#include <romfs.h> #include "backends/fs/fs-factory.h" /** diff --git a/backends/fs/n64/n64-fs.cpp b/backends/fs/n64/n64-fs.cpp index 4def84afcd..e712c198a9 100644 --- a/backends/fs/n64/n64-fs.cpp +++ b/backends/fs/n64/n64-fs.cpp @@ -22,65 +22,18 @@ #ifdef __N64__ -#include "backends/fs/abstract-fs.h" +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + +#include "backends/fs/n64/n64-fs.h" #include "backends/fs/n64/romfsstream.h" +#include <romfs.h> #include <sys/param.h> #include <unistd.h> #include <n64utils.h> #define ROOT_PATH "/" -/** - * Implementation of the ScummVM file system API based on N64 Hkz romfs. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class N64FilesystemNode : public AbstractFSNode { -protected: - Common::String _displayName; - Common::String _path; - bool _isDirectory; - bool _isValid; - -public: - /** - * Creates a N64FilesystemNode with the root node as path. - */ - N64FilesystemNode(); - - /** - * Creates a N64FilesystemNode for a given path. - * - * @param path Common::String with the path the new node should point to. - * @param verify true if the isValid and isDirectory flags should be verified during the construction. - */ - N64FilesystemNode(const Common::String &p, bool verify = true); - - virtual bool exists() const; - virtual Common::String getDisplayName() const { - return _displayName; - } - virtual Common::String getName() const { - return _displayName; - } - virtual Common::String getPath() const { - return _path; - } - virtual bool isDirectory() const { - return _isDirectory; - } - virtual bool isReadable() const; - virtual bool isWritable() const; - - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); -}; - N64FilesystemNode::N64FilesystemNode() { _isDirectory = true; _displayName = "Root"; diff --git a/backends/fs/n64/n64-fs.h b/backends/fs/n64/n64-fs.h new file mode 100644 index 0000000000..3a5dd375b9 --- /dev/null +++ b/backends/fs/n64/n64-fs.h @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef N64_FILESYSTEM_H +#define N64_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API based on N64 Hkz romfs. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class N64FilesystemNode : public AbstractFSNode { +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isValid; + +public: + /** + * Creates a N64FilesystemNode with the root node as path. + */ + N64FilesystemNode(); + + /** + * Creates a N64FilesystemNode for a given path. + * + * @param path Common::String with the path the new node should point to. + * @param verify true if the isValid and isDirectory flags should be verified during the construction. + */ + N64FilesystemNode(const Common::String &p, bool verify = true); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { + return _displayName; + } + virtual Common::String getName() const { + return _displayName; + } + virtual Common::String getPath() const { + return _path; + } + virtual bool isDirectory() const { + return _isDirectory; + } + virtual bool isReadable() const; + virtual bool isWritable() const; + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); +}; + +#endif diff --git a/backends/fs/posix/posix-fs-factory.cpp b/backends/fs/posix/posix-fs-factory.cpp index df21d41dda..639f57ac06 100644 --- a/backends/fs/posix/posix-fs-factory.cpp +++ b/backends/fs/posix/posix-fs-factory.cpp @@ -23,8 +23,15 @@ */ #if defined(UNIX) + +// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h. +// Also with clock() in sys/time.h in some Mac OS X SDKs. +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + #include "backends/fs/posix/posix-fs-factory.h" -#include "backends/fs/posix/posix-fs.cpp" +#include "backends/fs/posix/posix-fs.h" AbstractFSNode *POSIXFilesystemFactory::makeRootFileNode() const { return new POSIXFilesystemNode("/"); diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp index b218e9dd59..34edb78504 100644 --- a/backends/fs/posix/posix-fs.cpp +++ b/backends/fs/posix/posix-fs.cpp @@ -24,6 +24,12 @@ #if defined(UNIX) +// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h. +// Also with clock() in sys/time.h in some Mac OS X SDKs. +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + #include "backends/fs/posix/posix-fs.h" #include "backends/fs/stdiostream.h" #include "common/algorithm.h" @@ -238,11 +244,11 @@ AbstractFSNode *POSIXFilesystemNode::getParent() const { } Common::SeekableReadStream *POSIXFilesystemNode::createReadStream() { - return StdioStream::makeFromPath(getPath().c_str(), false); + return StdioStream::makeFromPath(getPath(), false); } Common::WriteStream *POSIXFilesystemNode::createWriteStream() { - return StdioStream::makeFromPath(getPath().c_str(), true); + return StdioStream::makeFromPath(getPath(), true); } #endif //#if defined(UNIX) diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h index 859e8973b3..003a0b38d0 100644 --- a/backends/fs/posix/posix-fs.h +++ b/backends/fs/posix/posix-fs.h @@ -83,4 +83,4 @@ private: virtual void setFlags(); }; -#endif /*POSIX_FILESYSTEM_H*/ +#endif diff --git a/backends/fs/ps2/ps2-fs-factory.cpp b/backends/fs/ps2/ps2-fs-factory.cpp index 8b5202bff4..9e7ec3fa10 100644 --- a/backends/fs/ps2/ps2-fs-factory.cpp +++ b/backends/fs/ps2/ps2-fs-factory.cpp @@ -28,7 +28,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/fs/ps2/ps2-fs-factory.h" -#include "backends/fs/ps2/ps2-fs.cpp" +#include "backends/fs/ps2/ps2-fs.h" DECLARE_SINGLETON(Ps2FilesystemFactory); @@ -43,4 +43,5 @@ AbstractFSNode *Ps2FilesystemFactory::makeCurrentDirectoryFileNode() const { AbstractFSNode *Ps2FilesystemFactory::makeFileNodePath(const Common::String &path) const { return new Ps2FilesystemNode(path, true); } + #endif diff --git a/backends/fs/ps2/ps2-fs-factory.h b/backends/fs/ps2/ps2-fs-factory.h index 3a1dec252d..f193982d6b 100644 --- a/backends/fs/ps2/ps2-fs-factory.h +++ b/backends/fs/ps2/ps2-fs-factory.h @@ -39,9 +39,6 @@ public: virtual AbstractFSNode *makeCurrentDirectoryFileNode() const; virtual AbstractFSNode *makeFileNodePath(const Common::String &path) const; -protected: - Ps2FilesystemFactory() {}; - private: friend class Common::Singleton<SingletonBaseType>; }; diff --git a/backends/fs/ps2/ps2-fs.cpp b/backends/fs/ps2/ps2-fs.cpp index 0968ecc9d3..24cc6bd30a 100644 --- a/backends/fs/ps2/ps2-fs.cpp +++ b/backends/fs/ps2/ps2-fs.cpp @@ -22,7 +22,14 @@ * $Id$ */ -#include "backends/fs/abstract-fs.h" +#if defined(__PLAYSTATION2__) + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + + +#include "backends/fs/ps2/ps2-fs.h" + #include <kernel.h> #include <stdio.h> #include <stdlib.h> @@ -40,81 +47,6 @@ extern AsyncFio fio; extern OSystem_PS2 *g_systemPs2; -/** - * Implementation of the ScummVM file system API based on the Ps2SDK. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class Ps2FilesystemNode : public AbstractFSNode { - -friend class Ps2FilesystemFactory; - -protected: - Common::String _displayName; - Common::String _path; - bool _isDirectory; - bool _isRoot; - bool _isHere; - bool _verified; - -private: - const char *getDeviceDescription() const; - void doverify(); - -public: - /** - * Creates a PS2FilesystemNode with the root node as path. - */ - Ps2FilesystemNode(); - - /** - * Creates a PS2FilesystemNode for a given path. - * - * @param path Common::String with the path the new node should point to. - */ - Ps2FilesystemNode(const Common::String &path); - Ps2FilesystemNode(const Common::String &path, bool verify); - - /** - * Copy constructor. - */ - Ps2FilesystemNode(const Ps2FilesystemNode *node); - - virtual Common::String getDisplayName() const { return _displayName; } - virtual Common::String getName() const { return _displayName; } - virtual Common::String getPath() const { return _path; } - - virtual bool exists() const { - // printf("%s : is %d\n", _path.c_str(), _isHere); - return _isHere; - } - - virtual bool isDirectory() const { - // printf("%s : dir %d\n", _path.c_str(), _isDirectory); - return _isDirectory; - } - - virtual bool isReadable() const { - return _isHere; - } - - virtual bool isWritable() const { - if (strncmp(_path.c_str(), "cdfs", 4)==0) - return false; - return true; // exists(); // creating ? - } - - virtual AbstractFSNode *clone() const { return new Ps2FilesystemNode(this); } - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); - - int getDev() { return 0; }; -}; - const char *_lastPathComponent(const Common::String &str) { if (str.empty()) return ""; @@ -502,10 +434,12 @@ const char *Ps2FilesystemNode::getDeviceDescription() const { } Common::SeekableReadStream *Ps2FilesystemNode::createReadStream() { - Common::SeekableReadStream *ss = PS2FileStream::makeFromPath(getPath().c_str(), false); + Common::SeekableReadStream *ss = PS2FileStream::makeFromPath(getPath(), false); return ss; } Common::WriteStream *Ps2FilesystemNode::createWriteStream() { - return PS2FileStream::makeFromPath(getPath().c_str(), true); + return PS2FileStream::makeFromPath(getPath(), true); } + +#endif diff --git a/backends/fs/ps2/ps2-fs.h b/backends/fs/ps2/ps2-fs.h new file mode 100644 index 0000000000..0c37ceeb91 --- /dev/null +++ b/backends/fs/ps2/ps2-fs.h @@ -0,0 +1,105 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef PS2_FILESYSTEM_H +#define PS2_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API based on the Ps2SDK. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class Ps2FilesystemNode : public AbstractFSNode { + +friend class Ps2FilesystemFactory; + +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isRoot; + bool _isHere; + bool _verified; + +private: + const char *getDeviceDescription() const; + void doverify(); + +public: + /** + * Creates a PS2FilesystemNode with the root node as path. + */ + Ps2FilesystemNode(); + + /** + * Creates a PS2FilesystemNode for a given path. + * + * @param path Common::String with the path the new node should point to. + */ + Ps2FilesystemNode(const Common::String &path); + Ps2FilesystemNode(const Common::String &path, bool verify); + + /** + * Copy constructor. + */ + Ps2FilesystemNode(const Ps2FilesystemNode *node); + + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + + virtual bool exists() const { + // printf("%s : is %d\n", _path.c_str(), _isHere); + return _isHere; + } + + virtual bool isDirectory() const { + // printf("%s : dir %d\n", _path.c_str(), _isDirectory); + return _isDirectory; + } + + virtual bool isReadable() const { + return _isHere; + } + + virtual bool isWritable() const { + if (strncmp(_path.c_str(), "cdfs", 4)==0) + return false; + return true; // exists(); // creating ? + } + + virtual AbstractFSNode *clone() const { return new Ps2FilesystemNode(this); } + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); + + int getDev() { return 0; }; +}; + +#endif diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp index 7ed84de034..aee541d12a 100644 --- a/backends/fs/psp/psp-fs-factory.cpp +++ b/backends/fs/psp/psp-fs-factory.cpp @@ -23,8 +23,28 @@ */ #if defined(__PSP__) + +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + #include "backends/fs/psp/psp-fs-factory.h" -#include "backends/fs/psp/psp-fs.cpp" +#include "backends/fs/psp/psp-fs.h" +#include "backends/platform/psp/powerman.h" + +#include <unistd.h> DECLARE_SINGLETON(PSPFilesystemFactory); @@ -34,7 +54,7 @@ AbstractFSNode *PSPFilesystemFactory::makeRootFileNode() const { AbstractFSNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() const { char buf[MAXPATHLEN]; - char * ret = 0; + char *ret = 0; PowerMan.beginCriticalSection(); ret = getcwd(buf, MAXPATHLEN); @@ -46,4 +66,5 @@ AbstractFSNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() const { AbstractFSNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new PSPFilesystemNode(path, true); } + #endif diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp index 16a0e9cd5b..908430b2f9 100644 --- a/backends/fs/psp/psp-fs.cpp +++ b/backends/fs/psp/psp-fs.cpp @@ -22,12 +22,32 @@ * $Id$ */ -#ifdef __PSP__ +#if defined(__PSP__) -#include "engines/engine.h" -#include "backends/fs/abstract-fs.h" +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + +#include "backends/fs/psp/psp-fs.h" #include "backends/fs/psp/psp-stream.h" #include "common/bufferedstream.h" +#include "engines/engine.h" #include <sys/stat.h> #include <unistd.h> @@ -41,48 +61,6 @@ //#define __PSP_DEBUG_PRINT__ /* For debug printouts */ #include "backends/platform/psp/trace.h" -/** - * Implementation of the ScummVM file system API based on PSPSDK API. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class PSPFilesystemNode : public AbstractFSNode { -protected: - Common::String _displayName; - Common::String _path; - bool _isDirectory; - bool _isValid; - -public: - /** - * Creates a PSPFilesystemNode with the root node as path. - */ - PSPFilesystemNode(); - - /** - * Creates a PSPFilesystemNode for a given path. - * - * @param path Common::String with the path the new node should point to. - * @param verify true if the isValid and isDirectory flags should be verified during the construction. - */ - PSPFilesystemNode(const Common::String &p, bool verify = true); - - virtual bool exists() const; - virtual Common::String getDisplayName() const { return _displayName; } - virtual Common::String getName() const { return _displayName; } - virtual Common::String getPath() const { return _path; } - virtual bool isDirectory() const { return _isDirectory; } - virtual bool isReadable() const; - virtual bool isWritable() const; - - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); -}; - PSPFilesystemNode::PSPFilesystemNode() { _isDirectory = true; _displayName = "Root"; diff --git a/backends/fs/psp/psp-fs.h b/backends/fs/psp/psp-fs.h new file mode 100644 index 0000000000..12d2c540c0 --- /dev/null +++ b/backends/fs/psp/psp-fs.h @@ -0,0 +1,72 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef PSP_FILESYSTEM_H +#define PSP_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API based on PSPSDK API. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class PSPFilesystemNode : public AbstractFSNode { +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isValid; + +public: + /** + * Creates a PSPFilesystemNode with the root node as path. + */ + PSPFilesystemNode(); + + /** + * Creates a PSPFilesystemNode for a given path. + * + * @param path Common::String with the path the new node should point to. + * @param verify true if the isValid and isDirectory flags should be verified during the construction. + */ + PSPFilesystemNode(const Common::String &p, bool verify = true); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + virtual bool isDirectory() const { return _isDirectory; } + virtual bool isReadable() const; + virtual bool isWritable() const; + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); +}; + +#endif diff --git a/backends/fs/symbian/symbian-fs-factory.cpp b/backends/fs/symbian/symbian-fs-factory.cpp index c70a67f339..9afacfebf5 100644 --- a/backends/fs/symbian/symbian-fs-factory.cpp +++ b/backends/fs/symbian/symbian-fs-factory.cpp @@ -24,7 +24,7 @@ #if defined(__SYMBIAN32__) #include "backends/fs/symbian/symbian-fs-factory.h" -#include "backends/fs/symbian/symbian-fs.cpp" +#include "backends/fs/symbian/symbian-fs.h" AbstractFSNode *SymbianFilesystemFactory::makeRootFileNode() const { return new SymbianFilesystemNode(true); diff --git a/backends/fs/symbian/symbian-fs.cpp b/backends/fs/symbian/symbian-fs.cpp index 5d4951e269..b8fc5e19f6 100644 --- a/backends/fs/symbian/symbian-fs.cpp +++ b/backends/fs/symbian/symbian-fs.cpp @@ -23,7 +23,8 @@ */ #if defined (__SYMBIAN32__) -#include "backends/fs/abstract-fs.h" + +#include "backends/fs/symbian/symbian-fs.h" #include "backends/fs/symbian/symbianstream.h" #include "backends/platform/symbian/src/symbianos.h" @@ -35,66 +36,11 @@ #define KDriveLabelSize 30 /** - * Implementation of the ScummVM file system API based on POSIX. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class SymbianFilesystemNode : public AbstractFSNode { -protected: - Common::String _displayName; - Common::String _path; - TBool _isDirectory; - TBool _isValid; - TBool _isPseudoRoot; -public: - /** - * Creates a SymbianFilesystemNode with the root node as path. - * - * @param aIsRoot true if the node will be a pseudo root, false otherwise. - */ - SymbianFilesystemNode(bool aIsRoot); - - /** - * Creates a SymbianFilesystemNode for a given path. - * - * @param path Common::String with the path the new node should point to. - */ - SymbianFilesystemNode(const Common::String &path); - - virtual bool exists() const { - TFileName fname; - TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size()); - fname.Copy(ptr); - TBool fileExists = BaflUtils::FileExists(static_cast<OSystem_SDL_Symbian*> (g_system)->FsSession(), fname); - if (!fileExists) { - TParsePtrC parser(fname); - if (parser.PathPresent() && parser.Path().Compare(_L("\\")) == KErrNone && !parser.NameOrExtPresent()) { - fileExists = ETrue; - } - } - return fileExists; - } - virtual Common::String getDisplayName() const { return _displayName; } - virtual Common::String getName() const { return _displayName; } - virtual Common::String getPath() const { return _path; } - virtual bool isDirectory() const { return _isDirectory; } - virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } //FIXME: this is just a stub - virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } //FIXME: this is just a stub - - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); -}; - -/** * Fixes the path by changing all slashes to backslashes. * * @param path Common::String with the path to be fixed. */ -static void fixFilePath(Common::String& aPath){ +static void fixFilePath(Common::String &aPath){ TInt len = aPath.size(); for (TInt index = 0; index < len; index++) { @@ -106,18 +52,15 @@ static void fixFilePath(Common::String& aPath){ SymbianFilesystemNode::SymbianFilesystemNode(bool aIsRoot) { _path = ""; - _isValid = ETrue; - _isDirectory = ETrue; + _isValid = true; + _isDirectory = true; _isPseudoRoot = aIsRoot; _displayName = "Root"; } SymbianFilesystemNode::SymbianFilesystemNode(const Common::String &path) { - if (path.size() == 0) - _isPseudoRoot = ETrue; - else - _isPseudoRoot = EFalse; + _isPseudoRoot = path.empty(); _path = path; @@ -131,18 +74,41 @@ SymbianFilesystemNode::SymbianFilesystemNode(const Common::String &path) { fname.Copy(ptr); if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().Entry(fname, fileAttribs) == KErrNone) { - _isValid = ETrue; + _isValid = true; _isDirectory = fileAttribs.IsDir(); } else { - _isValid = ETrue; - _isDirectory = EFalse; + _isValid = true; + _isDirectory = false; TParsePtrC parser(fname); if (parser.PathPresent() && parser.Path().Compare(_L("\\")) == KErrNone && !parser.NameOrExtPresent()) { - _isDirectory = ETrue; + _isDirectory = true; } } } +bool SymbianFilesystemNode::exists() const { + TFileName fname; + TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size()); + fname.Copy(ptr); + bool fileExists = BaflUtils::FileExists(static_cast<OSystem_SDL_Symbian*> (g_system)->FsSession(), fname); + if (!fileExists) { + TParsePtrC parser(fname); + if (parser.PathPresent() && parser.Path().Compare(_L("\\")) == KErrNone && !parser.NameOrExtPresent()) { + fileExists = true; + } + } + return fileExists; +} + +bool SymbianFilesystemNode::isReadable() const { + return access(_path.c_str(), R_OK) == 0; +} + +bool SymbianFilesystemNode::isWritable() const { + return access(_path.c_str(), W_OK) == 0; +} + + AbstractFSNode *SymbianFilesystemNode::getChild(const Common::String &n) const { assert(_isDirectory); Common::String newPath(_path); @@ -191,9 +157,9 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b SymbianFilesystemNode entry(false); entry._displayName = (char*) driveString8.PtrZ(); // drive_name - entry._isDirectory = ETrue; - entry._isValid = ETrue; - entry._isPseudoRoot = EFalse; + entry._isDirectory = true; + entry._isValid = true; + entry._isPseudoRoot = false; entry._path = path; myList.push_back(new SymbianFilesystemNode(entry)); } @@ -209,20 +175,20 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().GetDir(fname, KEntryAttNormal|KEntryAttDir, 0, dirPtr) == KErrNone) { CleanupStack::PushL(dirPtr); - TInt cnt=dirPtr->Count(); - for (TInt loop=0;loop<cnt;loop++) { - TEntry fileentry=(*dirPtr)[loop]; + TInt cnt = dirPtr->Count(); + for (TInt loop = 0; loop < cnt; loop++) { + TEntry fileentry = (*dirPtr)[loop]; nameBuf.Copy(fileentry.iName); - SymbianFilesystemNode entry(EFalse); - entry._isPseudoRoot = EFalse; + SymbianFilesystemNode entry(false); + entry._isPseudoRoot = false; - entry._displayName =(char*) nameBuf.PtrZ(); + entry._displayName =(char *)nameBuf.PtrZ(); entry._path = _path; if (entry._path.lastChar() != '\\') entry._path+= '\\'; - entry._path +=(char*) nameBuf.PtrZ(); + entry._path +=(char *)nameBuf.PtrZ(); entry._isDirectory = fileentry.IsDir(); // Honor the chosen mode @@ -245,29 +211,27 @@ AbstractFSNode *SymbianFilesystemNode::getParent() const { // Root node is its own parent. Still we can't just return this // as the GUI code will call delete on the old node. if (!_isPseudoRoot && _path.size() > 3) { - p = new SymbianFilesystemNode(EFalse); + p = new SymbianFilesystemNode(false); const char *start = _path.c_str(); const char *end = lastPathComponent(_path, '\\'); p->_path = Common::String(start, end - start); - p->_isValid = ETrue; - p->_isDirectory = ETrue; + p->_isValid = true; + p->_isDirectory = true; p->_displayName = lastPathComponent(p->_path, '\\'); - } - else - { - p = new SymbianFilesystemNode(ETrue); + } else { + p = new SymbianFilesystemNode(true); } return p; } Common::SeekableReadStream *SymbianFilesystemNode::createReadStream() { - return SymbianStdioStream::makeFromPath(getPath().c_str(), false); + return SymbianStdioStream::makeFromPath(getPath(), false); } Common::WriteStream *SymbianFilesystemNode::createWriteStream() { - return SymbianStdioStream::makeFromPath(getPath().c_str(), true); + return SymbianStdioStream::makeFromPath(getPath(), true); } #endif //#if defined (__SYMBIAN32__) diff --git a/backends/fs/symbian/symbian-fs.h b/backends/fs/symbian/symbian-fs.h new file mode 100644 index 0000000000..9b0e80c3d6 --- /dev/null +++ b/backends/fs/symbian/symbian-fs.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef SYMBIAN_FILESYSTEM_H +#define SYMBIAN_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API based on POSIX. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class SymbianFilesystemNode : public AbstractFSNode { +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isValid; + bool _isPseudoRoot; +public: + /** + * Creates a SymbianFilesystemNode with the root node as path. + * + * @param aIsRoot true if the node will be a pseudo root, false otherwise. + */ + SymbianFilesystemNode(bool aIsRoot); + + /** + * Creates a SymbianFilesystemNode for a given path. + * + * @param path Common::String with the path the new node should point to. + */ + SymbianFilesystemNode(const Common::String &path); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + virtual bool isDirectory() const { return _isDirectory; } + virtual bool isReadable() const; + virtual bool isWritable() const; + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); +}; + +#endif diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp index 6a11d7d12e..34cde8ef46 100644 --- a/backends/fs/wii/wii-fs-factory.cpp +++ b/backends/fs/wii/wii-fs-factory.cpp @@ -22,10 +22,13 @@ #if defined(__WII__) +#define FORBIDDEN_SYMBOL_EXCEPTION_printf +#define FORBIDDEN_SYMBOL_EXCEPTION_getcwd + #include <unistd.h> #include "backends/fs/wii/wii-fs-factory.h" -#include "backends/fs/wii/wii-fs.cpp" +#include "backends/fs/wii/wii-fs.h" #ifdef USE_WII_DI #include <di/di.h> diff --git a/backends/fs/wii/wii-fs.cpp b/backends/fs/wii/wii-fs.cpp index e6ba2a4aa0..eb631df1bf 100644 --- a/backends/fs/wii/wii-fs.cpp +++ b/backends/fs/wii/wii-fs.cpp @@ -22,7 +22,13 @@ #if defined(__WII__) -#include "backends/fs/abstract-fs.h" +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + +#include "backends/fs/wii/wii-fs.h" +#include "backends/fs/wii/wii-fs-factory.h" #include "backends/fs/stdiostream.h" #include <sys/iosupport.h> @@ -34,52 +40,6 @@ #include <gctypes.h> -/** - * Implementation of the ScummVM file system API based on Wii. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class WiiFilesystemNode : public AbstractFSNode { -protected: - Common::String _displayName; - Common::String _path; - bool _exists, _isDirectory, _isReadable, _isWritable; - - virtual void initRootNode(); - virtual bool getDevopChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual void setFlags(const struct stat *st); - virtual void clearFlags(); - -public: - /** - * Creates a WiiFilesystemNode with the root node as path. - */ - WiiFilesystemNode(); - - /** - * Creates a WiiFilesystemNode for a given path. - * - * @param path Common::String with the path the new node should point to. - */ - WiiFilesystemNode(const Common::String &path); - WiiFilesystemNode(const Common::String &p, const struct stat *st); - - virtual bool exists() const; - virtual Common::String getDisplayName() const { return _displayName; } - virtual Common::String getName() const { return _displayName; } - virtual Common::String getPath() const { return _path; } - virtual bool isDirectory() const { return _isDirectory; } - virtual bool isReadable() const { return _isReadable; } - virtual bool isWritable() const { return _isWritable; } - - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); -}; - // gets all registered devoptab devices bool WiiFilesystemNode::getDevopChildren(AbstractFSList &list, ListMode mode, bool hidden) const { u8 i; @@ -234,11 +194,11 @@ AbstractFSNode *WiiFilesystemNode::getParent() const { } Common::SeekableReadStream *WiiFilesystemNode::createReadStream() { - return StdioStream::makeFromPath(getPath().c_str(), false); + return StdioStream::makeFromPath(getPath(), false); } Common::WriteStream *WiiFilesystemNode::createWriteStream() { - return StdioStream::makeFromPath(getPath().c_str(), true); + return StdioStream::makeFromPath(getPath(), true); } #endif //#if defined(__WII__) diff --git a/backends/fs/wii/wii-fs.h b/backends/fs/wii/wii-fs.h new file mode 100644 index 0000000000..fd160624ca --- /dev/null +++ b/backends/fs/wii/wii-fs.h @@ -0,0 +1,76 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef WII_FILESYSTEM_H +#define WII_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API based on Wii. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class WiiFilesystemNode : public AbstractFSNode { +protected: + Common::String _displayName; + Common::String _path; + bool _exists, _isDirectory, _isReadable, _isWritable; + + virtual void initRootNode(); + virtual bool getDevopChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual void setFlags(const struct stat *st); + virtual void clearFlags(); + +public: + /** + * Creates a WiiFilesystemNode with the root node as path. + */ + WiiFilesystemNode(); + + /** + * Creates a WiiFilesystemNode for a given path. + * + * @param path Common::String with the path the new node should point to. + */ + WiiFilesystemNode(const Common::String &path); + WiiFilesystemNode(const Common::String &p, const struct stat *st); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + virtual bool isDirectory() const { return _isDirectory; } + virtual bool isReadable() const { return _isReadable; } + virtual bool isWritable() const { return _isWritable; } + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); +}; + +#endif diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp index ae9485a121..0b240bcbcf 100644 --- a/backends/fs/windows/windows-fs-factory.cpp +++ b/backends/fs/windows/windows-fs-factory.cpp @@ -22,13 +22,13 @@ * $Id$ */ +#if defined(WIN32) + // Disable symbol overrides so that we can use system headers. #define FORBIDDEN_SYMBOL_ALLOW_ALL -#if defined(WIN32) - #include "backends/fs/windows/windows-fs-factory.h" -#include "backends/fs/windows/windows-fs.cpp" +#include "backends/fs/windows/windows-fs.h" AbstractFSNode *WindowsFilesystemFactory::makeRootFileNode() const { return new WindowsFilesystemNode(); diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp index 00f72773c3..8345c9d7b4 100644 --- a/backends/fs/windows/windows-fs.cpp +++ b/backends/fs/windows/windows-fs.cpp @@ -22,23 +22,13 @@ * $Id$ */ -#ifdef WIN32 +#if defined(WIN32) -#if defined(ARRAYSIZE) -#undef ARRAYSIZE -#endif -#include <windows.h> -// winnt.h defines ARRAYSIZE, but we want our own one... -#undef ARRAYSIZE -#ifdef _WIN32_WCE -#undef GetCurrentDirectory -#endif -#include "backends/fs/abstract-fs.h" +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/fs/windows/windows-fs.h" #include "backends/fs/stdiostream.h" -#include <io.h> -#include <stdio.h> -#include <stdlib.h> -#include <tchar.h> // F_OK, R_OK and W_OK are not defined under MSVC, so we define them here // For more information on the modes used by MSVC, check: @@ -55,84 +45,17 @@ #define W_OK 2 #endif -/** - * Implementation of the ScummVM file system API based on Windows API. - * - * Parts of this class are documented in the base interface class, AbstractFSNode. - */ -class WindowsFilesystemNode : public AbstractFSNode { -protected: - Common::String _displayName; - Common::String _path; - bool _isDirectory; - bool _isPseudoRoot; - bool _isValid; - -public: - /** - * Creates a WindowsFilesystemNode with the root node as path. - * - * In regular windows systems, a virtual root path is used "". - * In windows CE, the "\" root is used instead. - */ - WindowsFilesystemNode(); - - /** - * Creates a WindowsFilesystemNode for a given path. - * - * Examples: - * path=c:\foo\bar.txt, currentDir=false -> c:\foo\bar.txt - * path=c:\foo\bar.txt, currentDir=true -> current directory - * path=NULL, currentDir=true -> current directory - * - * @param path Common::String with the path the new node should point to. - * @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory. - */ - WindowsFilesystemNode(const Common::String &path, const bool currentDir); - - virtual bool exists() const { return _access(_path.c_str(), F_OK) == 0; } - virtual Common::String getDisplayName() const { return _displayName; } - virtual Common::String getName() const { return _displayName; } - virtual Common::String getPath() const { return _path; } - virtual bool isDirectory() const { return _isDirectory; } - virtual bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; } - virtual bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; } - - virtual AbstractFSNode *getChild(const Common::String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFSNode *getParent() const; - - virtual Common::SeekableReadStream *createReadStream(); - virtual Common::WriteStream *createWriteStream(); - -private: - /** - * Adds a single WindowsFilesystemNode to a given list. - * This method is used by getChildren() to populate the directory entries list. - * - * @param list List to put the file entry node in. - * @param mode Mode to use while adding the file entry to the list. - * @param base Common::String with the directory being listed. - * @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find. - */ - static void addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data); - - /** - * Converts a Unicode string to Ascii format. - * - * @param str Common::String to convert from Unicode to Ascii. - * @return str in Ascii format. - */ - static char *toAscii(TCHAR *str); - - /** - * Converts an Ascii string to Unicode format. - * - * @param str Common::String to convert from Ascii to Unicode. - * @return str in Unicode format. - */ - static const TCHAR* toUnicode(const char *str); -}; +bool WindowsFilesystemNode::exists() const { + return _access(_path.c_str(), F_OK) == 0; +} + +bool WindowsFilesystemNode::isReadable() const { + return _access(_path.c_str(), R_OK) == 0; +} + +bool WindowsFilesystemNode::isWritable() const { + return _access(_path.c_str(), W_OK) == 0; +} void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) { WindowsFilesystemNode entry; @@ -314,11 +237,11 @@ AbstractFSNode *WindowsFilesystemNode::getParent() const { } Common::SeekableReadStream *WindowsFilesystemNode::createReadStream() { - return StdioStream::makeFromPath(getPath().c_str(), false); + return StdioStream::makeFromPath(getPath(), false); } Common::WriteStream *WindowsFilesystemNode::createWriteStream() { - return StdioStream::makeFromPath(getPath().c_str(), true); + return StdioStream::makeFromPath(getPath(), true); } #endif //#ifdef WIN32 diff --git a/backends/fs/windows/windows-fs.h b/backends/fs/windows/windows-fs.h new file mode 100644 index 0000000000..8e4880ce23 --- /dev/null +++ b/backends/fs/windows/windows-fs.h @@ -0,0 +1,123 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef WINDOWS_FILESYSTEM_H +#define WINDOWS_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +#if defined(ARRAYSIZE) +#undef ARRAYSIZE +#endif +#include <windows.h> +// winnt.h defines ARRAYSIZE, but we want our own one... +#undef ARRAYSIZE +#ifdef _WIN32_WCE +#undef GetCurrentDirectory +#endif +#include <io.h> +#include <stdio.h> +#include <stdlib.h> +#include <tchar.h> + +/** + * Implementation of the ScummVM file system API based on Windows API. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class WindowsFilesystemNode : public AbstractFSNode { +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isPseudoRoot; + bool _isValid; + +public: + /** + * Creates a WindowsFilesystemNode with the root node as path. + * + * In regular windows systems, a virtual root path is used "". + * In windows CE, the "\" root is used instead. + */ + WindowsFilesystemNode(); + + /** + * Creates a WindowsFilesystemNode for a given path. + * + * Examples: + * path=c:\foo\bar.txt, currentDir=false -> c:\foo\bar.txt + * path=c:\foo\bar.txt, currentDir=true -> current directory + * path=NULL, currentDir=true -> current directory + * + * @param path Common::String with the path the new node should point to. + * @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory. + */ + WindowsFilesystemNode(const Common::String &path, const bool currentDir); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + virtual bool isDirectory() const { return _isDirectory; } + virtual bool isReadable() const; + virtual bool isWritable() const; + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); + +private: + /** + * Adds a single WindowsFilesystemNode to a given list. + * This method is used by getChildren() to populate the directory entries list. + * + * @param list List to put the file entry node in. + * @param mode Mode to use while adding the file entry to the list. + * @param base Common::String with the directory being listed. + * @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find. + */ + static void addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data); + + /** + * Converts a Unicode string to Ascii format. + * + * @param str Common::String to convert from Unicode to Ascii. + * @return str in Ascii format. + */ + static char *toAscii(TCHAR *str); + + /** + * Converts an Ascii string to Unicode format. + * + * @param str Common::String to convert from Ascii to Unicode. + * @return str in Unicode format. + */ + static const TCHAR* toUnicode(const char *str); +}; + +#endif diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp index 3c043ca986..4e2aee3a3b 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp @@ -31,6 +31,7 @@ #include "backends/events/dinguxsdl/dinguxsdl-events.h" #include "graphics/scaler/aspect.h" #include "common/mutex.h" +#include "common/textconsole.h" static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {"1x", "Standard", GFX_NORMAL}, @@ -437,14 +438,14 @@ bool DINGUXSdlGraphicsManager::loadGFXMode() { _videoMode.aspectRatioCorrection = false; } - fprintf(stdout, "Game ScreenMode = %d*%d\n", _videoMode.screenWidth, _videoMode.screenHeight); + debug("Game ScreenMode = %d*%d", _videoMode.screenWidth, _videoMode.screenHeight); if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) { _videoMode.aspectRatioCorrection = false; setGraphicsMode(GFX_HALF); - fprintf(stdout, "GraphicsMode set to HALF\n"); + debug("GraphicsMode set to HALF"); } else { setGraphicsMode(GFX_NORMAL); - fprintf(stdout, "GraphicsMode set to NORMAL\n"); + debug("GraphicsMode set to NORMAL"); } if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) { diff --git a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp index 75a1f17674..6e5a35a1b1 100644 --- a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp +++ b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp @@ -18,14 +18,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "common/scummsys.h" -#ifdef GP2X +#if defined(GP2X_OLD) #include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" #include "graphics/scaler/aspect.h" diff --git a/backends/platform/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp index 8fada7e40a..b407bf1faf 100644 --- a/backends/platform/gph/gph-graphics.cpp +++ b/backends/graphics/gph/gph-graphics.cpp @@ -18,35 +18,36 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ -#include "backends/platform/gph/gph-sdl.h" +#include "common/scummsys.h" -#include "common/mutex.h" -#include "graphics/font.h" -#include "graphics/fontman.h" -#include "graphics/scaler.h" +#if defined(GPH_DEVICE) + +#include "backends/graphics/gph/gph-graphics.h" +#include "backends/events/gph/gph-events.h" #include "graphics/scaler/aspect.h" -#include "graphics/scaler/downscaler.h" -#include "graphics/surface.h" +#include "common/mutex.h" +#include "common/textconsole.h" static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"1x", "Fullscreen", GFX_NORMAL}, + {"1x", "Standard", GFX_NORMAL}, {0, 0, 0} }; -const OSystem::GraphicsMode *OSystem_GPH::getSupportedGraphicsModes() const { +GPHGraphicsManager::GPHGraphicsManager(SdlEventSource *boss) + : SdlGraphicsManager(boss) { +} + +const OSystem::GraphicsMode *GPHGraphicsManager::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } -int OSystem_GPH::getDefaultGraphicsMode() const { +int GPHGraphicsManager::getDefaultGraphicsMode() const { return GFX_NORMAL; } -bool OSystem_GPH::setGraphicsMode(int mode) { +bool GPHGraphicsManager::setGraphicsMode(int mode) { Common::StackLock lock(_graphicsMutex); assert(_transactionMode == kTransactionActive); @@ -80,7 +81,7 @@ bool OSystem_GPH::setGraphicsMode(int mode) { return true; } -void OSystem_GPH::setGraphicsModeIntern() { +void GPHGraphicsManager::setGraphicsModeIntern() { Common::StackLock lock(_graphicsMutex); ScalerProc *newScalerProc = 0; @@ -109,7 +110,7 @@ void OSystem_GPH::setGraphicsModeIntern() { blitCursor(); } -void OSystem_GPH::initSize(uint w, uint h) { +void GPHGraphicsManager::initSize(uint w, uint h) { assert(_transactionMode == kTransactionActive); // Avoid redundant res changes @@ -121,41 +122,13 @@ void OSystem_GPH::initSize(uint w, uint h) { if (w > 320 || h > 240){ setGraphicsMode(GFX_HALF); setGraphicsModeIntern(); - toggleMouseGrab(); + _sdlEventSource->toggleMouseGrab(); } _transactionDetails.sizeChanged = true; } -bool OSystem_GPH::loadGFXMode() { - if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) { - _videoMode.aspectRatioCorrection = false; - setGraphicsMode(GFX_HALF); - printf("GFX_HALF\n"); - } else { - setGraphicsMode(GFX_NORMAL); - printf("GFX_NORMAL\n"); - } - - if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) { - _videoMode.overlayWidth = _videoMode.screenWidth / 2; - _videoMode.overlayHeight = _videoMode.screenHeight / 2; - _videoMode.fullscreen = true; - } else { - - _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; - - if (_videoMode.aspectRatioCorrection) - _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); - - _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.hardwareHeight = effectiveScreenHeight(); - } - return OSystem_SDL::loadGFXMode(); -} - -void OSystem_GPH::drawMouse() { +void GPHGraphicsManager::drawMouse() { if (!_mouseVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; @@ -226,7 +199,7 @@ void OSystem_GPH::drawMouse() { addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); } -void OSystem_GPH::undrawMouse() { +void GPHGraphicsManager::undrawMouse() { const int x = _mouseBackup.x; const int y = _mouseBackup.y; @@ -244,7 +217,7 @@ void OSystem_GPH::undrawMouse() { } } -void OSystem_GPH::internUpdateScreen() { +void GPHGraphicsManager::internUpdateScreen() { SDL_Surface *srcSurf, *origSurf; int height, width; ScalerProc *scalerProc; @@ -443,28 +416,124 @@ void OSystem_GPH::internUpdateScreen() { _mouseNeedsRedraw = false; } -void OSystem_GPH::showOverlay() { +void GPHGraphicsManager::showOverlay() { if (_videoMode.mode == GFX_HALF){ _mouseCurState.x = _mouseCurState.x / 2; _mouseCurState.y = _mouseCurState.y / 2; } - OSystem_SDL::showOverlay(); + SdlGraphicsManager::showOverlay(); } -void OSystem_GPH::hideOverlay() { +void GPHGraphicsManager::hideOverlay() { if (_videoMode.mode == GFX_HALF){ _mouseCurState.x = _mouseCurState.x * 2; _mouseCurState.y = _mouseCurState.y * 2; } - OSystem_SDL::hideOverlay(); + SdlGraphicsManager::hideOverlay(); } -void OSystem_GPH::warpMouse(int x, int y) { + +bool GPHGraphicsManager::loadGFXMode() { + + /* Forcefully disable aspect ratio correction for games + that start with a native 240px height resolution + This corrects games with non-standard resolutions + such as MM Nes (256x240). + */ + + if(_videoMode.screenHeight == 240) { + _videoMode.aspectRatioCorrection = false; + } + + debug("Game ScreenMode = %d*%d", _videoMode.screenWidth, _videoMode.screenHeight); + if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) { + _videoMode.aspectRatioCorrection = false; + setGraphicsMode(GFX_HALF); + debug("GraphicsMode set to HALF"); + } else { + setGraphicsMode(GFX_NORMAL); + debug("GraphicsMode set to NORMAL"); + } + + if ((_videoMode.mode == GFX_HALF) && !_overlayVisible) { + _videoMode.overlayWidth = _videoMode.screenWidth / 2; + _videoMode.overlayHeight = _videoMode.screenHeight / 2; + _videoMode.fullscreen = true; + } else { + + _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; + _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; + + if (_videoMode.aspectRatioCorrection) + _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); + + _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; + _videoMode.hardwareHeight = effectiveScreenHeight(); + } + return SdlGraphicsManager::loadGFXMode(); +} + +bool GPHGraphicsManager::hasFeature(OSystem::Feature f) { + return + (f == OSystem::kFeatureAspectRatioCorrection) || + (f == OSystem::kFeatureCursorHasPalette); +} + +void GPHGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + setAspectRatioCorrection(enable); + break; + default: + break; + } +} + +bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) { + assert(_transactionMode == kTransactionNone); + + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + return _videoMode.aspectRatioCorrection; + default: + return false; + } +} + +SdlGraphicsManager::MousePos* GPHGraphicsManager::getMouseCurState() { + return &_mouseCurState; +} + +SdlGraphicsManager::VideoState* GPHGraphicsManager::getVideoMode() { + return &_videoMode; +} + +void GPHGraphicsManager::warpMouse(int x, int y) { if (_mouseCurState.x != x || _mouseCurState.y != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible){ x = x / 2; y = y / 2; } } - OSystem_SDL::warpMouse(x, y); + SdlGraphicsManager::warpMouse(x, y); +} + +void GPHGraphicsManager::adjustMouseEvent(const Common::Event &event) { + if (!event.synthetic) { + Common::Event newEvent(event); + newEvent.synthetic = true; + if (!_overlayVisible) { + if (_videoMode.mode == GFX_HALF) { + newEvent.mouse.x *= 2; + newEvent.mouse.y *= 2; + } + newEvent.mouse.x /= _videoMode.scaleFactor; + newEvent.mouse.y /= _videoMode.scaleFactor; + if (_videoMode.aspectRatioCorrection) + newEvent.mouse.y = aspect2Real(newEvent.mouse.y); + } + g_system->getEventManager()->pushEvent(newEvent); + } } + +#endif diff --git a/backends/graphics/gph/gph-graphics.h b/backends/graphics/gph/gph-graphics.h new file mode 100644 index 0000000000..6ba2b344a6 --- /dev/null +++ b/backends/graphics/gph/gph-graphics.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_GPH_H +#define BACKENDS_GRAPHICS_GPH_H + +#include "backends/graphics/sdl/sdl-graphics.h" +#include "graphics/scaler/aspect.h" // for aspect2Real +#include "graphics/scaler/downscaler.h" + +enum { + GFX_HALF = 12 +}; + +class GPHGraphicsManager : public SdlGraphicsManager { +public: + GPHGraphicsManager(SdlEventSource *boss); + + bool hasFeature(OSystem::Feature f); + void setFeatureState(OSystem::Feature f, bool enable); + bool getFeatureState(OSystem::Feature f); + int getDefaultGraphicsMode() const; + + void initSize(uint w, uint h); + const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + bool setGraphicsMode(const char *name); + bool setGraphicsMode(int mode); + void setGraphicsModeIntern(); + void internUpdateScreen(); + void showOverlay(); + void hideOverlay(); + bool loadGFXMode(); + void drawMouse(); + void undrawMouse(); + virtual void warpMouse(int x, int y); + + SdlGraphicsManager::MousePos *getMouseCurState(); + SdlGraphicsManager::VideoState *getVideoMode(); + + virtual void adjustMouseEvent(const Common::Event &event); +}; + +#endif /* BACKENDS_GRAPHICS_GPH_H */ diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp index c2dcb7f587..7d1809f4ac 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp @@ -30,6 +30,7 @@ #include "backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h" #include "backends/events/linuxmotosdl/linuxmotosdl-events.h" #include "common/mutex.h" +#include "common/textconsole.h" #include "graphics/font.h" #include "graphics/fontman.h" #include "graphics/scaler.h" @@ -143,14 +144,14 @@ void LinuxmotoSdlGraphicsManager::initSize(uint w, uint h) { } bool LinuxmotoSdlGraphicsManager::loadGFXMode() { - printf("Game ScreenMode = %d*%d\n",_videoMode.screenWidth, _videoMode.screenHeight); + debug("Game ScreenMode = %d*%d",_videoMode.screenWidth, _videoMode.screenHeight); if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) { _videoMode.aspectRatioCorrection = false; setGraphicsMode(GFX_HALF); - printf("GraphicsMode set to HALF\n"); + debug("GraphicsMode set to HALF"); } else { setGraphicsMode(GFX_NORMAL); - printf("GraphicsMode set to NORMAL\n"); + debug("GraphicsMode set to NORMAL"); } if (_videoMode.mode == GFX_HALF && !_overlayVisible) { _videoMode.overlayWidth = 320; diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp index cd9e23cb71..7b7d40f174 100644 --- a/backends/graphics/opengl/gltexture.cpp +++ b/backends/graphics/opengl/gltexture.cpp @@ -149,7 +149,7 @@ void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLu glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR(); // Check if the buffer has its data contiguously - if (static_cast<int>(w) * _bytesPerPixel == pitch && w == _textureWidth) { + if (static_cast<int>(w) * _bytesPerPixel == pitch) { glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, _glFormat, _glType, buf); CHECK_GL_ERROR(); } else { diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h index e7951a0c96..238b035425 100644 --- a/backends/graphics/opengl/gltexture.h +++ b/backends/graphics/opengl/gltexture.h @@ -42,9 +42,6 @@ #include "graphics/surface.h" -#include "common/rect.h" -#include "common/array.h" - /** * OpenGL texture manager class */ diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index beac2f6d3e..b85cac809e 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -32,7 +32,11 @@ #include "common/config-manager.h" #include "common/file.h" #include "common/mutex.h" +#include "common/textconsole.h" #include "common/translation.h" +#ifdef USE_OSD +#include "common/tokenizer.h" +#endif #include "graphics/font.h" #include "graphics/fontman.h" @@ -50,8 +54,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _cursorVisible(false), _cursorKeyColor(0), _cursorTargetScale(1), _formatBGR(false), - _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0), - _aspectRatioCorrection(false) { + _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0) { memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); memset(&_videoMode, 0, sizeof(_videoMode)); @@ -96,17 +99,31 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { switch (f) { + case OSystem::kFeatureFullscreenMode: + setFullscreenMode(enable); + break; + case OSystem::kFeatureAspectRatioCorrection: - _videoMode.mode = OpenGL::GFX_4_3; - _aspectRatioCorrection = enable; + _videoMode.aspectRatioCorrection = enable; + _transactionDetails.needRefresh = true; break; + default: break; } } bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { - return false; + switch (f) { + case OSystem::kFeatureFullscreenMode: + return _videoMode.fullscreen; + + case OSystem::kFeatureAspectRatioCorrection: + return _videoMode.aspectRatioCorrection; + + default: + return false; + } } // @@ -116,7 +133,6 @@ bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {"gl1", _s("OpenGL Normal"), OpenGL::GFX_NORMAL}, {"gl2", _s("OpenGL Conserve"), OpenGL::GFX_CONSERVE}, - {"gl3", _s("OpenGL 4/3"), OpenGL::GFX_4_3}, {"gl4", _s("OpenGL Original"), OpenGL::GFX_ORIGINAL}, {0, 0, 0} }; @@ -136,17 +152,18 @@ int OpenGLGraphicsManager::getDefaultGraphicsMode() const { bool OpenGLGraphicsManager::setGraphicsMode(int mode) { assert(_transactionMode == kTransactionActive); + setScale(2); + if (_oldVideoMode.setup && _oldVideoMode.mode == mode) return true; switch (mode) { case OpenGL::GFX_NORMAL: case OpenGL::GFX_CONSERVE: - case OpenGL::GFX_4_3: case OpenGL::GFX_ORIGINAL: break; default: - warning("unknown gfx mode %d", mode); + warning("Unknown gfx mode %d", mode); return false; } @@ -166,11 +183,9 @@ void OpenGLGraphicsManager::resetGraphicsScale() { } #ifdef USE_RGB_COLOR - Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const { return _screenFormat; } - #endif void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) { @@ -308,7 +323,7 @@ int16 OpenGLGraphicsManager::getWidth() { void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { assert(colors); - + #ifdef USE_RGB_COLOR assert(_screenFormat.bytesPerPixel == 1); #endif @@ -324,7 +339,7 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { assert(colors); - + #ifdef USE_RGB_COLOR assert(_screenFormat.bytesPerPixel == 1); #endif @@ -341,9 +356,9 @@ void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, // Copy buffer data to game screen internal buffer const byte *src = buf; - byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch; + byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch + x * _screenData.format.bytesPerPixel; for (int i = 0; i < h; i++) { - memcpy(dst + x * _screenData.bytesPerPixel, src, w * _screenData.bytesPerPixel); + memcpy(dst, src, w * _screenData.format.bytesPerPixel); src += pitch; dst += _screenData.pitch; } @@ -367,6 +382,7 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) { if (_gameTexture == NULL) return; +#ifdef USE_RGB_COLOR if (_screenFormat.bytesPerPixel == 1) { memset(_screenData.pixels, col, _screenData.h * _screenData.pitch); } else if (_screenFormat.bytesPerPixel == 2) { @@ -392,7 +408,9 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) { pixels[i] = col; } } - +#else + memset(_screenData.pixels, col, _screenData.h * _screenData.pitch); +#endif _screenNeedsRedraw = true; } @@ -449,7 +467,7 @@ void OpenGLGraphicsManager::clearOverlay() { } void OpenGLGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) { - assert(_overlayData.bytesPerPixel == sizeof(buf[0])); + assert(_overlayData.format.bytesPerPixel == sizeof(buf[0])); const byte *src = (byte *)_overlayData.pixels; for (int i = 0; i < _overlayData.h; i++) { // Copy overlay data to buffer @@ -502,7 +520,7 @@ void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch const byte *src = (const byte *)buf; byte *dst = (byte *)_overlayData.pixels + y * _overlayData.pitch; for (int i = 0; i < h; i++) { - memcpy(dst + x * _overlayData.bytesPerPixel, src, w * _overlayData.bytesPerPixel); + memcpy(dst + x * _overlayData.format.bytesPerPixel, src, w * _overlayData.format.bytesPerPixel); src += pitch * sizeof(buf[0]); dst += _overlayData.pitch; } @@ -537,13 +555,53 @@ bool OpenGLGraphicsManager::showMouse(bool visible) { return last; } -void OpenGLGraphicsManager::setMousePos(int x, int y) { - _cursorState.x = x; - _cursorState.y = y; -} - void OpenGLGraphicsManager::warpMouse(int x, int y) { - setMousePos(x, y); + int scaledX = x; + int scaledY = y; + + int16 currentX = _cursorState.x; + int16 currentY = _cursorState.y; + + adjustMousePosition(currentX, currentY); + + // Do not adjust the real screen position, when the current game / overlay + // coordinates match the requested coordinates. This avoids a slight + // movement which might occur otherwise when the mouse is at a subpixel + // position. + if (x == currentX && y == currentY) + return; + + if (_videoMode.mode == OpenGL::GFX_NORMAL) { + if (_videoMode.hardwareWidth != _videoMode.overlayWidth) + scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth; + if (_videoMode.hardwareHeight != _videoMode.overlayHeight) + scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight; + + if (!_overlayVisible) { + scaledX *= _videoMode.scaleFactor; + scaledY *= _videoMode.scaleFactor; + } + } else { + if (_overlayVisible) { + if (_displayWidth != _videoMode.overlayWidth) + scaledX = scaledX * _displayWidth / _videoMode.overlayWidth; + if (_displayHeight != _videoMode.overlayHeight) + scaledY = scaledY * _displayHeight / _videoMode.overlayHeight; + } else { + if (_displayWidth != _videoMode.screenWidth) + scaledX = scaledX * _displayWidth / _videoMode.screenWidth; + if (_displayHeight != _videoMode.screenHeight) + scaledY = scaledY * _displayHeight / _videoMode.screenHeight; + } + + scaledX += _displayX; + scaledY += _displayY; + } + + setInternalMousePosition(scaledX, scaledY); + + _cursorState.x = scaledX; + _cursorState.y = scaledY; } void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { @@ -558,8 +616,9 @@ void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int #endif // Allocate space for cursor data - if (_cursorData.w != w || _cursorData.h != h) - _cursorData.create(w, h, _cursorFormat.bytesPerPixel); + if (_cursorData.w != w || _cursorData.h != h || + _cursorData.format.bytesPerPixel != _cursorFormat.bytesPerPixel) + _cursorData.create(w, h, _cursorFormat); // Save cursor data memcpy(_cursorData.pixels, buf, h * _cursorData.pitch); @@ -599,61 +658,13 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { assert(_transactionMode == kTransactionNone); assert(msg); - // The font we are going to use: - const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont); - - if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight()) - _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2); - else - // Clear everything - memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch); - +#ifdef USE_OSD // Split the message into separate lines. - Common::Array<Common::String> lines; - const char *ptr; - for (ptr = msg; *ptr; ++ptr) { - if (*ptr == '\n') { - lines.push_back(Common::String(msg, ptr - msg)); - msg = ptr + 1; - } - } - lines.push_back(Common::String(msg, ptr - msg)); - - // Determine a rect which would contain the message string (clipped to the - // screen dimensions). - const int vOffset = 6; - const int lineSpacing = 1; - const int lineHeight = font->getFontHeight() + 2 * lineSpacing; - int width = 0; - int height = lineHeight * lines.size() + 2 * vOffset; - for (uint i = 0; i < lines.size(); i++) { - width = MAX(width, font->getStringWidth(lines[i]) + 14); - } - - // Clip the rect - if (width > _osdSurface.w) - width = _osdSurface.w; - if (height > _osdSurface.h) - height = _osdSurface.h; - - int dstX = (_osdSurface.w - width) / 2; - int dstY = (_osdSurface.h - height) / 2; + _osdLines.clear(); - // Draw a dark gray rect - uint16 color = 0x294B; - uint16 *dst = (uint16 *)_osdSurface.pixels + dstY * _osdSurface.w + dstX; - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) - dst[j] = color; - dst += _osdSurface.w; - } - - // Render the message, centered, and in white - for (uint i = 0; i < lines.size(); i++) { - font->drawString(&_osdSurface, lines[i], - dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, - 0xFFFF, Graphics::kTextAlignCenter); - } + Common::StringTokenizer tokenizer(msg, "\n"); + while (!tokenizer.empty()) + _osdLines.push_back(tokenizer.nextToken()); // Request update of the texture _requireOSDUpdate = true; @@ -661,12 +672,25 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { // Init the OSD display parameters, and the fade out _osdAlpha = kOSDInitialAlpha; _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; +#endif } // // Intern // +void OpenGLGraphicsManager::setFullscreenMode(bool enable) { + assert(_transactionMode == kTransactionActive); + + if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable) + return; + + if (_transactionMode == kTransactionActive) { + _videoMode.fullscreen = enable; + _transactionDetails.needRefresh = true; + } +} + void OpenGLGraphicsManager::refreshGameScreen() { if (_screenNeedsRedraw) _screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h); @@ -676,13 +700,13 @@ void OpenGLGraphicsManager::refreshGameScreen() { int w = _screenDirtyRect.width(); int h = _screenDirtyRect.height(); - if (_screenData.bytesPerPixel == 1) { + if (_screenData.format.bytesPerPixel == 1) { // Create a temporary RGB888 surface byte *surface = new byte[w * h * 3]; // Convert the paletted buffer to RGB888 const byte *src = (byte *)_screenData.pixels + y * _screenData.pitch; - src += x * _screenData.bytesPerPixel; + src += x * _screenData.format.bytesPerPixel; byte *dst = surface; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { @@ -702,7 +726,7 @@ void OpenGLGraphicsManager::refreshGameScreen() { } else { // Update the texture _gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch + - x * _screenData.bytesPerPixel, _screenData.pitch, x, y, w, h); + x * _screenData.format.bytesPerPixel, _screenData.pitch, x, y, w, h); } _screenNeedsRedraw = false; @@ -718,13 +742,13 @@ void OpenGLGraphicsManager::refreshOverlay() { int w = _overlayDirtyRect.width(); int h = _overlayDirtyRect.height(); - if (_overlayData.bytesPerPixel == 1) { + if (_overlayData.format.bytesPerPixel == 1) { // Create a temporary RGB888 surface byte *surface = new byte[w * h * 3]; // Convert the paletted buffer to RGB888 const byte *src = (byte *)_overlayData.pixels + y * _overlayData.pitch; - src += x * _overlayData.bytesPerPixel; + src += x * _overlayData.format.bytesPerPixel; byte *dst = surface; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { @@ -744,7 +768,7 @@ void OpenGLGraphicsManager::refreshOverlay() { } else { // Update the texture _overlayTexture->updateBuffer((byte *)_overlayData.pixels + y * _overlayData.pitch + - x * _overlayData.bytesPerPixel, _overlayData.pitch, x, y, w, h); + x * _overlayData.format.bytesPerPixel, _overlayData.pitch, x, y, w, h); } _overlayNeedsRedraw = false; @@ -754,11 +778,17 @@ void OpenGLGraphicsManager::refreshOverlay() { void OpenGLGraphicsManager::refreshCursor() { _cursorNeedsRedraw = false; - if (_cursorFormat.bytesPerPixel == 1) { - // Create a temporary RGBA8888 surface - byte *surface = new byte[_cursorState.w * _cursorState.h * 4]; - memset(surface, 0, _cursorState.w * _cursorState.h * 4); + // Allocate a texture big enough for cursor + _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); + + // Create a temporary RGBA8888 surface + byte *surface = new byte[_cursorState.w * _cursorState.h * 4]; + memset(surface, 0, _cursorState.w * _cursorState.h * 4); + byte *dst = surface; + + // Convert the paletted cursor to RGBA8888 + if (_cursorFormat.bytesPerPixel == 1) { // Select palette byte *palette; if (_cursorPaletteDisabled) @@ -768,7 +798,6 @@ void OpenGLGraphicsManager::refreshCursor() { // Convert the paletted cursor to RGBA8888 const byte *src = (byte *)_cursorData.pixels; - byte *dst = surface; for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { // Check for keycolor if (src[i] != _cursorKeyColor) { @@ -779,16 +808,42 @@ void OpenGLGraphicsManager::refreshCursor() { } dst += 4; } + } else { + const bool gotNoAlpha = (_cursorFormat.aLoss == 8); + + // Convert the RGB cursor to RGBA8888 + if (_cursorFormat.bytesPerPixel == 2) { + const uint16 *src = (uint16 *)_cursorData.pixels; + for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { + // Check for keycolor + if (src[i] != _cursorKeyColor) { + _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]); + + if (gotNoAlpha) + dst[3] = 255; + } + dst += 4; + } + } else if (_cursorFormat.bytesPerPixel == 4) { + const uint32 *src = (uint32 *)_cursorData.pixels; + for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { + // Check for keycolor + if (src[i] != _cursorKeyColor) { + _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]); + + if (gotNoAlpha) + dst[3] = 255; + } + dst += 4; + } + } + } - // Allocate a texture big enough for cursor - _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); - - // Update the texture with new cursor - _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h); + // Update the texture with new cursor + _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h); - // Free the temp surface - delete[] surface; - } + // Free the temp surface + delete[] surface; } void OpenGLGraphicsManager::refreshCursorScale() { @@ -811,7 +866,8 @@ void OpenGLGraphicsManager::refreshCursorScale() { } else { // Otherwise, scale the cursor for the overlay int targetScaleFactor = MIN(_cursorTargetScale, _videoMode.scaleFactor); - int actualFactor = screenScaleFactor - (targetScaleFactor - 1) * 10000; + // We limit the maximum scale to 3 here to avoid too big cursors, for large overlay resolutions + int actualFactor = MIN<uint>(3, screenScaleFactor - (targetScaleFactor - 1)) * 10000; _cursorState.rW = (int16)(_cursorState.w * actualFactor / 10000); _cursorState.rH = (int16)(_cursorState.h * actualFactor / 10000); _cursorState.rHotX = (int16)(_cursorState.hotX * actualFactor / 10000); @@ -827,8 +883,8 @@ void OpenGLGraphicsManager::refreshCursorScale() { void OpenGLGraphicsManager::calculateDisplaySize(int &width, int &height) { if (_videoMode.mode == OpenGL::GFX_ORIGINAL) { - width = _videoMode.overlayWidth; - height = _videoMode.overlayHeight; + width = _videoMode.screenWidth; + height = _videoMode.screenHeight; } else { width = _videoMode.hardwareWidth; height = _videoMode.hardwareHeight; @@ -873,6 +929,11 @@ void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, intFormat = GL_RGBA; glFormat = GL_RGBA; gltype = GL_UNSIGNED_SHORT_5_5_5_1; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 + bpp = 2; + intFormat = GL_RGB; + glFormat = GL_BGRA; + gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 bpp = 2; intFormat = GL_RGBA; @@ -963,7 +1024,7 @@ void OpenGLGraphicsManager::internUpdateScreen() { refreshOverlay(); // Draw the overlay - _overlayTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight); + _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight); } if (_cursorVisible) { @@ -990,9 +1051,7 @@ void OpenGLGraphicsManager::internUpdateScreen() { #ifdef USE_OSD if (_osdAlpha > 0) { if (_requireOSDUpdate) { - // Update the texture - _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0, - _osdSurface.w, _osdSurface.h); + updateOSD(); _requireOSDUpdate = false; } @@ -1059,10 +1118,14 @@ void OpenGLGraphicsManager::initGL() { void OpenGLGraphicsManager::loadTextures() { #ifdef USE_RGB_COLOR - if (_transactionDetails.formatChanged && _gameTexture) + if (_transactionDetails.formatChanged && _gameTexture) { delete _gameTexture; + _gameTexture = 0; + } #endif + uint gameScreenBPP = 0; + if (!_gameTexture) { byte bpp; GLenum intformat; @@ -1073,6 +1136,7 @@ void OpenGLGraphicsManager::loadTextures() { #else getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, intformat, format, type); #endif + gameScreenBPP = bpp; _gameTexture = new GLTexture(bpp, intformat, format, type); } else _gameTexture->refresh(); @@ -1093,7 +1157,7 @@ void OpenGLGraphicsManager::loadTextures() { _cursorTexture = new GLTexture(4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); else _cursorTexture->refresh(); - + GLint filter = _videoMode.antialiasing ? GL_LINEAR : GL_NEAREST; _gameTexture->setFilter(filter); _overlayTexture->setFilter(filter); @@ -1104,21 +1168,43 @@ void OpenGLGraphicsManager::loadTextures() { _overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); - if (_transactionDetails.formatChanged || + if ( +#ifdef USE_RGB_COLOR + _transactionDetails.formatChanged || +#endif _oldVideoMode.screenWidth != _videoMode.screenWidth || _oldVideoMode.screenHeight != _videoMode.screenHeight) _screenData.create(_videoMode.screenWidth, _videoMode.screenHeight, - _screenFormat.bytesPerPixel); +#ifdef USE_RGB_COLOR + _screenFormat +#else + Graphics::PixelFormat::createFormatCLUT8() +#endif + ); + if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth || _oldVideoMode.overlayHeight != _videoMode.overlayHeight) _overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight, - _overlayFormat.bytesPerPixel); - + _overlayFormat); + _screenNeedsRedraw = true; _overlayNeedsRedraw = true; _cursorNeedsRedraw = true; + // We need to setup a proper unpack alignment value here, else we will + // get problems with the texture updates, in case the surface data is + // not properly aligned. + // For now we use the gcd of the game screen format and 2, since 2 is + // the BPP value for the overlay and the OSD. + if (gameScreenBPP) + glPixelStorei(GL_UNPACK_ALIGNMENT, Common::gcd<uint>(gameScreenBPP, 2)); + + // We use a "pack" alignment (when reading from textures) to 4 here, + // since the only place where we really use it is the BMP screenshot + // code and that requires the same alignment too. + glPixelStorei(GL_PACK_ALIGNMENT, 4); + #ifdef USE_OSD if (!_osdTexture) _osdTexture = new GLTexture(2, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1); @@ -1126,6 +1212,9 @@ void OpenGLGraphicsManager::loadTextures() { _osdTexture->refresh(); _osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); + + // Update the OSD in case it is used right now + _requireOSDUpdate = true; #endif } @@ -1149,6 +1238,8 @@ void OpenGLGraphicsManager::unloadGFXMode() { } void OpenGLGraphicsManager::setScale(int newScale) { + assert(_transactionMode == kTransactionActive); + if (newScale == _videoMode.scaleFactor) return; @@ -1156,50 +1247,48 @@ void OpenGLGraphicsManager::setScale(int newScale) { _transactionDetails.sizeChanged = true; } +void OpenGLGraphicsManager::toggleAntialiasing() { + assert(_transactionMode == kTransactionActive); + + _videoMode.antialiasing = !_videoMode.antialiasing; + _transactionDetails.filterChanged = true; +} + uint OpenGLGraphicsManager::getAspectRatio() { - if (_videoMode.mode == OpenGL::GFX_NORMAL) - return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight; - else if (_videoMode.mode == OpenGL::GFX_4_3) + // In case we enable aspect ratio correction we force a 4/3 ratio. + // TODO: This makes OpenGL Normal behave like OpenGL Conserve, when aspect + // ratio correction is enabled, but it's better than the previous 4/3 mode + // mess at least... + if (_videoMode.aspectRatioCorrection) return 13333; + else if (_videoMode.mode == OpenGL::GFX_NORMAL) + return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight; else return _videoMode.screenWidth * 10000 / _videoMode.screenHeight; } void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { - if (_videoMode.mode == OpenGL::GFX_NORMAL) { - if (_videoMode.hardwareWidth != _videoMode.overlayWidth) - x = x * _videoMode.overlayWidth / _videoMode.hardwareWidth; - if (_videoMode.hardwareHeight != _videoMode.overlayHeight) - y = y * _videoMode.overlayHeight / _videoMode.hardwareHeight; - - if (!_overlayVisible) { - x /= _videoMode.scaleFactor; - y /= _videoMode.scaleFactor; - } + if (_overlayVisible) + return; - } else { + if (!_overlayVisible) { x -= _displayX; y -= _displayY; - if (_overlayVisible) { - if (_displayWidth != _videoMode.overlayWidth) - x = x * _videoMode.overlayWidth / _displayWidth; - if (_displayHeight != _videoMode.overlayHeight) - y = y * _videoMode.overlayHeight / _displayHeight; - } else { - if (_displayWidth != _videoMode.screenWidth) - x = x * _videoMode.screenWidth / _displayWidth; - if (_displayHeight != _videoMode.screenHeight) - y = y * _videoMode.screenHeight / _displayHeight; - } + if (_displayWidth != _videoMode.screenWidth) + x = x * _videoMode.screenWidth / _displayWidth; + if (_displayHeight != _videoMode.screenHeight) + y = y * _videoMode.screenHeight / _displayHeight; } } bool OpenGLGraphicsManager::notifyEvent(const Common::Event &event) { switch (event.type) { case Common::EVENT_MOUSEMOVE: - if (!event.synthetic) - setMousePos(event.mouse.x, event.mouse.y); + if (!event.synthetic) { + _cursorState.x = event.mouse.x; + _cursorState.y = event.mouse.y; + } case Common::EVENT_LBUTTONDOWN: case Common::EVENT_RBUTTONDOWN: case Common::EVENT_WHEELUP: @@ -1227,8 +1316,16 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { int width = _videoMode.hardwareWidth; int height = _videoMode.hardwareHeight; + // A line of a BMP image must have a size divisible by 4. + // We calculate the padding bytes needed here. + // Since we use a 3 byte per pixel mode, we can use width % 4 here, since + // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the + // usual way of computing the padding bytes required). + const int linePaddingSize = width % 4; + const int lineSize = width * 3 + linePaddingSize; + // Allocate memory for screenshot - uint8 *pixels = new uint8[width * height * 3]; + uint8 *pixels = new uint8[lineSize * height]; // Get pixel data from OpenGL buffer #ifdef USE_GLES @@ -1248,9 +1345,9 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { // Write BMP header out.writeByte('B'); out.writeByte('M'); - out.writeUint32LE(height * width * 3 + 52); + out.writeUint32LE(height * lineSize + 54); out.writeUint32LE(0); - out.writeUint32LE(52); + out.writeUint32LE(54); out.writeUint32LE(40); out.writeUint32LE(width); out.writeUint32LE(height); @@ -1264,7 +1361,7 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { out.writeUint32LE(0); // Write pixel data to BMP - out.write(pixels, width * height * 3); + out.write(pixels, lineSize * height); // Free allocated memory delete[] pixels; @@ -1285,21 +1382,52 @@ const char *OpenGLGraphicsManager::getCurrentModeName() { return modeName; } -void OpenGLGraphicsManager::switchDisplayMode(int mode) { - if (_oldVideoMode.setup && _oldVideoMode.mode == mode) - return; +#ifdef USE_OSD +void OpenGLGraphicsManager::updateOSD() { + // The font we are going to use: + const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont); - if (_transactionMode == kTransactionActive) { - if (mode == -1) // If -1, switch to next mode - _videoMode.mode = (_videoMode.mode + 1) % 4; - else if (mode == -2) // If -2, switch to previous mode - _videoMode.mode = (_videoMode.mode + 3) % 4; - else - _videoMode.mode = mode; + if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight()) + _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), _overlayFormat); + else + // Clear everything + memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch); - _transactionDetails.needRefresh = true; - _aspectRatioCorrection = false; + // Determine a rect which would contain the message string (clipped to the + // screen dimensions). + const int vOffset = 6; + const int lineSpacing = 1; + const int lineHeight = font->getFontHeight() + 2 * lineSpacing; + int width = 0; + int height = lineHeight * _osdLines.size() + 2 * vOffset; + for (uint i = 0; i < _osdLines.size(); i++) { + width = MAX(width, font->getStringWidth(_osdLines[i]) + 14); } + + // Clip the rect + if (width > _osdSurface.w) + width = _osdSurface.w; + if (height > _osdSurface.h) + height = _osdSurface.h; + + int dstX = (_osdSurface.w - width) / 2; + int dstY = (_osdSurface.h - height) / 2; + + // Draw a dark gray rect + const uint16 color = 0x294B; + _osdSurface.fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color); + + // Render the message, centered, and in white + for (uint i = 0; i < _osdLines.size(); i++) { + font->drawString(&_osdSurface, _osdLines[i], + dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, + 0xFFFF, Graphics::kTextAlignCenter); + } + + // Update the texture + _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0, + _osdSurface.w, _osdSurface.h); } +#endif #endif diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index b4084e8e41..1725817730 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -28,7 +28,9 @@ #include "backends/graphics/opengl/gltexture.h" #include "backends/graphics/graphics.h" +#include "common/array.h" #include "common/events.h" +#include "graphics/pixelformat.h" // Uncomment this to enable the 'on screen display' code. #define USE_OSD 1 @@ -39,8 +41,7 @@ namespace OpenGL { enum { GFX_NORMAL = 0, GFX_CONSERVE = 1, - GFX_4_3 = 2, - GFX_ORIGINAL = 3 + GFX_ORIGINAL = 2 }; } @@ -152,11 +153,11 @@ protected: bool setup; bool fullscreen; - int activeFullscreenMode; int mode; int scaleFactor; bool antialiasing; + bool aspectRatioCorrection; int screenWidth, screenHeight; int overlayWidth, overlayHeight; @@ -176,7 +177,41 @@ protected: virtual bool loadGFXMode(); virtual void unloadGFXMode(); - virtual void setScale(int newScale); + /** + * Setup the fullscreen mode state. + */ + void setFullscreenMode(bool enable); + + /** + * Query the fullscreen state. + */ + inline bool getFullscreenMode() const { return _videoMode.fullscreen; } + + /** + * Set the scale factor. + * + * This can only be used in a GFX transaction. + * + * @param newScale New scale factor. + */ + void setScale(int newScale); + + /** + * Query the scale factor. + */ + inline int getScale() const { return _videoMode.scaleFactor; } + + /** + * Toggle the antialiasing state of the current video mode. + * + * This can only be used in a GFX transaction. + */ + void toggleAntialiasing(); + + /** + * Query the antialiasing state. + */ + inline bool getAntialiasingState() const { return _videoMode.antialiasing; } // Drawing coordinates for the current display mode and scale int _displayX; @@ -184,19 +219,11 @@ protected: int _displayWidth; int _displayHeight; - /** - * Sets the dispaly mode. - * @mode the dispaly mode, if -1 it will switch to next mode. If -2 to previous mode. - */ - virtual void switchDisplayMode(int mode); - virtual const char *getCurrentModeName(); virtual void calculateDisplaySize(int &width, int &height); virtual void refreshDisplaySize(); - bool _aspectRatioCorrection; - /** * Returns the current target aspect ratio x 10000 */ @@ -232,7 +259,7 @@ protected: bool _overlayVisible; bool _overlayNeedsRedraw; Common::Rect _overlayDirtyRect; - + virtual void refreshOverlay(); // @@ -272,6 +299,15 @@ protected: virtual void refreshCursor(); virtual void refreshCursorScale(); + + /** + * Set up the mouse position for the (event) system. + * + * @param x X coordinate in native coordinates. + * @param y Y coordinate in native coordinates. + */ + virtual void setInternalMousePosition(int x, int y) = 0; + /** * Adjusts hardware screen coordinates to either overlay or game screen * coordinates depending on whether the overlay is visible or not. @@ -280,7 +316,6 @@ protected: * @param y Y coordinate of the mouse position. */ virtual void adjustMousePosition(int16 &x, int16 &y); - virtual void setMousePos(int x, int y); // // Misc @@ -288,6 +323,16 @@ protected: virtual bool saveScreenshot(const char *filename); #ifdef USE_OSD + /** + * The OSD contents. + */ + Common::Array<Common::String> _osdLines; + + /** + * Update the OSD texture / surface. + */ + void updateOSD(); + GLTexture *_osdTexture; Graphics::Surface _osdSurface; uint8 _osdAlpha; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index c7ce0aa7de..fe86dd2098 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -30,11 +30,13 @@ #include "backends/graphics/openglsdl/openglsdl-graphics.h" #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" +#include "common/textconsole.h" OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager() : _hwscreen(0), _screenResized(false), + _activeFullscreenMode(-2), _lastFullscreenModeWidth(0), _lastFullscreenModeHeight(0), _desktopWidth(0), @@ -78,9 +80,6 @@ bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { switch (f) { - case OSystem::kFeatureFullscreenMode: - setFullscreenMode(enable); - break; case OSystem::kFeatureIconifyWindow: if (enable) SDL_WM_IconifyWindow(); @@ -121,6 +120,7 @@ void OpenGLSdlGraphicsManager::detectSupportedFormats() { #endif Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), // RGB565 Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0), // RGB5551 + Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), // RGB555 Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444 #ifndef USE_GLES Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) // ARGB4444 @@ -191,52 +191,8 @@ void OpenGLSdlGraphicsManager::detectSupportedFormats() { #endif -void OpenGLSdlGraphicsManager::warpMouse(int x, int y) { - int scaledX = x; - int scaledY = y; - - int16 currentX = _cursorState.x; - int16 currentY = _cursorState.y; - - adjustMousePosition(currentX, currentY); - - // Do not adjust the real screen position, when the current game / overlay - // coordinates match the requested coordinates. This avoids a slight - // movement which might occur otherwise when the mouse is at a subpixel - // position. - if (x == currentX && y == currentY) - return; - - if (_videoMode.mode == OpenGL::GFX_NORMAL) { - if (_videoMode.hardwareWidth != _videoMode.overlayWidth) - scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth; - if (_videoMode.hardwareHeight != _videoMode.overlayHeight) - scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight; - - if (!_overlayVisible) { - scaledX *= _videoMode.scaleFactor; - scaledY *= _videoMode.scaleFactor; - } - } else { - if (_overlayVisible) { - if (_displayWidth != _videoMode.overlayWidth) - scaledX = scaledX * _displayWidth / _videoMode.overlayWidth; - if (_displayHeight != _videoMode.overlayHeight) - scaledY = scaledY * _displayHeight / _videoMode.overlayHeight; - } else { - if (_displayWidth != _videoMode.screenWidth) - scaledX = scaledX * _displayWidth / _videoMode.screenWidth; - if (_displayHeight != _videoMode.screenHeight) - scaledY = scaledY * _displayHeight / _videoMode.screenHeight; - } - - scaledX += _displayX; - scaledY += _displayY; - } - - SDL_WarpMouse(scaledX, scaledY); - - setMousePos(scaledX, scaledY); +void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { + SDL_WarpMouse(x, y); } void OpenGLSdlGraphicsManager::updateScreen() { @@ -258,7 +214,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() { if (availableModes == (void *)-1) { _videoMode.hardwareWidth = _desktopWidth; _videoMode.hardwareHeight = _desktopHeight; - _videoMode.activeFullscreenMode = -2; + _activeFullscreenMode = -2; return true; } @@ -266,7 +222,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() { // The last used fullscreen mode will be prioritized, if there is no last fullscreen // mode, the desktop resolution will be used, and in case the desktop resolution // is not available as a fullscreen mode, the one with smallest metric will be selected. - if (_videoMode.activeFullscreenMode == -2) { + if (_activeFullscreenMode == -2) { // Desktop resolution int desktopModeIndex = -1; @@ -281,7 +237,7 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() { if (mode->w == _lastFullscreenModeWidth && mode->h == _lastFullscreenModeHeight) { _videoMode.hardwareWidth = _lastFullscreenModeWidth; _videoMode.hardwareHeight = _lastFullscreenModeHeight; - _videoMode.activeFullscreenMode = i; + _activeFullscreenMode = i; return true; } @@ -305,32 +261,32 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() { _videoMode.hardwareWidth = _desktopWidth; _videoMode.hardwareHeight = _desktopHeight; - _videoMode.activeFullscreenMode = desktopModeIndex; + _activeFullscreenMode = desktopModeIndex; return true; } else if (bestMode) { _videoMode.hardwareWidth = bestMode->w; _videoMode.hardwareHeight = bestMode->h; - _videoMode.activeFullscreenMode = bestModeIndex; + _activeFullscreenMode = bestModeIndex; return true; } } else { // Use last fullscreen mode if looping backwards from the first mode - if (_videoMode.activeFullscreenMode == -1) { + if (_activeFullscreenMode == -1) { do { - _videoMode.activeFullscreenMode++; - } while(availableModes[_videoMode.activeFullscreenMode]); - _videoMode.activeFullscreenMode--; + _activeFullscreenMode++; + } while(availableModes[_activeFullscreenMode]); + _activeFullscreenMode--; } // Use first fullscreen mode if looping from last mode - if (!availableModes[_videoMode.activeFullscreenMode]) - _videoMode.activeFullscreenMode = 0; + if (!availableModes[_activeFullscreenMode]) + _activeFullscreenMode = 0; // Check if the fullscreen mode is valid - if (availableModes[_videoMode.activeFullscreenMode]) { - _videoMode.hardwareWidth = availableModes[_videoMode.activeFullscreenMode]->w; - _videoMode.hardwareHeight = availableModes[_videoMode.activeFullscreenMode]->h; + if (availableModes[_activeFullscreenMode]) { + _videoMode.hardwareWidth = availableModes[_activeFullscreenMode]->w; + _videoMode.hardwareHeight = availableModes[_activeFullscreenMode]->h; return true; } } @@ -340,17 +296,11 @@ bool OpenGLSdlGraphicsManager::setupFullscreenMode() { } bool OpenGLSdlGraphicsManager::loadGFXMode() { - // Force 4/3 if feature enabled - if (_aspectRatioCorrection) - _videoMode.mode = OpenGL::GFX_4_3; - - _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; - // If the screen was resized, do not change its size if (!_screenResized) { - _videoMode.hardwareWidth = _videoMode.overlayWidth; - _videoMode.hardwareHeight = _videoMode.overlayHeight; + const int scaleFactor = getScale(); + _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * scaleFactor; + _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * scaleFactor; int screenAspectRatio = _videoMode.screenWidth * 10000 / _videoMode.screenHeight; int desiredAspectRatio = getAspectRatio(); @@ -360,11 +310,6 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() { _videoMode.hardwareHeight = (_videoMode.overlayWidth * 10000 + 5000) / desiredAspectRatio; else if (screenAspectRatio < desiredAspectRatio) _videoMode.hardwareWidth = (_videoMode.overlayHeight * desiredAspectRatio + 5000) / 10000; - - // Only adjust the overlay height if it is bigger than original one. If - // the width is modified it can break the overlay. - if (_videoMode.hardwareHeight > _videoMode.overlayHeight) - _videoMode.overlayHeight = _videoMode.hardwareHeight; } _screenResized = false; @@ -376,14 +321,24 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() { SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - if (_videoMode.fullscreen) + const bool isFullscreen = getFullscreenMode(); + + // In case we have an fullscreen mode and we are not in a rollback, detect + // a proper mode to use. In case we are in a rollback, we already detected + // a proper mode when setting up that mode, thus there is no need to run + // the detection again. + if (isFullscreen && _transactionMode != kTransactionRollback) { if (!setupFullscreenMode()) // Failed setuping a fullscreen mode return false; + } + + _videoMode.overlayWidth = _videoMode.hardwareWidth; + _videoMode.overlayHeight = _videoMode.hardwareHeight; uint32 flags = SDL_OPENGL; - if (_videoMode.fullscreen) + if (isFullscreen) flags |= SDL_FULLSCREEN; else flags |= SDL_RESIZABLE; @@ -409,7 +364,7 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() { // Check if the screen is BGR format _formatBGR = _hwscreen->format->Rshift != 0; - if (_videoMode.fullscreen) { + if (isFullscreen) { _lastFullscreenModeWidth = _videoMode.hardwareWidth; _lastFullscreenModeHeight = _videoMode.hardwareHeight; ConfMan.setInt("last_fullscreen_mode_width", _lastFullscreenModeWidth); @@ -439,11 +394,13 @@ void OpenGLSdlGraphicsManager::internUpdateScreen() { void OpenGLSdlGraphicsManager::displayModeChangedMsg() { const char *newModeName = getCurrentModeName(); if (newModeName) { + const int scaleFactor = getScale(); + char buffer[128]; sprintf(buffer, "Current display mode: %s\n%d x %d -> %d x %d", newModeName, - _videoMode.screenWidth * _videoMode.scaleFactor, - _videoMode.screenHeight * _videoMode.scaleFactor, + _videoMode.screenWidth * scaleFactor, + _videoMode.screenHeight * scaleFactor, _hwscreen->w, _hwscreen->h ); displayMessageOnOSD(buffer); @@ -451,8 +408,9 @@ void OpenGLSdlGraphicsManager::displayModeChangedMsg() { } void OpenGLSdlGraphicsManager::displayScaleChangedMsg() { char buffer[128]; + const int scaleFactor = getScale(); sprintf(buffer, "Current scale: x%d\n%d x %d -> %d x %d", - _videoMode.scaleFactor, + scaleFactor, _videoMode.screenWidth, _videoMode.screenHeight, _videoMode.overlayWidth, _videoMode.overlayHeight ); @@ -460,17 +418,6 @@ void OpenGLSdlGraphicsManager::displayScaleChangedMsg() { } #endif -void OpenGLSdlGraphicsManager::setFullscreenMode(bool enable) { - if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable && - _oldVideoMode.activeFullscreenMode == _videoMode.activeFullscreenMode) - return; - - if (_transactionMode == kTransactionActive) { - _videoMode.fullscreen = enable; - _transactionDetails.needRefresh = true; - } -} - bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { if (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS || @@ -488,12 +435,14 @@ bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) { beginGFXTransaction(); - if (_videoMode.fullscreen && loop) { - _videoMode.activeFullscreenMode += loop; + const bool isFullscreen = getFullscreenMode(); + + if (isFullscreen && loop) { + _activeFullscreenMode += loop; setFullscreenMode(true); } else { - _videoMode.activeFullscreenMode = -2; - setFullscreenMode(!_videoMode.fullscreen); + _activeFullscreenMode = -2; + setFullscreenMode(!isFullscreen); } endGFXTransaction(); @@ -502,7 +451,7 @@ void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) { #ifdef USE_OSD char buffer[128]; - if (_videoMode.fullscreen) + if (getFullscreenMode()) sprintf(buffer, "Fullscreen mode\n%d x %d", _hwscreen->w, _hwscreen->h ); @@ -539,9 +488,9 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { SDL_RWclose(file); } if (saveScreenshot(filename)) - printf("Saved '%s'\n", filename); + debug("Saved screenshot '%s'", filename); else - printf("Could not save screenshot!\n"); + warning("Could not save screenshot"); return true; } } @@ -557,10 +506,19 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // Ctrl-Alt-a switch between display modes if (event.kbd.keycode == 'a') { beginGFXTransaction(); - switchDisplayMode(-1); + setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection)); endGFXTransaction(); #ifdef USE_OSD - displayModeChangedMsg(); + char buffer[128]; + if (getFeatureState(OSystem::kFeatureAspectRatioCorrection)) + sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d", + _videoMode.screenWidth, _videoMode.screenHeight, + _hwscreen->w, _hwscreen->h); + else + sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d", + _videoMode.screenWidth, _videoMode.screenHeight, + _hwscreen->w, _hwscreen->h); + displayMessageOnOSD(buffer); #endif internUpdateScreen(); return true; @@ -569,11 +527,14 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // Ctrl-Alt-f toggles antialiasing if (event.kbd.keycode == 'f') { beginGFXTransaction(); - _videoMode.antialiasing = !_videoMode.antialiasing; - _transactionDetails.filterChanged = true; + toggleAntialiasing(); endGFXTransaction(); + #ifdef USE_OSD - if (_videoMode.antialiasing) + // TODO: This makes guesses about what internal antialiasing + // modes we use, we might want to consider a better way of + // displaying information to the user. + if (getAntialiasingState()) displayMessageOnOSD("Active filter mode: Linear"); else displayMessageOnOSD("Active filter mode: Nearest"); @@ -586,7 +547,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // Ctrl+Alt+Plus/Minus Increase/decrease the scale factor if ((sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS)) { - int factor = _videoMode.scaleFactor; + int factor = getScale(); factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1; if (0 < factor && factor < 4) { // Check if the desktop resolution has been detected @@ -606,17 +567,21 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { } } - const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_4); - const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP4); + const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_3); + const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP3); // Ctrl-Alt-<number key> will change the GFX mode if (isNormalNumber || isKeypadNumber) { - if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 4) { + if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 3) { +#ifdef USE_OSD int lastMode = _videoMode.mode; +#endif + // We need to query the scale and set it up, because + // setGraphicsMode sets the default scale to 2 + int oldScale = getScale(); beginGFXTransaction(); - _videoMode.mode = sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1); - _transactionDetails.needRefresh = true; - _aspectRatioCorrection = false; + setGraphicsMode(sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1)); + setScale(oldScale); endGFXTransaction(); #ifdef USE_OSD if (lastMode != _videoMode.mode) @@ -634,18 +599,6 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { toggleFullScreen(-1); return true; } - - // Ctrl-Shift-a switch backwards between display modes - if (event.kbd.keycode == 'a') { - beginGFXTransaction(); - switchDisplayMode(-2); - endGFXTransaction(); -#ifdef USE_OSD - displayModeChangedMsg(); -#endif - internUpdateScreen(); - return true; - } } break; case Common::EVENT_KEYUP: @@ -655,7 +608,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // there is no common resize event. case OSystem_SDL::kSdlEventResize: // Do not resize if ignoring resize events. - if (!_ignoreResizeFrames && !_videoMode.fullscreen) { + if (!_ignoreResizeFrames && !getFullscreenMode()) { bool scaleChanged = false; beginGFXTransaction(); _videoMode.hardwareWidth = event.mouse.x; @@ -667,10 +620,11 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { } int scale = MIN(_videoMode.hardwareWidth / _videoMode.screenWidth, - _videoMode.hardwareHeight / _videoMode.screenHeight); - if (_videoMode.scaleFactor != scale) { + _videoMode.hardwareHeight / _videoMode.screenHeight); + + if (getScale() != scale) { scaleChanged = true; - _videoMode.scaleFactor = MAX(MIN(scale, 3), 1); + setScale(MAX(MIN(scale, 3), 1)); } if (_videoMode.mode == OpenGL::GFX_ORIGINAL) { diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index d39c0814de..e9e5ed882d 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -48,8 +48,6 @@ public: virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif - virtual void warpMouse(int x, int y); - virtual bool notifyEvent(const Common::Event &event); virtual void updateScreen(); @@ -59,9 +57,6 @@ protected: virtual bool loadGFXMode(); virtual void unloadGFXMode(); - - virtual void setFullscreenMode(bool enable); - virtual bool isHotkey(const Common::Event &event); #ifdef USE_RGB_COLOR @@ -80,12 +75,16 @@ protected: */ virtual void toggleFullScreen(int loop); + int _activeFullscreenMode; + /** * Setup the fullscreen mode. * @return false if failed finding a mode, true otherwise. */ virtual bool setupFullscreenMode(); + virtual void setInternalMousePosition(int x, int y); + int _lastFullscreenModeWidth; int _lastFullscreenModeHeight; int _desktopWidth; diff --git a/backends/platform/openpandora/op-graphics.cpp b/backends/graphics/openpandora/op-graphics.cpp index ef95f52e99..20ee5dfc36 100644 --- a/backends/platform/openpandora/op-graphics.cpp +++ b/backends/graphics/openpandora/op-graphics.cpp @@ -18,20 +18,26 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ +#include "common/scummsys.h" + +#if defined(OPENPANDORA) + +#include "backends/graphics/openpandora/op-graphics.h" +#include "backends/events/openpandora/op-events.h" #include "backends/platform/openpandora/op-sdl.h" #include "common/mutex.h" -#include "common/translation.h" #include "common/util.h" #include "graphics/scaler/aspect.h" #include "graphics/surface.h" -bool OSystem_OP::loadGFXMode() { +OPGraphicsManager::OPGraphicsManager(SdlEventSource *boss) + : SdlGraphicsManager(boss) { +} + +bool OPGraphicsManager::loadGFXMode() { /* FIXME: For now we just cheat and set the overlay to 640*480 not 800*480 and let SDL deal with the boarders (it saves cleaning up the overlay when the game screen is smaller than the overlay ;) @@ -43,8 +49,7 @@ bool OSystem_OP::loadGFXMode() { if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) _videoMode.aspectRatioCorrection = false; - OSystem_SDL::loadGFXMode(); - - return true; - + return SdlGraphicsManager::loadGFXMode(); } + +#endif diff --git a/backends/graphics/openpandora/op-graphics.h b/backends/graphics/openpandora/op-graphics.h new file mode 100644 index 0000000000..b0d4298620 --- /dev/null +++ b/backends/graphics/openpandora/op-graphics.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OP_H +#define BACKENDS_GRAPHICS_OP_H + +#include "backends/graphics/sdl/sdl-graphics.h" +#include "graphics/scaler/aspect.h" // for aspect2Real +#include "graphics/scaler/downscaler.h" + +enum { + GFX_HALF = 12 +}; + +class OPGraphicsManager : public SdlGraphicsManager { +public: + OPGraphicsManager(SdlEventSource *boss); + + bool hasFeature(OSystem::Feature f); + void setFeatureState(OSystem::Feature f, bool enable); + bool getFeatureState(OSystem::Feature f); + int getDefaultGraphicsMode() const; + + void initSize(uint w, uint h); + const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + bool setGraphicsMode(const char *name); + bool setGraphicsMode(int mode); + void setGraphicsModeIntern(); + void internUpdateScreen(); + void showOverlay(); + void hideOverlay(); + bool loadGFXMode(); + void drawMouse(); + void undrawMouse(); + virtual void warpMouse(int x, int y); + + SdlGraphicsManager::MousePos *getMouseCurState(); + SdlGraphicsManager::VideoState *getVideoMode(); + + virtual void adjustMouseEvent(const Common::Event &event); +}; + +#endif /* BACKENDS_GRAPHICS_OP_H */ diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 15d896c57a..3ae9597f1c 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -32,6 +32,7 @@ #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" #include "common/mutex.h" +#include "common/textconsole.h" #include "common/translation.h" #include "common/util.h" #ifdef USE_RGB_COLOR @@ -141,7 +142,11 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource) _currentShakePos(0), _newShakePos(0), _paletteDirtyStart(0), _paletteDirtyEnd(0), _screenIsLocked(false), - _graphicsMutex(0), _transactionMode(kTransactionNone) { + _graphicsMutex(0), +#ifdef USE_SDL_DEBUG_FOCUSRECT + _enableFocusRectDebugCode(false), _enableFocusRect(false), _focusRect(), +#endif + _transactionMode(kTransactionNone) { if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { error("Could not initialize SDL: %s", SDL_GetError()); @@ -161,11 +166,9 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource) _graphicsMutex = g_system->createMutex(); -#ifdef _WIN32_WCE - if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) { - SDL_VideoInit("windib", 0); - sdlFlags ^= SDL_INIT_VIDEO; - } +#ifdef USE_SDL_DEBUG_FOCUSRECT + if (ConfMan.hasKey("use_sdl_debug_focusrect")) + _enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect"); #endif SDL_ShowCursor(SDL_DISABLE); @@ -1103,6 +1106,79 @@ void SdlGraphicsManager::internUpdateScreen() { SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); } #endif + +#ifdef USE_SDL_DEBUG_FOCUSRECT + // We draw the focus rectangle on top of everything, to assure it's easily visible. + // Of course when the overlay is visible we do not show it, since it is only for game + // specific focus. + if (_enableFocusRect && !_overlayVisible) { + int y = _focusRect.top + _currentShakePos; + int h = 0; + int x = _focusRect.left * scale1; + int w = _focusRect.width() * scale1; + + if (y < height) { + h = _focusRect.height(); + if (h > height - y) + h = height - y; + + y *= scale1; + + if (_videoMode.aspectRatioCorrection && !_overlayVisible) + y = real2Aspect(y); + + if (h > 0 && w > 0) { + SDL_LockSurface(_hwscreen); + + // Use white as color for now. + Uint32 rectColor = SDL_MapRGB(_hwscreen->format, 0xFF, 0xFF, 0xFF); + + // First draw the top and bottom lines + // then draw the left and right lines + if (_hwscreen->format->BytesPerPixel == 2) { + uint16 *top = (uint16 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2); + uint16 *bottom = (uint16 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 2); + byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2); + byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 2); + + while (w--) { + *top++ = rectColor; + *bottom++ = rectColor; + } + + while (h--) { + *(uint16 *)left = rectColor; + *(uint16 *)right = rectColor; + + left += _hwscreen->pitch; + right += _hwscreen->pitch; + } + } else if (_hwscreen->format->BytesPerPixel == 4) { + uint32 *top = (uint32 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4); + uint32 *bottom = (uint32 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 4); + byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4); + byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 4); + + while (w--) { + *top++ = rectColor; + *bottom++ = rectColor; + } + + while (h--) { + *(uint32 *)left = rectColor; + *(uint32 *)right = rectColor; + + left += _hwscreen->pitch; + right += _hwscreen->pitch; + } + } + + SDL_UnlockSurface(_hwscreen); + } + } + } +#endif + // Finally, blit all our changes to the screen SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); } @@ -1166,25 +1242,25 @@ void SdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int error("SDL_LockSurface failed: %s", SDL_GetError()); #ifdef USE_RGB_COLOR - byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth * _screenFormat.bytesPerPixel + x * _screenFormat.bytesPerPixel; - if (_videoMode.screenWidth == w && pitch == w * _screenFormat.bytesPerPixel) { - memcpy(dst, src, h*w*_screenFormat.bytesPerPixel); + byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x * _screenFormat.bytesPerPixel; + if (_videoMode.screenWidth == w && pitch == _screen->pitch) { + memcpy(dst, src, h*pitch); } else { do { memcpy(dst, src, w * _screenFormat.bytesPerPixel); src += pitch; - dst += _videoMode.screenWidth * _screenFormat.bytesPerPixel; + dst += _screen->pitch; } while (--h); } #else - byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x; - if (_videoMode.screenWidth == pitch && pitch == w) { + byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x; + if (_screen->pitch == pitch && pitch == w) { memcpy(dst, src, h*w); } else { do { memcpy(dst, src, w); src += pitch; - dst += _videoMode.screenWidth; + dst += _screen->pitch; } while (--h); } #endif @@ -1212,9 +1288,9 @@ Graphics::Surface *SdlGraphicsManager::lockScreen() { _framebuffer.h = _screen->h; _framebuffer.pitch = _screen->pitch; #ifdef USE_RGB_COLOR - _framebuffer.bytesPerPixel = _screenFormat.bytesPerPixel; + _framebuffer.format = _screenFormat; #else - _framebuffer.bytesPerPixel = 1; + _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); #endif return &_framebuffer; @@ -1396,6 +1472,41 @@ void SdlGraphicsManager::setShakePos(int shake_pos) { _newShakePos = shake_pos; } +void SdlGraphicsManager::setFocusRectangle(const Common::Rect &rect) { +#ifdef USE_SDL_DEBUG_FOCUSRECT + // Only enable focus rectangle debug code, when the user wants it + if (!_enableFocusRectDebugCode) + return; + + _enableFocusRect = true; + _focusRect = rect; + + if (rect.left < 0 || rect.top < 0 || rect.right > _videoMode.screenWidth || rect.bottom > _videoMode.screenHeight) + warning("SdlGraphicsManager::setFocusRectangle: Got a rect which does not fit inside the screen bounds: %d,%d,%d,%d", rect.left, rect.top, rect.right, rect.bottom); + + // It's gross but we actually sometimes get rects, which are not inside the screen bounds, + // thus we need to clip the rect here... + _focusRect.clip(_videoMode.screenWidth, _videoMode.screenHeight); + + // We just fake this as a dirty rect for now, to easily force an screen update whenever + // the rect changes. + addDirtyRect(_focusRect.left, _focusRect.top, _focusRect.width(), _focusRect.height()); +#endif +} + +void SdlGraphicsManager::clearFocusRectangle() { +#ifdef USE_SDL_DEBUG_FOCUSRECT + // Only enable focus rectangle debug code, when the user wants it + if (!_enableFocusRectDebugCode) + return; + + _enableFocusRect = false; + + // We just fake this as a dirty rect for now, to easily force an screen update whenever + // the rect changes. + addDirtyRect(_focusRect.left, _focusRect.top, _focusRect.width(), _focusRect.height()); +#endif +} #pragma mark - #pragma mark --- Overlays --- @@ -1868,7 +1979,6 @@ void SdlGraphicsManager::drawMouse() { SDL_Rect dst; int scale; - int width, height; int hotX, hotY; dst.x = _mouseCurState.x; @@ -1876,16 +1986,12 @@ void SdlGraphicsManager::drawMouse() { if (!_overlayVisible) { scale = _videoMode.scaleFactor; - width = _videoMode.screenWidth; - height = _videoMode.screenHeight; dst.w = _mouseCurState.vW; dst.h = _mouseCurState.vH; hotX = _mouseCurState.vHotX; hotY = _mouseCurState.vHotY; } else { scale = 1; - width = _videoMode.overlayWidth; - height = _videoMode.overlayHeight; dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; hotX = _mouseCurState.rHotX; @@ -1949,7 +2055,11 @@ void SdlGraphicsManager::displayMessageOnOSD(const char *msg) { dst.w = _osdSurface->w; dst.h = _osdSurface->h; dst.pitch = _osdSurface->pitch; - dst.bytesPerPixel = _osdSurface->format->BytesPerPixel; + dst.format = Graphics::PixelFormat(_osdSurface->format->BytesPerPixel, + 8 - _osdSurface->format->Rloss, 8 - _osdSurface->format->Gloss, + 8 - _osdSurface->format->Bloss, 8 - _osdSurface->format->Aloss, + _osdSurface->format->Rshift, _osdSurface->format->Gshift, + _osdSurface->format->Bshift, _osdSurface->format->Ashift); // The font we are going to use: const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont); @@ -2169,9 +2279,9 @@ bool SdlGraphicsManager::notifyEvent(const Common::Event &event) { SDL_RWclose(file); } if (saveScreenshot(filename)) - printf("Saved '%s'\n", filename); + debug("Saved screenshot '%s'", filename); else - printf("Could not save screenshot!\n"); + warning("Could not save screenshot"); return true; } diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 0daaab104c..4895b240b0 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -27,6 +27,7 @@ #define BACKENDS_GRAPHICS_SDL_H #include "backends/graphics/graphics.h" +#include "graphics/pixelformat.h" #include "graphics/scaler.h" #include "common/events.h" #include "common/system.h" @@ -35,6 +36,10 @@ #include "backends/platform/sdl/sdl-sys.h" +#ifndef RELEASE_BUILD +// Define this to allow for focus rectangle debugging +#define USE_SDL_DEBUG_FOCUSRECT +#endif #if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) // Uncomment this to enable the 'on screen display' code. @@ -114,8 +119,8 @@ public: virtual void fillScreen(uint32 col); virtual void updateScreen(); virtual void setShakePos(int shakeOffset); - virtual void setFocusRectangle(const Common::Rect& rect) {} - virtual void clearFocusRectangle() {} + virtual void setFocusRectangle(const Common::Rect& rect); + virtual void clearFocusRectangle(); virtual void showOverlay(); virtual void hideOverlay(); @@ -301,6 +306,12 @@ protected: */ OSystem::MutexRef _graphicsMutex; +#ifdef USE_SDL_DEBUG_FOCUSRECT + bool _enableFocusRectDebugCode; + bool _enableFocusRect; + Common::Rect _focusRect; +#endif + virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); virtual void drawMouse(); diff --git a/backends/graphics/wincesdl/wincesdl-graphics.cpp b/backends/graphics/wincesdl/wincesdl-graphics.cpp new file mode 100644 index 0000000000..b15f86e8fe --- /dev/null +++ b/backends/graphics/wincesdl/wincesdl-graphics.cpp @@ -0,0 +1,1640 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/scummsys.h" + +#ifdef _WIN32_WCE + +#include "common/system.h" +#include "common/textconsole.h" +#include "common/translation.h" +#include "common/mutex.h" + +#include "graphics/scaler/downscaler.h" +#include "graphics/scaler/aspect.h" +#include "backends/graphics/wincesdl/wincesdl-graphics.h" +#include "backends/events/wincesdl/wincesdl-events.h" +#include "backends/platform/wince/wince-sdl.h" + +#include "backends/platform/wince/resource.h" +#include "backends/platform/wince/CEActionsPocket.h" +#include "backends/platform/wince/CEActionsSmartphone.h" +#include "backends/platform/wince/CEDevice.h" +#include "backends/platform/wince/CEScaler.h" +#include "backends/platform/wince/CEgui/ItemAction.h" + +WINCESdlGraphicsManager::WINCESdlGraphicsManager(SdlEventSource *sdlEventSource) + : SdlGraphicsManager(sdlEventSource), + _panelInitialized(false), _noDoubleTapRMB(false), + _toolbarHighDrawn(false), _newOrientation(0), _orientationLandscape(0), + _panelVisible(true), _saveActiveToolbar(NAME_MAIN_PANEL), _panelStateForced(false), + _canBeAspectScaled(false), _scalersChanged(false), _saveToolbarState(false), + _mouseBackupOld(NULL), _mouseBackupDim(0), _mouseBackupToolbar(NULL), + _usesEmulatedMouse(false), _forceHideMouse(false), _hasfocus(true), + _zoomUp(false), _zoomDown(false) { + memset(&_mouseCurState, 0, sizeof(_mouseCurState)); + if (_isSmartphone) { + _mouseCurState.x = 20; + _mouseCurState.y = 20; + } + + loadDeviceConfigurationElement("repeatTrigger", _keyRepeatTrigger, 200); + loadDeviceConfigurationElement("repeatX", _repeatX, 4); + loadDeviceConfigurationElement("repeatY", _repeatY, 4); + loadDeviceConfigurationElement("stepX1", _stepX1, 2); + loadDeviceConfigurationElement("stepX2", _stepX2, 10); + loadDeviceConfigurationElement("stepX3", _stepX3, 40); + loadDeviceConfigurationElement("stepY1", _stepY1, 2); + loadDeviceConfigurationElement("stepY2", _stepY2, 10); + loadDeviceConfigurationElement("stepY3", _stepY3, 20); + ConfMan.flushToDisk(); + + _isSmartphone = CEDevice::isSmartphone(); + + // Query SDL for screen size and init screen dependent stuff + OSystem_WINCE3::initScreenInfos(); + create_toolbar(); + _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone(); + if (_hasSmartphoneResolution) + _panelVisible = false; // init correctly in smartphones + + _screen = NULL; +} + +// Graphics mode consts + +// Low end devices 240x320 + +static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = { + {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, + {0, 0, 0} +}; + +// High end device 480x640 + +static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = { + {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, + {"2x", "2x", GFX_DOUBLESIZE}, +#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :) + {"2xsai", "2xSAI", GFX_2XSAI}, + {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI}, + {"supereagle", "SuperEagle", GFX_SUPEREAGLE}, +#endif + {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X}, +#ifndef _MSC_VER + {"hq2x", "HQ2x", GFX_HQ2X}, + {"tv2x", "TV2x", GFX_TV2X}, +#endif + {"dotmatrix", "DotMatrix", GFX_DOTMATRIX}, + {0, 0, 0} +}; + +const OSystem::GraphicsMode *WINCESdlGraphicsManager::getSupportedGraphicsModes() const { + if (CEDevice::hasWideResolution()) + return s_supportedGraphicsModesHigh; + else + return s_supportedGraphicsModesLow; +} + +bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) { + return (f == OSystem::kFeatureVirtualKeyboard); +} + +void WINCESdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + return; + + case OSystem::kFeatureVirtualKeyboard: + if (_hasSmartphoneResolution) + return; + _toolbarHighDrawn = false; + if (enable) { + _panelStateForced = true; + if (!_toolbarHandler.visible()) swap_panel_visibility(); + //_saveToolbarState = _toolbarHandler.visible(); + _saveActiveToolbar = _toolbarHandler.activeName(); + _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); + _toolbarHandler.setVisible(true); + } else if (_panelStateForced) { + _panelStateForced = false; + _toolbarHandler.setActive(_saveActiveToolbar); + //_toolbarHandler.setVisible(_saveToolbarState); + } + return; + + case OSystem::kFeatureDisableKeyFiltering: + if (_hasSmartphoneResolution) { + GUI::Actions::Instance()->beginMapping(enable); + } + return; + + default: + SdlGraphicsManager::setFeatureState(f, enable); + } +} + +bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + return false; + case OSystem::kFeatureVirtualKeyboard: + return (_panelStateForced); + default: + return SdlGraphicsManager::getFeatureState(f); + } +} + +int WINCESdlGraphicsManager::getDefaultGraphicsMode() const { + return GFX_NORMAL; +} + +void WINCESdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) { + if (_hasSmartphoneResolution && h == 240) + h = 200; // mainly for the launcher + + if (_isSmartphone && !ConfMan.hasKey("landscape")) { + ConfMan.setInt("landscape", 1); + ConfMan.flushToDisk(); + } + + _canBeAspectScaled = false; + if (w == 320 && h == 200 && !_hasSmartphoneResolution) { + _canBeAspectScaled = true; + h = 240; // use the extra 40 pixels height for the toolbar + } + + if (h == 400) // touche engine fixup + h += 80; + + if (!_hasSmartphoneResolution) { + if (h == 240) + _toolbarHandler.setOffset(200); + else + _toolbarHandler.setOffset(400); + } else { + if (h == 240) + _toolbarHandler.setOffset(200); + else // 176x220 + _toolbarHandler.setOffset(0); + } + + if (w != (uint) _videoMode.screenWidth || h != (uint) _videoMode.screenHeight) + _scalersChanged = false; + + _videoMode.overlayWidth = w; + _videoMode.overlayHeight = h; + + SdlGraphicsManager::initSize(w, h, format); + + if (_scalersChanged) { + unloadGFXMode(); + loadGFXMode(); + _scalersChanged = false; + } + + update_game_settings(); +} + +void WINCESdlGraphicsManager::loadDeviceConfigurationElement(Common::String element, int &value, int defaultValue) { + value = ConfMan.getInt(element, ConfMan.kApplicationDomain); + if (!value) { + value = defaultValue; + ConfMan.setInt(element, value, ConfMan.kApplicationDomain); + } +} + +void WINCESdlGraphicsManager::move_cursor_up() { + int x, y; + _usesEmulatedMouse = true; + retrieve_mouse_location(x, y); + if (_keyRepeat > _repeatY) + y -= _stepY3; + else if (_keyRepeat) + y -= _stepY2; + else + y -= _stepY1; + + if (y < 0) + y = 0; + + EventsBuffer::simulateMouseMove(x, y); +} + +void WINCESdlGraphicsManager::move_cursor_down() { + int x, y; + _usesEmulatedMouse = true; + retrieve_mouse_location(x, y); + if (_keyRepeat > _repeatY) + y += _stepY3; + else if (_keyRepeat) + y += _stepY2; + else + y += _stepY1; + + if (y > _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd) + y = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd; + + EventsBuffer::simulateMouseMove(x, y); +} + +void WINCESdlGraphicsManager::move_cursor_left() { + int x, y; + _usesEmulatedMouse = true; + retrieve_mouse_location(x, y); + if (_keyRepeat > _repeatX) + x -= _stepX3; + else if (_keyRepeat) + x -= _stepX2; + else + x -= _stepX1; + + if (x < 0) + x = 0; + + EventsBuffer::simulateMouseMove(x, y); +} + +void WINCESdlGraphicsManager::move_cursor_right() { + int x, y; + _usesEmulatedMouse = true; + retrieve_mouse_location(x, y); + if (_keyRepeat > _repeatX) + x += _stepX3; + else if (_keyRepeat) + x += _stepX2; + else + x += _stepX1; + + if (x > _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd) + x = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd; + + EventsBuffer::simulateMouseMove(x, y); +} + +void WINCESdlGraphicsManager::retrieve_mouse_location(int &x, int &y) { + x = _mouseCurState.x; + y = _mouseCurState.y; + + x = x * _scaleFactorXm / _scaleFactorXd; + y = y * _scaleFactorYm / _scaleFactorYd; + + if (_zoomDown) + y -= 240; +} + +void WINCESdlGraphicsManager::switch_zone() { + int x, y; + int i; + retrieve_mouse_location(x, y); + + for (i = 0; i < TOTAL_ZONES; i++) + if (x >= _zones[i].x && y >= _zones[i].y && + x <= _zones[i].x + _zones[i].width && y <= _zones[i].y + _zones[i].height) { + _mouseXZone[i] = x; + _mouseYZone[i] = y; + break; + } + _currentZone = i + 1; + if (_currentZone >= TOTAL_ZONES) + _currentZone = 0; + + EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]); +} + +void WINCESdlGraphicsManager::add_right_click(bool pushed) { + int x, y; + retrieve_mouse_location(x, y); + EventsBuffer::simulateMouseRightClick(x, y, pushed); +} + +void WINCESdlGraphicsManager::add_left_click(bool pushed) { + int x, y; + retrieve_mouse_location(x, y); + EventsBuffer::simulateMouseLeftClick(x, y, pushed); +} + +bool WINCESdlGraphicsManager::update_scalers() { + _videoMode.aspectRatioCorrection = false; + + if (CEDevice::hasPocketPCResolution()) { + if (_videoMode.mode != GFX_NORMAL) + return false; + + if ((!_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) + || CEDevice::hasSquareQVGAResolution()) { + if (OSystem_WINCE3::getScreenWidth() != 320) { + _scaleFactorXm = 3; + _scaleFactorXd = 4; + _scaleFactorYm = 1; + _scaleFactorYd = 1; + _scalerProc = DownscaleHorizByThreeQuarters; + } else { + _scaleFactorXm = 1; + _scaleFactorXd = 1; + _scaleFactorYm = 1; + _scaleFactorYd = 1; + _scalerProc = Normal1x; + } + } else if (_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) { + if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) { + _scaleFactorXm = 1; + _scaleFactorXd = 1; + _scaleFactorYm = 6; + _scaleFactorYd = 5; + _scalerProc = Normal1xAspect; + _videoMode.aspectRatioCorrection = true; + } else { + _scaleFactorXm = 1; + _scaleFactorXd = 1; + _scaleFactorYm = 1; + _scaleFactorYd = 1; + _scalerProc = Normal1x; + } + } else if (_videoMode.screenWidth == 640 && !(OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640))) { + _scaleFactorXm = 1; + _scaleFactorXd = 2; + _scaleFactorYm = 1; + _scaleFactorYd = 2; + _scalerProc = DownscaleAllByHalf; + } else if (_videoMode.screenWidth == 640 && (OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640))) { + _scaleFactorXm = 1; + _scaleFactorXd = 1; + _scaleFactorYm = 1; + _scaleFactorYd = 1; + _scalerProc = Normal1x; + } + + return true; + } else if (CEDevice::hasWideResolution()) { +#ifdef USE_ARM_SCALER_ASM + if (_videoMode.mode == GFX_DOUBLESIZE && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) { + if (!_panelVisible && !_overlayVisible && _canBeAspectScaled) { + _scaleFactorXm = 2; + _scaleFactorXd = 1; + _scaleFactorYm = 12; + _scaleFactorYd = 5; + _scalerProc = Normal2xAspect; + _videoMode.aspectRatioCorrection = true; + } else if ((_panelVisible || _overlayVisible) && _canBeAspectScaled) { + _scaleFactorXm = 2; + _scaleFactorXd = 1; + _scaleFactorYm = 2; + _scaleFactorYd = 1; + _scalerProc = Normal2x; + } + return true; + } +#endif + } else if (CEDevice::hasSmartphoneResolution()) { + if (_videoMode.mode != GFX_NORMAL) + return false; + + if (_videoMode.screenWidth > 320) + error("Game resolution not supported on Smartphone"); +#ifdef ARM + _scaleFactorXm = 11; + _scaleFactorXd = 16; +#else + _scaleFactorXm = 2; + _scaleFactorXd = 3; +#endif + _scaleFactorYm = 7; + _scaleFactorYd = 8; + _scalerProc = SmartphoneLandscape; + initZones(); + return true; + } + + return false; +} + +void WINCESdlGraphicsManager::update_game_settings() { + Common::String gameid(ConfMan.get("gameid")); + + // Finish panel initialization + if (!_panelInitialized && !gameid.empty()) { + CEGUI::Panel *panel; + _panelInitialized = true; + // Add the main panel + panel = new CEGUI::Panel(0, 32); + panel->setBackground(IMAGE_PANEL); + + // Save + panel->add(NAME_ITEM_OPTIONS, new CEGUI::ItemAction(ITEM_OPTIONS, POCKET_ACTION_SAVE)); + // Skip + panel->add(NAME_ITEM_SKIP, new CEGUI::ItemAction(ITEM_SKIP, POCKET_ACTION_SKIP)); + // sound +//__XXX__ panel->add(NAME_ITEM_SOUND, new CEGUI::ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &_soundMaster)); + panel->add(NAME_ITEM_SOUND, new CEGUI::ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &OSystem_WINCE3::_soundMaster)); + + // bind keys + panel->add(NAME_ITEM_BINDKEYS, new CEGUI::ItemAction(ITEM_BINDKEYS, POCKET_ACTION_BINDKEYS)); + // portrait/landscape - screen dependent + // FIXME : will still display the portrait/landscape icon when using a scaler (but will be disabled) + if (ConfMan.hasKey("landscape")) { + if (ConfMan.get("landscape")[0] > 57) { + _newOrientation = _orientationLandscape = ConfMan.getBool("landscape"); + //ConfMan.removeKey("landscape", ""); + ConfMan.setInt("landscape", _orientationLandscape); + } else + _newOrientation = _orientationLandscape = ConfMan.getInt("landscape"); + } else { + _newOrientation = _orientationLandscape = 0; + } + panel->add(NAME_ITEM_ORIENTATION, new CEGUI::ItemSwitch(ITEM_VIEW_LANDSCAPE, ITEM_VIEW_PORTRAIT, &_newOrientation, 2)); + _toolbarHandler.add(NAME_MAIN_PANEL, *panel); + _toolbarHandler.setActive(NAME_MAIN_PANEL); + _toolbarHandler.setVisible(true); + + if (_videoMode.mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) { + setGraphicsMode(GFX_NORMAL); + hotswapGFXMode(); + } + + if (_hasSmartphoneResolution) + panel->setVisible(false); + + _saveToolbarState = true; + } + + if (ConfMan.hasKey("no_doubletap_rightclick")) + _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick"); +} + +void WINCESdlGraphicsManager::internUpdateScreen() { + SDL_Surface *srcSurf, *origSurf; + static bool old_overlayVisible = false; + int numRectsOut = 0; + int16 routx, routy, routw, routh, stretch, shakestretch; + + assert(_hwscreen != NULL); + + // bail if the application is minimized, be nice to OS + if (!_hasfocus) { + Sleep(20); + return; + } + + // If the shake position changed, fill the dirty area with blackness + if (_currentShakePos != _newShakePos) { + SDL_Rect blackrect = {0, 0, _videoMode.screenWidth *_scaleFactorXm / _scaleFactorXd, _newShakePos *_scaleFactorYm / _scaleFactorYd}; + if (_videoMode.aspectRatioCorrection) + blackrect.h = real2Aspect(blackrect.h - 1) + 1; + SDL_FillRect(_hwscreen, &blackrect, 0); + _currentShakePos = _newShakePos; + _forceFull = true; + } + + // Make sure the mouse is drawn, if it should be drawn. + drawMouse(); + + // Check whether the palette was changed in the meantime and update the + // screen surface accordingly. + if (_paletteDirtyEnd != 0) { + SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart); + _paletteDirtyEnd = 0; + _forceFull = true; + } + + if (!_overlayVisible) { + origSurf = _screen; + srcSurf = _tmpscreen; + } else { + origSurf = _overlayscreen; + srcSurf = _tmpscreen2; + } + + if (old_overlayVisible != _overlayVisible) { + old_overlayVisible = _overlayVisible; + update_scalers(); + } + + // Force a full redraw if requested + if (_forceFull) { + _numDirtyRects = 1; + + _dirtyRectList[0].x = 0; + if (!_zoomDown) + _dirtyRectList[0].y = 0; + else + _dirtyRectList[0].y = _videoMode.screenHeight / 2; + _dirtyRectList[0].w = _videoMode.screenWidth; + if (!_zoomUp && !_zoomDown) + _dirtyRectList[0].h = _videoMode.screenHeight; + else + _dirtyRectList[0].h = _videoMode.screenHeight / 2; + + _toolbarHandler.forceRedraw(); + } + + // Only draw anything if necessary + if (_numDirtyRects > 0) { + + SDL_Rect *r, *rout; + SDL_Rect dst; + uint32 srcPitch, dstPitch; + SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects; + bool toolbarVisible = _toolbarHandler.visible(); + int toolbarOffset = _toolbarHandler.getOffset(); + + for (r = _dirtyRectList; r != last_rect; ++r) { + dst = *r; + dst.x++; // Shift rect by one since 2xSai needs to access the data around + dst.y++; // any pixel to scale it, and we want to avoid mem access crashes. + // NOTE: This is also known as BLACK MAGIC, copied from the sdl backend + if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0) + error("SDL_BlitSurface failed: %s", SDL_GetError()); + } + + SDL_LockSurface(srcSurf); + SDL_LockSurface(_hwscreen); + + srcPitch = srcSurf->pitch; + dstPitch = _hwscreen->pitch; + + for (r = _dirtyRectList, rout = _dirtyRectOut; r != last_rect; ++r) { + + // always clamp to enclosing, downsampled-grid-aligned rect in the downscaled image + if (_scaleFactorXd != 1) { + stretch = r->x % _scaleFactorXd; + r->x -= stretch; + r->w += stretch; + r->w = (r->x + r->w + _scaleFactorXd - 1) / _scaleFactorXd * _scaleFactorXd - r->x; + } + if (_scaleFactorYd != 1) { + stretch = r->y % _scaleFactorYd; + r->y -= stretch; + r->h += stretch; + r->h = (r->y + r->h + _scaleFactorYd - 1) / _scaleFactorYd * _scaleFactorYd - r->y; + } + + // transform + shakestretch = _currentShakePos * _scaleFactorYm / _scaleFactorYd; + routx = r->x * _scaleFactorXm / _scaleFactorXd; // locate position in scaled screen + routy = r->y * _scaleFactorYm / _scaleFactorYd + shakestretch; // adjust for shake offset + routw = r->w * _scaleFactorXm / _scaleFactorXd; + routh = r->h * _scaleFactorYm / _scaleFactorYd - shakestretch; + + // clipping destination rectangle inside device screen (more strict, also more tricky but more stable) + // note that all current scalers do not make dst rect exceed left/right, unless chosen badly (FIXME) + if (_zoomDown) routy -= 240; // adjust for zoom position + if (routy + routh < 0) continue; + if (routy < 0) { + routh += routy; + r->y -= routy * _scaleFactorYd / _scaleFactorYm; + routy = 0; + r->h = routh * _scaleFactorYd / _scaleFactorYm; + } + if (_orientationLandscape) { + if (routy > OSystem_WINCE3::getScreenWidth()) continue; + if (routy + routh > OSystem_WINCE3::getScreenWidth()) { + routh = OSystem_WINCE3::getScreenWidth() - routy; + r->h = routh * _scaleFactorYd / _scaleFactorYm; + } + } else { + if (routy > OSystem_WINCE3::getScreenHeight()) continue; + if (routy + routh > OSystem_WINCE3::getScreenHeight()) { + routh = OSystem_WINCE3::getScreenHeight() - routy; + r->h = routh * _scaleFactorYd / _scaleFactorYm; + } + } + + // check if the toolbar is overwritten + if (toolbarVisible && r->y + r->h >= toolbarOffset) + _toolbarHandler.forceRedraw(); + + // blit it (with added voodoo from the sdl backend, shifting the source rect again) + _scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, + (byte *)_hwscreen->pixels + routx * 2 + routy * dstPitch, dstPitch, + r->w, r->h - _currentShakePos); + + // add this rect to output + rout->x = routx; + rout->y = routy - shakestretch; + rout->w = routw; + rout->h = routh + shakestretch; + numRectsOut++; + rout++; + + } + SDL_UnlockSurface(srcSurf); + SDL_UnlockSurface(_hwscreen); + } + // Add the toolbar if needed + SDL_Rect toolbar_rect[1]; + if (_panelVisible && _toolbarHandler.draw(_toolbarLow, &toolbar_rect[0])) { + // It can be drawn, scale it + uint32 srcPitch, dstPitch; + SDL_Surface *toolbarSurface; + ScalerProc *toolbarScaler; + + if (_videoMode.screenHeight > 240) { + if (!_toolbarHighDrawn) { + // Resize the toolbar + SDL_LockSurface(_toolbarLow); + SDL_LockSurface(_toolbarHigh); + Normal2x((byte *)_toolbarLow->pixels, _toolbarLow->pitch, (byte *)_toolbarHigh->pixels, _toolbarHigh->pitch, toolbar_rect[0].w, toolbar_rect[0].h); + SDL_UnlockSurface(_toolbarHigh); + SDL_UnlockSurface(_toolbarLow); + _toolbarHighDrawn = true; + } + toolbar_rect[0].w *= 2; + toolbar_rect[0].h *= 2; + toolbarSurface = _toolbarHigh; + } else + toolbarSurface = _toolbarLow; + + drawToolbarMouse(toolbarSurface, true); // draw toolbar mouse if applicable + + // Apply the appropriate scaler + SDL_LockSurface(toolbarSurface); + SDL_LockSurface(_hwscreen); + srcPitch = toolbarSurface->pitch; + dstPitch = _hwscreen->pitch; + + toolbarScaler = _scalerProc; + if (_videoMode.scaleFactor == 2) + toolbarScaler = Normal2x; + else if (_videoMode.scaleFactor == 3) + toolbarScaler = Normal3x; + toolbarScaler((byte *)toolbarSurface->pixels, srcPitch, + (byte *)_hwscreen->pixels + (_toolbarHandler.getOffset() * _scaleFactorYm / _scaleFactorYd * dstPitch), + dstPitch, toolbar_rect[0].w, toolbar_rect[0].h); + SDL_UnlockSurface(toolbarSurface); + SDL_UnlockSurface(_hwscreen); + + // And blit it + toolbar_rect[0].y = _toolbarHandler.getOffset(); + toolbar_rect[0].x = toolbar_rect[0].x * _scaleFactorXm / _scaleFactorXd; + toolbar_rect[0].y = toolbar_rect[0].y * _scaleFactorYm / _scaleFactorYd; + toolbar_rect[0].w = toolbar_rect[0].w * _scaleFactorXm / _scaleFactorXd; + toolbar_rect[0].h = toolbar_rect[0].h * _scaleFactorYm / _scaleFactorYd; + + SDL_UpdateRects(_hwscreen, 1, toolbar_rect); + + drawToolbarMouse(toolbarSurface, false); // undraw toolbar mouse + } + + // Finally, blit all our changes to the screen + if (numRectsOut > 0) + SDL_UpdateRects(_hwscreen, numRectsOut, _dirtyRectOut); + + _numDirtyRects = 0; + _forceFull = false; +} + +bool WINCESdlGraphicsManager::setGraphicsMode(int mode) { + + Common::StackLock lock(_graphicsMutex); + int oldScaleFactorXm = _scaleFactorXm; + int oldScaleFactorXd = _scaleFactorXd; + int oldScaleFactorYm = _scaleFactorYm; + int oldScaleFactorYd = _scaleFactorYd; + + _scaleFactorXm = -1; + _scaleFactorXd = -1; + _scaleFactorYm = -1; + _scaleFactorYd = -1; + + if (ConfMan.hasKey("landscape")) + if (ConfMan.get("landscape")[0] > 57) { + _newOrientation = _orientationLandscape = ConfMan.getBool("landscape"); + ConfMan.setInt("landscape", _orientationLandscape); + } else + _newOrientation = _orientationLandscape = ConfMan.getInt("landscape"); + else + _newOrientation = _orientationLandscape = 0; + + if (OSystem_WINCE3::isOzone() && (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640) && mode) + _scaleFactorXm = -1; + + if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape) + _videoMode.mode = GFX_NORMAL; + else + _videoMode.mode = mode; + + if (_scaleFactorXm < 0) { + /* Standard scalers, from the SDL backend */ + switch (_videoMode.mode) { + case GFX_NORMAL: + _videoMode.scaleFactor = 1; + _scalerProc = Normal1x; + break; + case GFX_DOUBLESIZE: + _videoMode.scaleFactor = 2; + _scalerProc = Normal2x; + break; + case GFX_TRIPLESIZE: + _videoMode.scaleFactor = 3; + _scalerProc = Normal3x; + break; + case GFX_2XSAI: + _videoMode.scaleFactor = 2; + _scalerProc = _2xSaI; + break; + case GFX_SUPER2XSAI: + _videoMode.scaleFactor = 2; + _scalerProc = Super2xSaI; + break; + case GFX_SUPEREAGLE: + _videoMode.scaleFactor = 2; + _scalerProc = SuperEagle; + break; + case GFX_ADVMAME2X: + _videoMode.scaleFactor = 2; + _scalerProc = AdvMame2x; + break; + case GFX_ADVMAME3X: + _videoMode.scaleFactor = 3; + _scalerProc = AdvMame3x; + break; +#ifdef USE_HQ_SCALERS + case GFX_HQ2X: + _videoMode.scaleFactor = 2; + _scalerProc = HQ2x; + break; + case GFX_HQ3X: + _videoMode.scaleFactor = 3; + _scalerProc = HQ3x; + break; +#endif + case GFX_TV2X: + _videoMode.scaleFactor = 2; + _scalerProc = TV2x; + break; + case GFX_DOTMATRIX: + _videoMode.scaleFactor = 2; + _scalerProc = DotMatrix; + break; + + default: + error("unknown gfx mode %d", mode); + } + } + + // Check if the scaler can be accepted, if not get back to normal scaler + if (_videoMode.scaleFactor && ((_videoMode.scaleFactor * _videoMode.screenWidth > OSystem_WINCE3::getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenWidth > OSystem_WINCE3::getScreenHeight()) + || (_videoMode.scaleFactor * _videoMode.screenHeight > OSystem_WINCE3::getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenHeight > OSystem_WINCE3::getScreenHeight()))) { + _videoMode.scaleFactor = 1; + _scalerProc = Normal1x; + } + + // Common scaler system was used + if (_scaleFactorXm < 0) { + _scaleFactorXm = _videoMode.scaleFactor; + _scaleFactorXd = 1; + _scaleFactorYm = _videoMode.scaleFactor; + _scaleFactorYd = 1; + } + + _forceFull = true; + + if (oldScaleFactorXm != _scaleFactorXm || + oldScaleFactorXd != _scaleFactorXd || + oldScaleFactorYm != _scaleFactorYm || + oldScaleFactorYd != _scaleFactorYd) { + _scalersChanged = true; + } else + _scalersChanged = false; + + + return true; + +} + +bool WINCESdlGraphicsManager::loadGFXMode() { + int displayWidth; + int displayHeight; + unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE; + + _videoMode.fullscreen = true; // forced + _forceFull = true; + + _tmpscreen = NULL; + + // Recompute scalers if necessary + update_scalers(); + + // Create the surface that contains the 8 bit game data + _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0); + if (_screen == NULL) + error("_screen failed (%s)", SDL_GetError()); + + // Create the surface that contains the scaled graphics in 16 bit mode + // Always use full screen mode to have a "clean screen" + if (!_videoMode.aspectRatioCorrection) { + displayWidth = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd; + displayHeight = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd; + } else { + displayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; + displayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; + } + + switch (_orientationLandscape) { + case 1: + flags |= SDL_LANDSCVIDEO; + break; + case 2: + flags |= SDL_INVLNDVIDEO; + break; + default: + flags |= SDL_PORTRTVIDEO; + } + _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags); + + if (_hwscreen == NULL) { + warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError()); + g_system->quit(); + } + + // see what orientation sdl finally accepted + if (_hwscreen->flags & SDL_PORTRTVIDEO) + _orientationLandscape = _newOrientation = 0; + else if (_hwscreen->flags & SDL_LANDSCVIDEO) + _orientationLandscape = _newOrientation = 1; + else + _orientationLandscape = _newOrientation = 2; + + // Create the surface used for the graphics in 16 bit before scaling, and also the overlay + // Distinguish 555 and 565 mode + if (_hwscreen->format->Rmask == 0x7C00) + InitScalers(555); + else + InitScalers(565); + _overlayFormat.bytesPerPixel = _hwscreen->format->BytesPerPixel; + _overlayFormat.rLoss = _hwscreen->format->Rloss; + _overlayFormat.gLoss = _hwscreen->format->Gloss; + _overlayFormat.bLoss = _hwscreen->format->Bloss; + _overlayFormat.aLoss = _hwscreen->format->Aloss; + _overlayFormat.rShift = _hwscreen->format->Rshift; + _overlayFormat.gShift = _hwscreen->format->Gshift; + _overlayFormat.bShift = _hwscreen->format->Bshift; + _overlayFormat.aShift = _hwscreen->format->Ashift; + + // Need some extra bytes around when using 2xSaI + _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask); + + if (_tmpscreen == NULL) + error("_tmpscreen creation failed (%s)", SDL_GetError()); + + // Overlay + if (CEDevice::hasDesktopResolution()) { + _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0); + if (_overlayscreen == NULL) + error("_overlayscreen failed (%s)", SDL_GetError()); + _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0); + if (_tmpscreen2 == NULL) + error("_tmpscreen2 failed (%s)", SDL_GetError()); + } else { + _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, 0, 0, 0, 0); + if (_overlayscreen == NULL) + error("_overlayscreen failed (%s)", SDL_GetError()); + _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, 0, 0, 0, 0); + if (_tmpscreen2 == NULL) + error("_tmpscreen2 failed (%s)", SDL_GetError()); + } + + // Toolbar + _toolbarHighDrawn = false; + uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16)); // *not* leaking memory here + _toolbarLow = SDL_CreateRGBSurfaceFrom(toolbar_screen, 320, 40, 16, 320 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask); + + if (_toolbarLow == NULL) + error("_toolbarLow failed (%s)", SDL_GetError()); + + if (_videoMode.screenHeight > 240) { + uint16 *toolbar_screen_high = (uint16 *)calloc(640 * 80, sizeof(uint16)); + _toolbarHigh = SDL_CreateRGBSurfaceFrom(toolbar_screen_high, 640, 80, 16, 640 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask); + + if (_toolbarHigh == NULL) + error("_toolbarHigh failed (%s)", SDL_GetError()); + } else + _toolbarHigh = NULL; + + // keyboard cursor control, some other better place for it? + _sdlEventSource->resetKeyboadEmulation(_videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd - 1, _videoMode.screenHeight * _scaleFactorXm / _scaleFactorXd - 1); + + return true; +} + +void WINCESdlGraphicsManager::unloadGFXMode() { + if (_screen) { + SDL_FreeSurface(_screen); + _screen = NULL; + } + + if (_hwscreen) { + SDL_FreeSurface(_hwscreen); + _hwscreen = NULL; + } + + if (_tmpscreen) { + SDL_FreeSurface(_tmpscreen); + _tmpscreen = NULL; + } +} + +bool WINCESdlGraphicsManager::hotswapGFXMode() { + if (!_screen) + return false; + + // Keep around the old _screen & _tmpscreen so we can restore the screen data + // after the mode switch. (also for the overlay) + SDL_Surface *old_screen = _screen; + SDL_Surface *old_tmpscreen = _tmpscreen; + SDL_Surface *old_overlayscreen = _overlayscreen; + SDL_Surface *old_tmpscreen2 = _tmpscreen2; + + // Release the HW screen surface + SDL_FreeSurface(_hwscreen); + + // Release toolbars + free(_toolbarLow->pixels); + SDL_FreeSurface(_toolbarLow); + if (_toolbarHigh) { + free(_toolbarHigh->pixels); + SDL_FreeSurface(_toolbarHigh); + } + + // Setup the new GFX mode + if (!loadGFXMode()) { + unloadGFXMode(); + + _screen = old_screen; + _overlayscreen = old_overlayscreen; + + return false; + } + + // reset palette + SDL_SetColors(_screen, _currentPalette, 0, 256); + + // Restore old screen content + SDL_BlitSurface(old_screen, NULL, _screen, NULL); + SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL); + if (_overlayVisible) { + SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL); + SDL_BlitSurface(old_tmpscreen2, NULL, _tmpscreen2, NULL); + } + + // Free the old surfaces + SDL_FreeSurface(old_screen); + SDL_FreeSurface(old_tmpscreen); + SDL_FreeSurface(old_overlayscreen); + SDL_FreeSurface(old_tmpscreen2); + + // Blit everything back to the screen + _toolbarHighDrawn = false; + internUpdateScreen(); + + // Make sure that a Common::EVENT_SCREEN_CHANGED gets sent later -> FIXME this crashes when no game has been loaded. +// _modeChanged = true; + + return true; +} + +bool WINCESdlGraphicsManager::saveScreenshot(const char *filename) { + assert(_hwscreen != NULL); + + Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends + SDL_SaveBMP(_hwscreen, filename); + return true; +} + +void WINCESdlGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + assert(_transactionMode == kTransactionNone); + + if (_overlayscreen == NULL) + return; + + // Clip the coordinates + if (x < 0) { + w += x; + buf -= x; + x = 0; + } + + if (y < 0) { + h += y; + buf -= y * pitch; + y = 0; + } + + if (w > _videoMode.overlayWidth - x) { + w = _videoMode.overlayWidth - x; + } + + if (h > _videoMode.overlayHeight - y) { + h = _videoMode.overlayHeight - y; + } + + if (w <= 0 || h <= 0) + return; + + // Mark the modified region as dirty + addDirtyRect(x, y, w, h); + + undrawMouse(); + + if (SDL_LockSurface(_overlayscreen) == -1) + error("SDL_LockSurface failed: %s", SDL_GetError()); + + byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2; + do { + memcpy(dst, buf, w * 2); + dst += _overlayscreen->pitch; + buf += pitch; + } while (--h); + + SDL_UnlockSurface(_overlayscreen); +} + +void WINCESdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) { + assert(_transactionMode == kTransactionNone); + assert(src); + + if (_screen == NULL) + return; + + Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends + + /* Clip the coordinates */ + if (x < 0) { + w += x; + src -= x; + x = 0; + } + + if (y < 0) { + h += y; + src -= y * pitch; + y = 0; + } + + if (w > _videoMode.screenWidth - x) { + w = _videoMode.screenWidth - x; + } + + if (h > _videoMode.screenHeight - y) { + h = _videoMode.screenHeight - y; + } + + if (w <= 0 || h <= 0) + return; + + addDirtyRect(x, y, w, h); + + undrawMouse(); + + // Try to lock the screen surface + if (SDL_LockSurface(_screen) == -1) + error("SDL_LockSurface failed: %s", SDL_GetError()); + + byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x; + + if (_videoMode.screenWidth == pitch && pitch == w) { + memcpy(dst, src, h * w); + } else { + do { + memcpy(dst, src, w); + src += pitch; + dst += _videoMode.screenWidth; + } while (--h); + } + + // Unlock the screen surface + SDL_UnlockSurface(_screen); +} + +void WINCESdlGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { + + undrawMouse(); + if (w == 0 || h == 0) + return; + + _mouseCurState.w = w; + _mouseCurState.h = h; + + _mouseHotspotX = hotspot_x; + _mouseHotspotY = hotspot_y; + + _mouseKeyColor = keycolor; + + free(_mouseData); + + _mouseData = (byte *) malloc(w * h); + memcpy(_mouseData, buf, w * h); + + if (w > _mouseBackupDim || h > _mouseBackupDim) { + // mouse has been undrawn, adjust sprite backup area + free(_mouseBackupOld); + free(_mouseBackupToolbar); + uint16 tmp = (w > h) ? w : h; + _mouseBackupOld = (byte *) malloc(tmp * tmp * 2); // can hold 8bpp (playfield) or 16bpp (overlay) data + _mouseBackupToolbar = (uint16 *) malloc(tmp * tmp * 2); // 16 bpp + _mouseBackupDim = tmp; + } +} + +void WINCESdlGraphicsManager::adjustMouseEvent(const Common::Event &event) { + if (!event.synthetic) { + Common::Event newEvent(event); + newEvent.synthetic = true; + if (!_overlayVisible) { + /* + newEvent.mouse.x = newEvent.mouse.x * _scaleFactorXd / _scaleFactorXm; + newEvent.mouse.y = newEvent.mouse.y * _scaleFactorYd / _scaleFactorYm; + newEvent.mouse.x /= _videoMode.scaleFactor; + newEvent.mouse.y /= _videoMode.scaleFactor; + */ + if (_videoMode.aspectRatioCorrection) + newEvent.mouse.y = aspect2Real(newEvent.mouse.y); + } + g_system->getEventManager()->pushEvent(newEvent); + } +} + +void WINCESdlGraphicsManager::setMousePos(int x, int y) { + if (x != _mouseCurState.x || y != _mouseCurState.y) { + undrawMouse(); + _mouseCurState.x = x; + _mouseCurState.y = y; + updateScreen(); + } +} + +Graphics::Surface *WINCESdlGraphicsManager::lockScreen() { + // Make sure mouse pointer is not painted over the playfield at the time of locking + undrawMouse(); + return SdlGraphicsManager::lockScreen(); +} + +void WINCESdlGraphicsManager::showOverlay() { + assert(_transactionMode == kTransactionNone); + + if (_overlayVisible) + return; + + undrawMouse(); + _overlayVisible = true; + update_scalers(); + clearOverlay(); +} + +void WINCESdlGraphicsManager::hideOverlay() { + assert(_transactionMode == kTransactionNone); + + if (!_overlayVisible) + return; + + undrawMouse(); + _overlayVisible = false; + clearOverlay(); + _forceFull = true; +} + +void WINCESdlGraphicsManager::blitCursor() { +} + +void WINCESdlGraphicsManager::drawToolbarMouse(SDL_Surface *surf, bool draw) { + + if (!_mouseData || !_usesEmulatedMouse) + return; + + int x = _mouseCurState.x - _mouseHotspotX; + int y = _mouseCurState.y - _mouseHotspotY - _toolbarHandler.getOffset(); + int w = _mouseCurState.w; + int h = _mouseCurState.h; + byte color; + const byte *src = _mouseData; + int width; + + // clip + if (x < 0) { + w += x; + src -= x; + x = 0; + } + if (y < 0) { + h += y; + src -= y * _mouseCurState.w; + y = 0; + } + if (w > surf->w - x) + w = surf->w - x; + if (h > surf->h - y) + h = surf->h - y; + if (w <= 0 || h <= 0) + return; + + if (SDL_LockSurface(surf) == -1) + error("SDL_LockSurface failed at internDrawToolbarMouse: %s", SDL_GetError()); + + uint16 *bak = _mouseBackupToolbar; // toolbar surfaces are 16bpp + uint16 *dst; + dst = (uint16 *)surf->pixels + y * surf->w + x; + + if (draw) { // blit it + while (h > 0) { + width = w; + while (width > 0) { + *bak++ = *dst; + color = *src++; + if (color != _mouseKeyColor) // transparent color + *dst = 0xFFFF; + dst++; + width--; + } + src += _mouseCurState.w - w; + bak += _mouseBackupDim - w; + dst += surf->w - w; + h--; + } + } else { // restore bg + for (y = 0; y < h; ++y, bak += _mouseBackupDim, dst += surf->w) + memcpy(dst, bak, w << 1); + } + + SDL_UnlockSurface(surf); +} + +void WINCESdlGraphicsManager::warpMouse(int x, int y) { + if (_mouseCurState.x != x || _mouseCurState.y != y) { + SDL_WarpMouse(x * _scaleFactorXm / _scaleFactorXd, y * _scaleFactorYm / _scaleFactorYd); + + // SDL_WarpMouse() generates a mouse movement event, so + // set_mouse_pos() would be called eventually. However, the + // cannon script in CoMI calls this function twice each time + // the cannon is reloaded. Unless we update the mouse position + // immediately the second call is ignored, causing the cannon + // to change its aim. + + setMousePos(x, y); + } +} + +void WINCESdlGraphicsManager::unlockScreen() { + SdlGraphicsManager::unlockScreen(); +} + +void WINCESdlGraphicsManager::internDrawMouse() { + if (!_mouseNeedsRedraw || !_mouseVisible || !_mouseData) + return; + + int x = _mouseCurState.x - _mouseHotspotX; + int y = _mouseCurState.y - _mouseHotspotY; + int w = _mouseCurState.w; + int h = _mouseCurState.h; + byte color; + const byte *src = _mouseData; // Image representing the mouse + int width; + + // clip the mouse rect, and adjust the src pointer accordingly + if (x < 0) { + w += x; + src -= x; + x = 0; + } + if (y < 0) { + h += y; + src -= y * _mouseCurState.w; + y = 0; + } + + if (w > _videoMode.screenWidth - x) + w = _videoMode.screenWidth - x; + if (h > _videoMode.screenHeight - y) + h = _videoMode.screenHeight - y; + + // Quick check to see if anything has to be drawn at all + if (w <= 0 || h <= 0) + return; + + // Draw the mouse cursor; backup the covered area in "bak" + if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1) + error("SDL_LockSurface failed: %s", SDL_GetError()); + + // Mark as dirty + addDirtyRect(x, y, w, h); + + if (!_overlayVisible) { + byte *bak = _mouseBackupOld; // Surface used to backup the area obscured by the mouse + byte *dst; // Surface we are drawing into + + dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x; + while (h > 0) { + width = w; + while (width > 0) { + *bak++ = *dst; + color = *src++; + if (color != _mouseKeyColor) // transparent, don't draw + *dst = color; + dst++; + width--; + } + src += _mouseCurState.w - w; + bak += _mouseBackupDim - w; + dst += _videoMode.screenWidth - w; + h--; + } + + } else { + uint16 *bak = (uint16 *)_mouseBackupOld; // Surface used to backup the area obscured by the mouse + byte *dst; // Surface we are drawing into + + dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2; + while (h > 0) { + width = w; + while (width > 0) { + *bak++ = *(uint16 *)dst; + color = *src++; + if (color != 0xFF) // 0xFF = transparent, don't draw + *(uint16 *)dst = SDL_MapRGB(_overlayscreen->format, _currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b); + dst += 2; + width--; + } + src += _mouseCurState.w - w; + bak += _mouseBackupDim - w; + dst += _overlayscreen->pitch - w * 2; + h--; + } + } + + SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen); + + // Finally, set the flag to indicate the mouse has been drawn + _mouseNeedsRedraw = false; +} + +void WINCESdlGraphicsManager::undrawMouse() { + assert(_transactionMode == kTransactionNone); + + if (_mouseNeedsRedraw) + return; + + int old_mouse_x = _mouseCurState.x - _mouseHotspotX; + int old_mouse_y = _mouseCurState.y - _mouseHotspotY; + int old_mouse_w = _mouseCurState.w; + int old_mouse_h = _mouseCurState.h; + + // clip the mouse rect, and adjust the src pointer accordingly + if (old_mouse_x < 0) { + old_mouse_w += old_mouse_x; + old_mouse_x = 0; + } + if (old_mouse_y < 0) { + old_mouse_h += old_mouse_y; + old_mouse_y = 0; + } + + if (old_mouse_w > _videoMode.screenWidth - old_mouse_x) + old_mouse_w = _videoMode.screenWidth - old_mouse_x; + if (old_mouse_h > _videoMode.screenHeight - old_mouse_y) + old_mouse_h = _videoMode.screenHeight - old_mouse_y; + + // Quick check to see if anything has to be drawn at all + if (old_mouse_w <= 0 || old_mouse_h <= 0) + return; + + + if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1) + error("SDL_LockSurface failed: %s", SDL_GetError()); + + int y; + if (!_overlayVisible) { + byte *dst, *bak = _mouseBackupOld; + + // No need to do clipping here, since drawMouse() did that already + dst = (byte *)_screen->pixels + old_mouse_y * _videoMode.screenWidth + old_mouse_x; + for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _videoMode.screenWidth) + memcpy(dst, bak, old_mouse_w); + } else { + byte *dst; + uint16 *bak = (uint16 *)_mouseBackupOld; + + // No need to do clipping here, since drawMouse() did that already + dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2; + for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _overlayscreen->pitch) + memcpy(dst, bak, old_mouse_w << 1); + } + + addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h); + + SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen); + + _mouseNeedsRedraw = true; +} + +void WINCESdlGraphicsManager::drawMouse() { + if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset() && !_usesEmulatedMouse) && !_forceHideMouse) + internDrawMouse(); +} + +bool WINCESdlGraphicsManager::showMouse(bool visible) { + if (_mouseVisible == visible) + return visible; + + if (visible == false) + undrawMouse(); + + bool last = _mouseVisible; + _mouseVisible = visible; + _mouseNeedsRedraw = true; + + return last; +} + +void WINCESdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool mouseRect) { + + if (_forceFull || _paletteDirtyEnd) + return; + + SdlGraphicsManager::addDirtyRect(x, y, w, h, false); +} + +void WINCESdlGraphicsManager::swap_panel_visibility() { + //if (!_forcePanelInvisible && !_panelStateForced) { + if (_zoomDown || _zoomUp) + return; + + if (_panelVisible) { + if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD) + _panelVisible = !_panelVisible; + else + _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); + } else { + _toolbarHandler.setActive(NAME_MAIN_PANEL); + _panelVisible = !_panelVisible; + } + _toolbarHandler.setVisible(_panelVisible); + _toolbarHighDrawn = false; + + if (_videoMode.screenHeight > 240) + addDirtyRect(0, 400, 640, 80); + else + addDirtyRect(0, 200, 320, 40); + + if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible) + internUpdateScreen(); + else { + update_scalers(); + hotswapGFXMode(); + } + //} +} + +void WINCESdlGraphicsManager::swap_panel() { + _toolbarHighDrawn = false; + //if (!_panelStateForced) { + if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible) + _toolbarHandler.setActive(NAME_MAIN_PANEL); + else + _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); + + if (_videoMode.screenHeight > 240) + addDirtyRect(0, 400, 640, 80); + else + addDirtyRect(0, 200, 320, 40); + + _toolbarHandler.setVisible(true); + if (!_panelVisible) { + _panelVisible = true; + update_scalers(); + hotswapGFXMode(); + } + //} +} + +void WINCESdlGraphicsManager::swap_smartphone_keyboard() { + _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); + _panelVisible = !_panelVisible; + _toolbarHandler.setVisible(_panelVisible); + if (_videoMode.screenHeight > 240) + addDirtyRect(0, 0, 640, 80); + else + addDirtyRect(0, 0, 320, 40); + internUpdateScreen(); +} + +void WINCESdlGraphicsManager::swap_zoom_up() { + if (_zoomUp) { + // restore visibility + _toolbarHandler.setVisible(_saveToolbarZoom); + // restore scaler + _scaleFactorYd = 2; + _scalerProc = DownscaleAllByHalf; + _zoomUp = false; + _zoomDown = false; + } else { + // only active if running on a PocketPC + if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf) + return; + if (_scalerProc == DownscaleAllByHalf) { + _saveToolbarZoom = _toolbarHandler.visible(); + _toolbarHandler.setVisible(false); + // set zoom scaler + _scaleFactorYd = 1; + _scalerProc = DownscaleHorizByHalf; + } + + _zoomDown = false; + _zoomUp = true; + } + // redraw whole screen + addDirtyRect(0, 0, 640, 480); + internUpdateScreen(); +} + +void WINCESdlGraphicsManager::swap_zoom_down() { + if (_zoomDown) { + // restore visibility + _toolbarHandler.setVisible(_saveToolbarZoom); + // restore scaler + _scaleFactorYd = 2; + _scalerProc = DownscaleAllByHalf; + _zoomDown = false; + _zoomUp = false; + } else { + // only active if running on a PocketPC + if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf) + return; + if (_scalerProc == DownscaleAllByHalf) { + _saveToolbarZoom = _toolbarHandler.visible(); + _toolbarHandler.setVisible(false); + // set zoom scaler + _scaleFactorYd = 1; + _scalerProc = DownscaleHorizByHalf; + } + + _zoomUp = false; + _zoomDown = true; + } + // redraw whole screen + addDirtyRect(0, 0, 640, 480); + internUpdateScreen(); +} + +void WINCESdlGraphicsManager::swap_mouse_visibility() { + _forceHideMouse = !_forceHideMouse; + if (_forceHideMouse) + undrawMouse(); +} + +// Smartphone actions +void WINCESdlGraphicsManager::initZones() { + int i; + + _currentZone = 0; + for (i = 0; i < TOTAL_ZONES; i++) { + _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)) * _scaleFactorXm / _scaleFactorXd; + _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)) * _scaleFactorYm / _scaleFactorYd; + } +} + +void WINCESdlGraphicsManager::smartphone_rotate_display() { + _orientationLandscape = _newOrientation = _orientationLandscape == 1 ? 2 : 1; + ConfMan.setInt("landscape", _orientationLandscape); + ConfMan.flushToDisk(); + hotswapGFXMode(); +} + +void WINCESdlGraphicsManager::create_toolbar() { + CEGUI::PanelKeyboard *keyboard; + + // Add the keyboard + keyboard = new CEGUI::PanelKeyboard(PANEL_KEYBOARD); + _toolbarHandler.add(NAME_PANEL_KEYBOARD, *keyboard); + _toolbarHandler.setVisible(false); +} + +WINCESdlGraphicsManager::zoneDesc WINCESdlGraphicsManager::_zones[TOTAL_ZONES] = { + { 0, 0, 320, 145 }, + { 0, 145, 150, 55 }, + { 150, 145, 170, 55 } +}; + +#endif /* _WIN32_WCE */ + diff --git a/backends/graphics/wincesdl/wincesdl-graphics.h b/backends/graphics/wincesdl/wincesdl-graphics.h new file mode 100644 index 0000000000..c8d683b158 --- /dev/null +++ b/backends/graphics/wincesdl/wincesdl-graphics.h @@ -0,0 +1,206 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_WINCE_SDL_H +#define BACKENDS_GRAPHICS_WINCE_SDL_H + +#include "backends/graphics/sdl/sdl-graphics.h" +#include "backends/platform/wince/CEgui/CEGUI.h" + +// Internal GUI names +#define NAME_MAIN_PANEL "MainPanel" +#define NAME_PANEL_KEYBOARD "Keyboard" +#define NAME_ITEM_OPTIONS "Options" +#define NAME_ITEM_SKIP "Skip" +#define NAME_ITEM_SOUND "Sound" +#define NAME_ITEM_ORIENTATION "Orientation" +#define NAME_ITEM_BINDKEYS "Bindkeys" + +#define TOTAL_ZONES 3 + +extern bool _hasSmartphoneResolution; + +class WINCESdlGraphicsManager : public SdlGraphicsManager { +public: + WINCESdlGraphicsManager(SdlEventSource *sdlEventSource); + + const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); + + bool hasFeature(OSystem::Feature f); + void setFeatureState(OSystem::Feature f, bool enable); + bool getFeatureState(OSystem::Feature f); + + int getDefaultGraphicsMode() const; + bool setGraphicsMode(int mode); + bool loadGFXMode(); + void unloadGFXMode(); + bool hotswapGFXMode(); + + // Overloaded from SDL backend (toolbar handling) + void drawMouse(); + // Overloaded from SDL backend (new scaler handling) + void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false); + // Overloaded from SDL backend (new scaler handling) + void warpMouse(int x, int y); + + // Update the dirty areas of the screen + void internUpdateScreen(); + bool saveScreenshot(const char *filename); + + // Overloaded from SDL_Common (FIXME) + void internDrawMouse(); + void undrawMouse(); + bool showMouse(bool visible); + void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend + void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); + void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME) + Graphics::Surface *lockScreen(); + void unlockScreen(); + void blitCursor(); + void showOverlay(); + void hideOverlay(); + void setMousePos(int x, int y); + + // GUI and action stuff + void swap_panel_visibility(); + void swap_panel(); + void swap_smartphone_keyboard(); + void swap_zoom_up(); + void swap_zoom_down(); + void swap_mouse_visibility(); + + +//#ifdef WIN32_PLATFORM_WFSP + void move_cursor_up(); + void move_cursor_down(); + void move_cursor_left(); + void move_cursor_right(); + + void retrieve_mouse_location(int &x, int &y); + void switch_zone(); + + void add_right_click(bool pushed); + void add_left_click(bool pushed); + + void initZones(); + void smartphone_rotate_display(); +//#endif + + bool _panelInitialized; // only initialize the toolbar once + bool _noDoubleTapRMB; // disable double tap -> rmb click + + CEGUI::ToolbarHandler _toolbarHandler; + + bool _toolbarHighDrawn; // cache toolbar 640x80 + int _newOrientation; // new orientation + int _orientationLandscape; // current orientation + + int _scaleFactorXm; // scaler X * + int _scaleFactorXd; // scaler X / + int _scaleFactorYm; // scaler Y * + int _scaleFactorYd; // scaler Y / + + bool _hasfocus; // scummvm has the top window + + bool hasPocketPCResolution(); + bool hasDesktopResolution(); + bool hasSquareQVGAResolution(); + bool hasWideResolution() const; + + MousePos _mouseCurState; + + bool _zoomUp; // zooming up mode + bool _zoomDown; // zooming down mode + + bool _usesEmulatedMouse; // emulated mousemove ever been used in this session + + int _mouseXZone[TOTAL_ZONES]; + int _mouseYZone[TOTAL_ZONES]; + int _currentZone; + + // Smartphone specific variables + int _lastKeyPressed; // last key pressed + int _keyRepeat; // number of time the last key was repeated + int _keyRepeatTime; // elapsed time since the key was pressed + int _keyRepeatTrigger; // minimum time to consider the key was repeated + + struct zoneDesc { + int x; + int y; + int width; + int height; + }; + + static zoneDesc _zones[TOTAL_ZONES]; + +protected: + virtual void adjustMouseEvent(const Common::Event &event); + +private: + bool update_scalers(); + void update_game_settings(); + void drawToolbarMouse(SDL_Surface *surf, bool draw); + + void create_toolbar(); + bool _panelVisible; // panel visibility + bool _panelStateForced; // panel visibility forced by external call + String _saveActiveToolbar; // save active toolbar when forced + + bool _canBeAspectScaled; // game screen size allows for aspect scaling + + SDL_Rect _dirtyRectOut[NUM_DIRTY_RECT]; + bool _scalersChanged; + + bool isOzone(); + + bool _saveToolbarState; // save visibility when forced + bool _saveToolbarZoom; // save visibility when zooming + + SDL_Surface *_toolbarLow; // toolbar 320x40 + SDL_Surface *_toolbarHigh; // toolbar 640x80 + + // Mouse + int _mouseHotspotX, _mouseHotspotY; + byte *_mouseBackupOld; + uint16 *_mouseBackupToolbar; + uint16 _mouseBackupDim; + + bool _forceHideMouse; // force invisible mouse cursor + + // Smartphone specific variables + void loadDeviceConfigurationElement(Common::String element, int &value, int defaultValue); + int _repeatX; // repeat trigger for left and right cursor moves + int _repeatY; // repeat trigger for up and down cursor moves + int _stepX1; // offset for left and right cursor moves (slowest) + int _stepX2; // offset for left and right cursor moves (faster) + int _stepX3; // offset for left and right cursor moves (fastest) + int _stepY1; // offset for up and down cursor moves (slowest) + int _stepY2; // offset for up and down cursor moves (faster) + int _stepY3; // offset for up and down cursor moves (fastest) +}; + +#endif /* BACKENDS_GRAPHICS_WINCE_SDL_H */ + diff --git a/backends/keymapper/hardware-key.h b/backends/keymapper/hardware-key.h index 7c608a53fc..b6d9dbf042 100644 --- a/backends/keymapper/hardware-key.h +++ b/backends/keymapper/hardware-key.h @@ -31,6 +31,7 @@ #ifdef ENABLE_KEYMAPPER #include "backends/keymapper/types.h" +#include "common/textconsole.h" namespace Common { diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index 2f913055fc..8edc26a526 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -26,6 +26,7 @@ #ifdef ENABLE_KEYMAPPER +#include "common/system.h" #include "gui/gui-manager.h" #include "gui/widgets/popup.h" #include "gui/widgets/scrollbar.h" diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h index 2c0e79a79d..5721d368a4 100644 --- a/backends/keymapper/remap-dialog.h +++ b/backends/keymapper/remap-dialog.h @@ -33,8 +33,10 @@ #include "gui/dialog.h" namespace GUI { - class PopupWidget; - class ScrollBarWidget; +class ButtonWidget; +class PopUpWidget; +class ScrollBarWidget; +class StaticTextWidget; } namespace Common { diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp index 953b088958..5110734a18 100644 --- a/backends/midi/alsa.cpp +++ b/backends/midi/alsa.cpp @@ -30,6 +30,8 @@ #if defined(USE_ALSA) #include "common/config-manager.h" +#include "common/error.h" +#include "common/textconsole.h" #include "common/util.h" #include "audio/musicplugin.h" #include "audio/mpu401.h" @@ -44,7 +46,7 @@ #if SND_LIB_MAJOR >= 1 || SND_LIB_MINOR >= 6 #define snd_seq_flush_output(x) snd_seq_drain_output(x) -#define snd_seq_set_client_group(x,name) /*nop */ +#define snd_seq_set_client_group(x,name) /*nop */ #define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0) #else /* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */ @@ -53,9 +55,8 @@ #define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) -static int check_permission(snd_seq_port_info_t *pinfo) -{ - if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) { +static int check_permission(snd_seq_port_info_t *pinfo) { + if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) { if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT)) return 1; } @@ -68,10 +69,11 @@ static int check_permission(snd_seq_port_info_t *pinfo) #define ADDR_DELIM ".:" -class MidiDriver_ALSA:public MidiDriver_MPU401 { +class MidiDriver_ALSA : public MidiDriver_MPU401 { public: MidiDriver_ALSA(int client, int port); int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -83,11 +85,12 @@ private: snd_seq_t *seq_handle; int seq_client, seq_port; int my_client, my_port; + // The volume controller value of the first MIDI channel + int8 _channel0Volume; }; MidiDriver_ALSA::MidiDriver_ALSA(int client, int port) - : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0) -{ + : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0), _channel0Volume(127) { memset(&ev, 0, sizeof(ev)); } @@ -114,7 +117,7 @@ int MidiDriver_ALSA::open() { // with those capabilities. my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM port 0", 0, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); + SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (my_port < 0) { snd_seq_close(seq_handle); @@ -208,24 +211,41 @@ void MidiDriver_ALSA::send(uint32 b) { case 0xB0: /* is it this simple ? Wow... */ snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]); + + // We save the volume of the first MIDI channel here to utilize it in + // our workaround for broken USB-MIDI cables. + if (chanID == 0 && midiCmd[1] == 0x07) + _channel0Volume = midiCmd[2]; + send_event(1); break; case 0xC0: snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]); send_event(0); + + // Send a volume change command to work around a firmware bug in common + // USB-MIDI cables. If the first MIDI command in a USB packet is a + // Cx or Dx command, the second command in the packet is dropped + // somewhere. + send(0x07B0 | (_channel0Volume << 16)); break; case 0xD0: snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]); send_event(1); + + // Send a volume change command to work around a firmware bug in common + // USB-MIDI cables. If the first MIDI command in a USB packet is a + // Cx or Dx command, the second command in the packet is dropped + // somewhere. + send(0x07B0 | (_channel0Volume << 16)); break; - case 0xE0:{ - // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4; - // snd_seq_ev_set_pitchbend(&ev, chanID, theBend); - long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; - snd_seq_ev_set_pitchbend(&ev, chanID, theBend); - send_event(1); - } - break; + case 0xE0: { + // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4; + // snd_seq_ev_set_pitchbend(&ev, chanID, theBend); + long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; + snd_seq_ev_set_pitchbend(&ev, chanID, theBend); + send_event(1); + } break; default: warning("Unknown MIDI Command: %08x", (int)b); @@ -280,6 +300,9 @@ typedef Common::List<AlsaDevice> AlsaDevices; AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client) : _name(name), _type(mt), _client(client) { + // Make sure we do not get any trailing spaces to avoid problems when + // storing the name in the configuration file. + _name.trim(); } Common::String AlsaDevice::getName() { diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp index 57251b45e1..cc791cf7c0 100644 --- a/backends/midi/camd.cpp +++ b/backends/midi/camd.cpp @@ -29,6 +29,8 @@ #if defined(__amigaos4__) +#include "common/textconsole.h" +#include "common/error.h" #include "common/endian.h" #include "common/util.h" #include "audio/musicplugin.h" @@ -46,6 +48,7 @@ class MidiDriver_CAMD : public MidiDriver_MPU401 { public: MidiDriver_CAMD(); int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -134,8 +137,8 @@ void MidiDriver_CAMD::sysEx(const byte *msg, uint16 length) { char *MidiDriver_CAMD::getDevice() { char *retname = NULL; - APTR key; - if (key = _ICamd->LockCAMD(CD_Linkages)) { + APTR key = _ICamd->LockCAMD(CD_Linkages); + if (key != NULL) { struct MidiCluster *cluster = _ICamd->NextCluster(NULL); while (cluster && !retname) { diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp index 75c512cad7..52d32cb5e3 100644 --- a/backends/midi/coreaudio.cpp +++ b/backends/midi/coreaudio.cpp @@ -41,6 +41,8 @@ #include "common/config-manager.h" +#include "common/error.h" +#include "common/textconsole.h" #include "common/util.h" #include "audio/musicplugin.h" #include "audio/mpu401.h" @@ -72,7 +74,9 @@ do { \ class MidiDriver_CORE : public MidiDriver_MPU401 { public: MidiDriver_CORE(); + ~MidiDriver_CORE(); int open(); + bool isOpen() const { return _auGraph != 0; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -86,10 +90,18 @@ MidiDriver_CORE::MidiDriver_CORE() : _auGraph(0) { } +MidiDriver_CORE::~MidiDriver_CORE() { + if (_auGraph) { + AUGraphStop(_auGraph); + DisposeAUGraph(_auGraph); + _auGraph = 0; + } +} + int MidiDriver_CORE::open() { OSStatus err = 0; - if (_auGraph) + if (isOpen()) return MERR_ALREADY_OPEN; // Open the Music Device. @@ -176,7 +188,6 @@ bail: void MidiDriver_CORE::close() { MidiDriver_MPU401::close(); - if (_auGraph) { AUGraphStop(_auGraph); DisposeAUGraph(_auGraph); @@ -185,7 +196,7 @@ void MidiDriver_CORE::close() { } void MidiDriver_CORE::send(uint32 b) { - assert(_auGraph != NULL); + assert(isOpen()); byte status_byte = (b & 0x000000FF); byte first_byte = (b & 0x0000FF00) >> 8; @@ -198,7 +209,7 @@ void MidiDriver_CORE::sysEx(const byte *msg, uint16 length) { unsigned char buf[266]; assert(length + 2 <= ARRAYSIZE(buf)); - assert(_auGraph != NULL); + assert(isOpen()); // Add SysEx frame buf[0] = 0xF0; diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp index c0663352cb..87cd6307ba 100644 --- a/backends/midi/coremidi.cpp +++ b/backends/midi/coremidi.cpp @@ -30,6 +30,8 @@ #ifdef MACOSX #include "common/config-manager.h" +#include "common/error.h" +#include "common/textconsole.h" #include "common/util.h" #include "audio/musicplugin.h" #include "audio/mpu401.h" @@ -56,6 +58,7 @@ public: MidiDriver_CoreMIDI(); ~MidiDriver_CoreMIDI(); int open(); + bool isOpen() const { return mOutPort != 0 && mDest != 0; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -80,7 +83,7 @@ MidiDriver_CoreMIDI::~MidiDriver_CoreMIDI() { } int MidiDriver_CoreMIDI::open() { - if (mDest) + if (isOpen()) return MERR_ALREADY_OPEN; OSStatus err = noErr; @@ -106,7 +109,7 @@ int MidiDriver_CoreMIDI::open() { void MidiDriver_CoreMIDI::close() { MidiDriver_MPU401::close(); - if (mOutPort && mDest) { + if (isOpen()) { MIDIPortDispose(mOutPort); mOutPort = 0; mDest = 0; @@ -114,8 +117,7 @@ void MidiDriver_CoreMIDI::close() { } void MidiDriver_CoreMIDI::send(uint32 b) { - assert(mOutPort != 0); - assert(mDest != 0); + assert(isOpen()); // Extract the MIDI data byte status_byte = (b & 0x000000FF); @@ -158,8 +160,7 @@ void MidiDriver_CoreMIDI::send(uint32 b) { } void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) { - assert(mOutPort != 0); - assert(mDest != 0); + assert(isOpen()); byte buf[384]; MIDIPacketList *packetList = (MIDIPacketList *)buf; diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp index f0ab84c934..c4c1968354 100644 --- a/backends/midi/dmedia.cpp +++ b/backends/midi/dmedia.cpp @@ -57,6 +57,7 @@ class MidiDriver_DMEDIA : public MidiDriver_MPU401 { public: MidiDriver_DMEDIA(); int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -179,7 +180,7 @@ void MidiDriver_DMEDIA::sysEx (const byte *msg, uint16 length) { memcpy(buf, msg, length); buf[length] = MD_EOX; event.sysexmsg = buf; - event.msglen = length; + event.msglen = length; event.msg[0] = MD_SYSEX; event.msg[1] = 0; event.msg[2] = 0; diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp index 064129b74a..b90a9b19e0 100644 --- a/backends/midi/seq.cpp +++ b/backends/midi/seq.cpp @@ -35,6 +35,8 @@ #if defined(USE_SEQ_MIDI) +#include "common/error.h" +#include "common/textconsole.h" #include "common/util.h" #include "audio/musicplugin.h" #include "audio/mpu401.h" @@ -55,6 +57,7 @@ class MidiDriver_SEQ : public MidiDriver_MPU401 { public: MidiDriver_SEQ(); int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp index 562c3c7ece..42f829a7a3 100644 --- a/backends/midi/stmidi.cpp +++ b/backends/midi/stmidi.cpp @@ -48,8 +48,9 @@ class MidiDriver_STMIDI : public MidiDriver_MPU401 { public: - MidiDriver_STMIDI() : _isOpen (false) { } + MidiDriver_STMIDI() : _isOpen (false) { } int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -59,7 +60,7 @@ private: }; int MidiDriver_STMIDI::open() { - if ((_isOpen) && (!Bcostat(4))) + if (_isOpen && (!Bcostat(4))) return MERR_ALREADY_OPEN; warning("ST Midi Port Open"); _isOpen = true; @@ -123,36 +124,36 @@ void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) { class StMidiMusicPlugin : public MusicPluginObject { public: - const char *getName() const { - return "STMIDI"; - } + const char *getName() const { + return "STMIDI"; + } - const char *getId() const { - return "stmidi"; - } + const char *getId() const { + return "stmidi"; + } - MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; + MusicDevices getDevices() const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices StMidiMusicPlugin::getDevices() const { - MusicDevices devices; - // TODO: Return a different music type depending on the configuration - // TODO: List the available devices - devices.push_back(MusicDevice(this, "", MT_GM)); - return devices; + MusicDevices devices; + // TODO: Return a different music type depending on the configuration + // TODO: List the available devices + devices.push_back(MusicDevice(this, "", MT_GM)); + return devices; } Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { - *mididriver = new MidiDriver_STMIDI(); + *mididriver = new MidiDriver_STMIDI(); - return Common::kNoError; + return Common::kNoError; } //#if PLUGIN_ENABLED_DYNAMIC(STMIDI) - //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin); + //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin); //#else - REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin); + REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin); //#endif #endif diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp index eeaf872747..dd76196ae0 100644 --- a/backends/midi/timidity.cpp +++ b/backends/midi/timidity.cpp @@ -41,13 +41,13 @@ #if defined(USE_TIMIDITY) -#include "common/util.h" #include "common/endian.h" +#include "common/error.h" #include "common/str.h" +#include "common/textconsole.h" #include "audio/musicplugin.h" #include "audio/mpu401.h" -#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> @@ -92,49 +92,50 @@ class MidiDriver_TIMIDITY : public MidiDriver_MPU401 { public: MidiDriver_TIMIDITY(); - int open(); - void close(); - void send(uint32 b); - void sysEx(const byte *msg, uint16 length); + int open(); + bool isOpen() const { return _isOpen; } + void close(); + void send(uint32 b); + void sysEx(const byte *msg, uint16 length); private: /* standart routine to extract ip address from a string */ - in_addr_t host_to_addr(const char* address); + in_addr_t host_to_addr(const char* address); /* creates a tcp connection to TiMidity server, returns filedesc (like open()) */ - int connect_to_server(const char* hostname, unsigned short tcp_port); + int connect_to_server(const char* hostname, unsigned short tcp_port); /* send command to the server; printf-like; returns reply string */ - char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3); + char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3); /* timidity data socket-related stuff */ - void timidity_meta_seq(int p1, int p2, int p3); - int timidity_sync(int centsec); - int timidity_eot(); + void timidity_meta_seq(int p1, int p2, int p3); + int timidity_sync(int centsec); + int timidity_eot(); /* write() analogue for any midi data */ - void timidity_write_data(const void *buf, size_t nbytes); + void timidity_write_data(const void *buf, size_t nbytes); /* get single line of server reply on control connection */ - int fdgets(char *buff, size_t buff_size); + int fdgets(char *buff, size_t buff_size); /* teardown connection to server */ - void teardown(); + void teardown(); /* close (if needed) and nullify both control and data filedescs */ - void close_all(); + void close_all(); private: - bool _isOpen; - int _device_num; + bool _isOpen; + int _device_num; - int _control_fd; - int _data_fd; + int _control_fd; + int _data_fd; /* buffer for partial data read from _control_fd - from timidity-io.c, see fdgets() */ - char _controlbuffer[BUFSIZ]; - int _controlbuffer_count; /* beginning of read pointer */ - int _controlbuffer_size; /* end of read pointer */ + char _controlbuffer[BUFSIZ]; + int _controlbuffer_count; /* beginning of read pointer */ + int _controlbuffer_size; /* end of read pointer */ }; MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() { @@ -149,9 +150,9 @@ MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() { } int MidiDriver_TIMIDITY::open() { - char *res; - char timidity_host[MAXHOSTNAMELEN]; - int timidity_port, data_port, i; + char *res; + char timidity_host[MAXHOSTNAMELEN]; + int timidity_port, data_port, i; /* count ourselves open */ if (_isOpen) @@ -427,10 +428,9 @@ void MidiDriver_TIMIDITY::timidity_write_data(const void *buf, size_t nbytes) { } int MidiDriver_TIMIDITY::fdgets(char *buff, size_t buff_size) { - int n, len, count, size; + int n, count, size; char *buff_endp = buff + buff_size - 1, *pbuff, *beg; - len = 0; count = _controlbuffer_count; size = _controlbuffer_size; pbuff = _controlbuffer; diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index b585b71fbe..292bbea79e 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -38,6 +38,8 @@ #include "audio/mpu401.h" #include "common/config-manager.h" #include "common/translation.h" +#include "common/textconsole.h" +#include "common/error.h" #include <mmsystem.h> @@ -61,6 +63,7 @@ private: public: MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { } int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -93,6 +96,8 @@ void MidiDriver_WIN::close() { } void MidiDriver_WIN::send(uint32 b) { + assert(_isOpen); + union { DWORD dwData; BYTE bData[4]; diff --git a/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp b/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp index 6b0074862e..93c779ea5f 100644 --- a/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp +++ b/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp @@ -23,7 +23,7 @@ * */ -#if defined(MACOSX) || defined(GP2X) +#if defined(MACOSX) || defined(GP2X) || defined(CAANOO) || defined(GP2XWIZ) #include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h" diff --git a/backends/mixer/sdl/sdl-mixer.cpp b/backends/mixer/sdl/sdl-mixer.cpp index fa2bf3e232..90629954c5 100644 --- a/backends/mixer/sdl/sdl-mixer.cpp +++ b/backends/mixer/sdl/sdl-mixer.cpp @@ -26,8 +26,10 @@ #if defined(SDL_BACKEND) #include "backends/mixer/sdl/sdl-mixer.h" +#include "common/debug.h" #include "common/system.h" #include "common/config-manager.h" +#include "common/textconsole.h" #ifdef GP2X #define SAMPLES_PER_SEC 11025 diff --git a/backends/mixer/wincesdl/wincesdl-mixer.cpp b/backends/mixer/wincesdl/wincesdl-mixer.cpp new file mode 100644 index 0000000000..17cf0ced49 --- /dev/null +++ b/backends/mixer/wincesdl/wincesdl-mixer.cpp @@ -0,0 +1,188 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef _WIN32_WCE + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/config-manager.h" +#include "backends/platform/wince/wince-sdl.h" +#include "backends/mixer/wincesdl/wincesdl-mixer.h" +#include "common/system.h" +#include "common/textconsole.h" + +#ifdef USE_VORBIS +#ifndef USE_TREMOR +#include <vorbis/vorbisfile.h> +#else +#ifdef USE_TREMOLO +#include <tremolo/ivorbisfile.h> +#else +#include <tremor/ivorbisfile.h> +#endif +#endif +#endif + +#define SAMPLES_PER_SEC_OLD 11025 +#define SAMPLES_PER_SEC_NEW 22050 + +WINCESdlMixerManager::WINCESdlMixerManager() { + +} + +WINCESdlMixerManager::~WINCESdlMixerManager() { + +} + +void WINCESdlMixerManager::init() { + SDL_AudioSpec desired; + int thread_priority; + + uint32 sampleRate = compute_sample_rate(); + if (sampleRate == 0) + warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work"); + else if (_mixer && _mixer->getOutputRate() == sampleRate) { + debug(1, "Skipping sound mixer re-init: samplerate is good"); + return; + } + + memset(&desired, 0, sizeof(desired)); + desired.freq = sampleRate; + desired.format = AUDIO_S16SYS; + desired.channels = 2; + desired.samples = 128; + desired.callback = private_sound_proc; + desired.userdata = this; + + // Create the mixer instance + if (_mixer == 0) + _mixer = new Audio::MixerImpl(g_system, sampleRate); + + // Add sound thread priority + if (!ConfMan.hasKey("sound_thread_priority")) + thread_priority = THREAD_PRIORITY_NORMAL; + else + thread_priority = ConfMan.getInt("sound_thread_priority"); + + desired.thread_priority = thread_priority; + + SDL_CloseAudio(); + if (SDL_OpenAudio(&desired, NULL) != 0) { + warning("Could not open audio device: %s", SDL_GetError()); + _mixer->setReady(false); + + } else { + debug(1, "Sound opened OK, mixing at %d Hz", sampleRate); + + // Re-create mixer to match the output rate + int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType); + int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); + int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType); + int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType); + delete _mixer; + _mixer = new Audio::MixerImpl(g_system, sampleRate); + _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2); + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4); + _mixer->setReady(true); + SDL_PauseAudio(0); + } +} + +void WINCESdlMixerManager::private_sound_proc(void *param, byte *buf, int len) { + WINCESdlMixerManager *this_ = (WINCESdlMixerManager *)param; + assert(this_); + + if (this_->_mixer) + this_->_mixer->mixCallback(buf, len); + if (!OSystem_WINCE3::_soundMaster) + memset(buf, 0, len); +} + +uint32 WINCESdlMixerManager::compute_sample_rate() { + uint32 sampleRate; + + // Force at least medium quality FM synthesis for FOTAQ + Common::String gameid(ConfMan.get("gameid")); + if (gameid == "queen") { + if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) || + (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) { + ConfMan.setBool("FM_medium_quality", true); + ConfMan.flushToDisk(); + } + } + // See if the output frequency is forced by the game + if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi") + sampleRate = SAMPLES_PER_SEC_NEW; + else { + if (ConfMan.hasKey("high_sample_rate") && ConfMan.getBool("high_sample_rate")) + sampleRate = SAMPLES_PER_SEC_NEW; + else + sampleRate = SAMPLES_PER_SEC_OLD; + } + +#ifdef USE_VORBIS + // Modify the sample rate on the fly if OGG is involved + if (sampleRate == SAMPLES_PER_SEC_OLD) + if (checkOggHighSampleRate()) + sampleRate = SAMPLES_PER_SEC_NEW; +#endif + + return sampleRate; +} + +#ifdef USE_VORBIS +bool WINCESdlMixerManager::checkOggHighSampleRate() { + char trackFile[255]; + FILE *testFile; + OggVorbis_File *test_ov_file = new OggVorbis_File; + + // FIXME: The following sprintf assumes that "path" is always + // terminated by a path separator. This is *not* true in general. + // This code really should check for the path separator, or even + // better, use the FSNode API. + sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str()); + // Check if we have an OGG audio track + testFile = fopen(trackFile, "rb"); + if (testFile) { + if (!ov_open(testFile, test_ov_file, NULL, 0)) { + bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050); + ov_clear(test_ov_file); + delete test_ov_file; + return highSampleRate; + } + } + + // Do not test for OGG samples - too big and too slow anyway :) + + delete test_ov_file; + return false; +} +#endif + +#endif + diff --git a/backends/mixer/wincesdl/wincesdl-mixer.h b/backends/mixer/wincesdl/wincesdl-mixer.h new file mode 100644 index 0000000000..6c2f1efeee --- /dev/null +++ b/backends/mixer/wincesdl/wincesdl-mixer.h @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MIXER_WINCE_SDL_H +#define BACKENDS_MIXER_WINCE_SDL_H + +#include "backends/mixer/sdl/sdl-mixer.h" + +/** + * SDL mixer manager for WinCE + */ +class WINCESdlMixerManager : public SdlMixerManager { +public: + WINCESdlMixerManager(); + virtual ~WINCESdlMixerManager(); + + virtual void init(); + +private: + +#ifdef USE_VORBIS + bool checkOggHighSampleRate(); +#endif + + static void private_sound_proc(void *param, byte *buf, int len); + uint32 compute_sample_rate(); + +}; + +#endif + diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index 19cba89af3..b691250289 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -26,12 +26,14 @@ #include "backends/modular-backend.h" #include "backends/fs/fs-factory.h" -#include "backends/events/default/default-events.h" -#include "backends/audiocd/default/default-audiocd.h" -#include "backends/mutex/null/null-mutex.h" -#include "backends/graphics/null/null-graphics.h" +#include "backends/audiocd/audiocd.h" +#include "backends/graphics/graphics.h" +#include "backends/mutex/mutex.h" +#include "audio/mixer.h" +#include "common/events.h" #include "gui/message.h" +#include "graphics/pixelformat.h" ModularBackend::ModularBackend() : diff --git a/backends/module.mk b/backends/module.mk index 5a8a63c2a2..e4abf49ba8 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -8,25 +8,36 @@ MODULE_OBJS := \ events/default/default-events.o \ events/dinguxsdl/dinguxsdl-events.o \ events/gp2xsdl/gp2xsdl-events.o \ + events/gph/gph-events.o \ events/linuxmotosdl/linuxmotosdl-events.o \ + events/openpandora/op-events.o \ events/samsungtvsdl/samsungtvsdl-events.o \ events/sdl/sdl-events.o \ events/symbiansdl/symbiansdl-events.o \ + events/webossdl/webossdl-events.o \ + events/wincesdl/wincesdl-events.o \ fs/abstract-fs.o \ fs/stdiostream.o \ + fs/amigaos4/amigaos4-fs.o \ fs/amigaos4/amigaos4-fs-factory.o \ + fs/posix/posix-fs.o \ fs/posix/posix-fs-factory.o \ + fs/symbian/symbian-fs.o \ fs/symbian/symbian-fs-factory.o \ + fs/windows/windows-fs.o \ fs/windows/windows-fs-factory.o \ graphics/dinguxsdl/dinguxsdl-graphics.o \ graphics/gp2xsdl/gp2xsdl-graphics.o \ + graphics/gph/gph-graphics.o \ graphics/linuxmotosdl/linuxmotosdl-graphics.o \ graphics/opengl/glerrorcheck.o \ graphics/opengl/gltexture.o \ graphics/opengl/opengl-graphics.o \ graphics/openglsdl/openglsdl-graphics.o \ + graphics/openpandora/op-graphics.o \ graphics/sdl/sdl-graphics.o \ graphics/symbiansdl/symbiansdl-graphics.o \ + graphics/wincesdl/wincesdl-graphics.o \ keymapper/action.o \ keymapper/keymap.o \ keymapper/keymapper.o \ @@ -44,6 +55,7 @@ MODULE_OBJS := \ mixer/doublebuffersdl/doublebuffersdl-mixer.o \ mixer/sdl/sdl-mixer.o \ mixer/symbiansdl/symbiansdl-mixer.o \ + mixer/wincesdl/wincesdl-mixer.o \ mutex/sdl/sdl-mutex.o \ plugins/elf/elf-loader.o \ plugins/elf/mips-loader.o \ @@ -67,32 +79,30 @@ MODULE_OBJS := \ vkeybd/virtual-keyboard-gui.o \ vkeybd/virtual-keyboard-parser.o -ifeq ($(BACKEND),dc) -MODULE_OBJS += \ - plugins/dc/dc-provider.o -endif - ifeq ($(BACKEND),ds) MODULE_OBJS += \ - fs/ds/ds-fs-factory.o \ fs/ds/ds-fs.o \ + fs/ds/ds-fs-factory.o \ plugins/ds/ds-provider.o endif ifeq ($(BACKEND),n64) MODULE_OBJS += \ + fs/n64/n64-fs.o \ fs/n64/n64-fs-factory.o \ fs/n64/romfsstream.o endif ifeq ($(BACKEND),ps2) MODULE_OBJS += \ + fs/ps2/ps2-fs.o \ fs/ps2/ps2-fs-factory.o \ plugins/ps2/ps2-provider.o endif ifeq ($(BACKEND),psp) MODULE_OBJS += \ + fs/psp/psp-fs.o \ fs/psp/psp-fs-factory.o \ fs/psp/psp-stream.o \ plugins/psp/psp-provider.o \ @@ -102,6 +112,7 @@ endif ifeq ($(BACKEND),wii) MODULE_OBJS += \ + fs/wii/wii-fs.o \ fs/wii/wii-fs-factory.o \ plugins/wii/wii-provider.o endif diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index c49745f8bd..b1d0727d1f 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -25,37 +25,43 @@ #if defined(__ANDROID__) -#include "backends/base-backend.h" -#include "base/main.h" -#include "graphics/surface.h" +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +// Disable printf override in common/forbidden.h to avoid +// clashes with log.h from the Android SDK. +// That header file uses +// __attribute__ ((format(printf, 3, 4))) +// which gets messed up by our override mechanism; this could +// be avoided by either changing the Android SDK to use the equally +// legal and valid +// __attribute__ ((format(printf, 3, 4))) +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the Android port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf -#include "backends/platform/android/android.h" -#include "backends/platform/android/video.h" - -#include <jni.h> - -#include <string.h> -#include <unistd.h> -#include <pthread.h> #include <sys/time.h> +#include <sys/resource.h> +#include <sys/system_properties.h> #include <time.h> +#include <unistd.h> -#include "common/archive.h" #include "common/util.h" +#include "common/textconsole.h" #include "common/rect.h" #include "common/queue.h" #include "common/mutex.h" #include "common/events.h" #include "common/config-manager.h" -#include "backends/fs/posix/posix-fs-factory.h" #include "backends/keymapper/keymapper.h" #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" -#include "backends/plugins/posix/posix-provider.h" -#include "audio/mixer_intern.h" -#include "backends/platform/android/asset-archive.h" +#include "backends/platform/android/jni.h" +#include "backends/platform/android/android.h" const char *android_log_tag = "ScummVM"; @@ -68,7 +74,8 @@ extern "C" { expr, file, line); } - void __assert2(const char *file, int line, const char *func, const char *expr) { + void __assert2(const char *file, int line, const char *func, + const char *expr) { __android_log_assert(expr, android_log_tag, "Assertion failure: '%s' in %s:%d (%s)", expr, file, line, func); @@ -106,235 +113,25 @@ void checkGlError(const char *expr, const char *file, int line) { } #endif -static JavaVM *cached_jvm; -static jfieldID FID_Event_type; -static jfieldID FID_Event_synthetic; -static jfieldID FID_Event_kbd_keycode; -static jfieldID FID_Event_kbd_ascii; -static jfieldID FID_Event_kbd_flags; -static jfieldID FID_Event_mouse_x; -static jfieldID FID_Event_mouse_y; -static jfieldID FID_Event_mouse_relative; -static jfieldID FID_ScummVM_nativeScummVM; -static jmethodID MID_Object_wait; - -JNIEnv *JNU_GetEnv() { - JNIEnv *env = 0; - - jint res = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2); - - if (res != JNI_OK) { - LOGE("GetEnv() failed: %d", res); - abort(); - } - - return env; -} - -static void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) { - jclass cls = env->FindClass(name); - - // if cls is 0, an exception has already been thrown - if (cls != 0) - env->ThrowNew(cls, msg); - - env->DeleteLocalRef(cls); -} - -// floating point. use sparingly -template <class T> -static inline T scalef(T in, float numerator, float denominator) { - return static_cast<float>(in) * numerator / denominator; -} - -static inline GLfixed xdiv(int numerator, int denominator) { - assert(numerator < (1 << 16)); - return (numerator << 16) / denominator; -} - -#ifdef DYNAMIC_MODULES -class AndroidPluginProvider : public POSIXPluginProvider { -protected: - virtual void addCustomDirectories(Common::FSList &dirs) const; -}; -#endif - -class OSystem_Android : public BaseBackend, public PaletteManager { -private: - // back pointer to (java) peer instance - jobject _back_ptr; - - jmethodID MID_displayMessageOnOSD; - jmethodID MID_setWindowCaption; - jmethodID MID_initBackend; - jmethodID MID_audioSampleRate; - jmethodID MID_showVirtualKeyboard; - jmethodID MID_getSysArchives; - jmethodID MID_getPluginDirectories; - jmethodID MID_setupScummVMSurface; - jmethodID MID_destroyScummVMSurface; - jmethodID MID_swapBuffers; - - int _screen_changeid; - int _egl_surface_width; - int _egl_surface_height; - - bool _force_redraw; - - // Game layer - GLESPaletteTexture *_game_texture; - int _shake_offset; - Common::Rect _focus_rect; - - // Overlay layer - GLES4444Texture *_overlay_texture; - bool _show_overlay; - - // Mouse layer - GLESPaletteATexture *_mouse_texture; - Common::Point _mouse_hotspot; - int _mouse_targetscale; - bool _show_mouse; - bool _use_mouse_palette; - - Common::Queue<Common::Event> _event_queue; - MutexRef _event_queue_lock; - - bool _timer_thread_exit; - pthread_t _timer_thread; - static void *timerThreadFunc(void *arg); - - bool _enable_zoning; - bool _virtkeybd_on; - - Common::SaveFileManager *_savefile; - Audio::MixerImpl *_mixer; - Common::TimerManager *_timer; - FilesystemFactory *_fsFactory; - Common::Archive *_asset_archive; - timeval _startTime; - - void setupScummVMSurface(); - void destroyScummVMSurface(); - void setupKeymapper(); - void _setCursorPalette(const byte *colors, uint start, uint num); - -public: - OSystem_Android(jobject am); - virtual ~OSystem_Android(); - bool initJavaHooks(JNIEnv *env, jobject self); - - static OSystem_Android *fromJavaObject(JNIEnv *env, jobject obj); - virtual void initBackend(); - void addPluginDirectories(Common::FSList &dirs) const; - void enableZoning(bool enable) { _enable_zoning = enable; } - void setSurfaceSize(int width, int height) { - _egl_surface_width = width; - _egl_surface_height = height; - } - - virtual bool hasFeature(Feature f); - virtual void setFeatureState(Feature f, bool enable); - virtual bool getFeatureState(Feature f); - virtual const GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - bool setGraphicsMode(const char *name); - virtual bool setGraphicsMode(int mode); - virtual int getGraphicsMode() const; - virtual void initSize(uint width, uint height, - const Graphics::PixelFormat *format); - - virtual int getScreenChangeID() const { - return _screen_changeid; - } - - virtual int16 getHeight(); - virtual int16 getWidth(); - - virtual PaletteManager *getPaletteManager() { - return this; - } - -protected: - // PaletteManager API - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); - -public: - virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h); - virtual void updateScreen(); - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - virtual void setShakePos(int shakeOffset); - virtual void fillScreen(uint32 col); - virtual void setFocusRectangle(const Common::Rect& rect); - virtual void clearFocusRectangle(); - - virtual void showOverlay(); - virtual void hideOverlay(); - virtual void clearOverlay(); - virtual void grabOverlay(OverlayColor *buf, int pitch); - virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); - virtual int16 getOverlayHeight(); - virtual int16 getOverlayWidth(); - - // RGBA 4444 - virtual Graphics::PixelFormat getOverlayFormat() const { - Graphics::PixelFormat format; - - format.bytesPerPixel = 2; - format.rLoss = 8 - 4; - format.gLoss = 8 - 4; - format.bLoss = 8 - 4; - format.aLoss = 8 - 4; - format.rShift = 3 * 4; - format.gShift = 2 * 4; - format.bShift = 1 * 4; - format.aShift = 0 * 4; - - return format; - } - - virtual bool showMouse(bool visible); - - virtual void warpMouse(int x, int y); - virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); - virtual void setCursorPalette(const byte *colors, uint start, uint num); - virtual void disableCursorPalette(bool disable); - - virtual bool pollEvent(Common::Event &event); - void pushEvent(const Common::Event& event); - virtual uint32 getMillis(); - virtual void delayMillis(uint msecs); - - virtual MutexRef createMutex(void); - virtual void lockMutex(MutexRef mutex); - virtual void unlockMutex(MutexRef mutex); - virtual void deleteMutex(MutexRef mutex); - - virtual void quit(); - - virtual void setWindowCaption(const char *caption); - virtual void displayMessageOnOSD(const char *msg); - virtual void showVirtualKeyboard(bool enable); - - virtual Common::SaveFileManager *getSavefileManager(); - virtual Audio::Mixer *getMixer(); - virtual void getTimeAndDate(TimeDate &t) const; - virtual Common::TimerManager *getTimerManager(); - virtual FilesystemFactory *getFilesystemFactory(); - virtual void logMessage(LogMessageType::Type type, const char *message); - virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); -}; - -OSystem_Android::OSystem_Android(jobject am) : - _back_ptr(0), +OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : + _audio_sample_rate(audio_sample_rate), + _audio_buffer_size(audio_buffer_size), _screen_changeid(0), + _egl_surface_width(0), + _egl_surface_height(0), + _htc_fail(false), _force_redraw(false), _game_texture(0), _overlay_texture(0), _mouse_texture(0), + _mouse_texture_palette(0), + _mouse_texture_rgb(0), + _mouse_hotspot(), + _mouse_keycolor(0), _use_mouse_palette(false), + _graphicsMode(0), + _fullscreen(true), + _ar_correction(true), _show_mouse(false), _show_overlay(false), _enable_zoning(false), @@ -342,876 +139,306 @@ OSystem_Android::OSystem_Android(jobject am) : _mixer(0), _timer(0), _fsFactory(new POSIXFilesystemFactory()), - _asset_archive(new AndroidAssetArchive(am)), _shake_offset(0), - _event_queue_lock(createMutex()) { + _event_queue_lock(createMutex()), + _touch_pt_down(), + _touch_pt_scroll(), + _touch_pt_dt(), + _eventScaleX(100), + _eventScaleY(100), + // TODO put these values in some option dlg? + _touchpad_mode(true), + _touchpad_scale(66), + _dpad_scale(4), + _fingersDown(0), + _trackball_scale(2) { + Common::String mf = getSystemProperty("ro.product.manufacturer"); + + LOGI("Running on: [%s] [%s] [%s] [%s] [%s] SDK:%s ABI:%s", + mf.c_str(), + getSystemProperty("ro.product.model").c_str(), + getSystemProperty("ro.product.brand").c_str(), + getSystemProperty("ro.build.fingerprint").c_str(), + getSystemProperty("ro.build.display.id").c_str(), + getSystemProperty("ro.build.version.sdk").c_str(), + getSystemProperty("ro.product.cpu.abi").c_str()); + + mf.toLowercase(); + _htc_fail = mf.contains("htc"); + + if (_htc_fail) + LOGI("Enabling HTC workaround"); } OSystem_Android::~OSystem_Android() { ENTER(); - delete _game_texture; - delete _overlay_texture; - delete _mouse_texture; - - destroyScummVMSurface(); - - JNIEnv *env = JNU_GetEnv(); - //env->DeleteWeakGlobalRef(_back_ptr); - env->DeleteGlobalRef(_back_ptr); - delete _savefile; - delete _mixer; delete _timer; + delete _mixer; delete _fsFactory; - delete _asset_archive; deleteMutex(_event_queue_lock); } -OSystem_Android *OSystem_Android::fromJavaObject(JNIEnv *env, jobject obj) { - jlong peer = env->GetLongField(obj, FID_ScummVM_nativeScummVM); - return (OSystem_Android *)peer; -} - -bool OSystem_Android::initJavaHooks(JNIEnv *env, jobject self) { - // weak global ref to allow class to be unloaded - // ... except dalvik doesn't implement NewWeakGlobalRef (yet) - //_back_ptr = env->NewWeakGlobalRef(self); - _back_ptr = env->NewGlobalRef(self); - - jclass cls = env->GetObjectClass(_back_ptr); - -#define FIND_METHOD(name, signature) do { \ - MID_ ## name = env->GetMethodID(cls, #name, signature); \ - if (MID_ ## name == 0) \ - return false; \ - } while (0) - - FIND_METHOD(setWindowCaption, "(Ljava/lang/String;)V"); - FIND_METHOD(displayMessageOnOSD, "(Ljava/lang/String;)V"); - FIND_METHOD(initBackend, "()V"); - FIND_METHOD(audioSampleRate, "()I"); - FIND_METHOD(showVirtualKeyboard, "(Z)V"); - FIND_METHOD(getSysArchives, "()[Ljava/lang/String;"); - FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;"); - FIND_METHOD(setupScummVMSurface, "()V"); - FIND_METHOD(destroyScummVMSurface, "()V"); - FIND_METHOD(swapBuffers, "()Z"); - -#undef FIND_METHOD - - return true; -} - -static void ScummVM_create(JNIEnv *env, jobject self, jobject am) { - OSystem_Android *cpp_obj = new OSystem_Android(am); - - // Exception already thrown by initJavaHooks? - if (!cpp_obj->initJavaHooks(env, self)) - return; - - env->SetLongField(self, FID_ScummVM_nativeScummVM, (jlong)cpp_obj); - -#ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new AndroidPluginProvider()); -#endif -} - -static void ScummVM_nativeDestroy(JNIEnv *env, jobject self) { - OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self); - delete cpp_obj; -} - -static void ScummVM_audioMixCallback(JNIEnv *env, jobject self, - jbyteArray jbuf) { - OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self); - jsize len = env->GetArrayLength(jbuf); - jbyte *buf = env->GetByteArrayElements(jbuf, 0); - - if (buf == 0) { - warning("Unable to get Java audio byte array. Skipping"); - return; - } - - Audio::MixerImpl *mixer = - static_cast<Audio::MixerImpl *>(cpp_obj->getMixer()); - assert(mixer); - mixer->mixCallback(reinterpret_cast<byte *>(buf), len); - - env->ReleaseByteArrayElements(jbuf, buf, 0); -} - -static void ScummVM_setConfManInt(JNIEnv *env, jclass cls, - jstring key_obj, jint value) { - ENTER("%p, %d", key_obj, (int)value); - - const char *key = env->GetStringUTFChars(key_obj, 0); - - if (key == 0) - return; - - ConfMan.setInt(key, value); - - env->ReleaseStringUTFChars(key_obj, key); -} - -static void ScummVM_setConfManString(JNIEnv *env, jclass cls, jstring key_obj, - jstring value_obj) { - ENTER("%p, %p", key_obj, value_obj); - - const char *key = env->GetStringUTFChars(key_obj, 0); - - if (key == 0) - return; - - const char *value = env->GetStringUTFChars(value_obj, 0); - - if (value == 0) { - env->ReleaseStringUTFChars(key_obj, key); - return; - } - - ConfMan.set(key, value); - - env->ReleaseStringUTFChars(value_obj, value); - env->ReleaseStringUTFChars(key_obj, key); -} - void *OSystem_Android::timerThreadFunc(void *arg) { OSystem_Android *system = (OSystem_Android *)arg; DefaultTimerManager *timer = (DefaultTimerManager *)(system->_timer); - JNIEnv *env = 0; - jint res = cached_jvm->AttachCurrentThread(&env, 0); + // renice this thread to boost the audio thread + if (setpriority(PRIO_PROCESS, 0, 19) < 0) + LOGW("couldn't renice the timer thread"); - if (res != JNI_OK) { - LOGE("AttachCurrentThread() failed: %d", res); - abort(); - } + JNI::attachThread(); struct timespec tv; tv.tv_sec = 0; - tv.tv_nsec = 100 * 1000 * 1000; // 100ms + tv.tv_nsec = 10 * 1000 * 1000; // 10ms while (!system->_timer_thread_exit) { + if (JNI::pause) { + LOGD("timer thread going to sleep"); + sem_wait(&JNI::pause_sem); + LOGD("timer thread woke up"); + } + timer->handler(); nanosleep(&tv, 0); } - res = cached_jvm->DetachCurrentThread(); - - if (res != JNI_OK) { - LOGE("DetachCurrentThread() failed: %d", res); - abort(); - } + JNI::detachThread(); return 0; } -void OSystem_Android::initBackend() { - ENTER(); - - JNIEnv *env = JNU_GetEnv(); - - ConfMan.setInt("autosave_period", 0); - ConfMan.setInt("FM_medium_quality", true); - - // must happen before creating TimerManager to avoid race in - // creating EventManager - setupKeymapper(); - - // BUG: "transient" ConfMan settings get nuked by the options - // screen. Passing the savepath in this way makes it stick - // (via ConfMan.registerDefault) - _savefile = new DefaultSaveFileManager(ConfMan.get("savepath")); - _timer = new DefaultTimerManager(); - - gettimeofday(&_startTime, 0); - - jint sample_rate = env->CallIntMethod(_back_ptr, MID_audioSampleRate); - if (env->ExceptionCheck()) { - warning("Error finding audio sample rate - assuming 11025HZ"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - - sample_rate = 11025; - } - - _mixer = new Audio::MixerImpl(this, sample_rate); - _mixer->setReady(true); - - env->CallVoidMethod(_back_ptr, MID_initBackend); +void *OSystem_Android::audioThreadFunc(void *arg) { + JNI::attachThread(); - if (env->ExceptionCheck()) { - error("Error in Java initBackend"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } - - _timer_thread_exit = false; - pthread_create(&_timer_thread, 0, timerThreadFunc, this); + OSystem_Android *system = (OSystem_Android *)arg; + Audio::MixerImpl *mixer = system->_mixer; - OSystem::initBackend(); + uint buf_size = system->_audio_buffer_size; - setupScummVMSurface(); -} + JNIEnv *env = JNI::getEnv(); -void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const { - ENTER(); + jbyteArray bufa = env->NewByteArray(buf_size); - JNIEnv *env = JNU_GetEnv(); + bool paused = true; - jobjectArray array = - (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getPluginDirectories); - if (env->ExceptionCheck()) { - warning("Error finding plugin directories"); + byte *buf; + int offset, left, written; + int samples, i; - env->ExceptionDescribe(); - env->ExceptionClear(); + struct timespec tv_delay; + tv_delay.tv_sec = 0; + tv_delay.tv_nsec = 20 * 1000 * 1000; - return; - } + uint msecs_full = buf_size * 1000 / (mixer->getOutputRate() * 2 * 2); - jsize size = env->GetArrayLength(array); - for (jsize i = 0; i < size; ++i) { - jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); + struct timespec tv_full; + tv_full.tv_sec = 0; + tv_full.tv_nsec = msecs_full * 1000 * 1000; - if (path_obj == 0) - continue; + bool silence; + uint silence_count = 33; - const char *path = env->GetStringUTFChars(path_obj, 0); - if (path == 0) { - warning("Error getting string characters from plugin directory"); + while (!system->_audio_thread_exit) { + if (JNI::pause) { + JNI::setAudioStop(); - env->ExceptionClear(); - env->DeleteLocalRef(path_obj); + paused = true; + silence_count = 33; - continue; + LOGD("audio thread going to sleep"); + sem_wait(&JNI::pause_sem); + LOGD("audio thread woke up"); } - dirs.push_back(Common::FSNode(path)); - - env->ReleaseStringUTFChars(path_obj, path); - env->DeleteLocalRef(path_obj); - } -} + buf = (byte *)env->GetPrimitiveArrayCritical(bufa, 0); + assert(buf); -bool OSystem_Android::hasFeature(Feature f) { - return (f == kFeatureCursorHasPalette || - f == kFeatureVirtualKeyboard || - f == kFeatureOverlaySupportsAlpha); -} + samples = mixer->mixCallback(buf, buf_size); -void OSystem_Android::setFeatureState(Feature f, bool enable) { - ENTER("%d, %d", f, enable); + silence = samples < 1; - switch (f) { - case kFeatureVirtualKeyboard: - _virtkeybd_on = enable; - showVirtualKeyboard(enable); - break; - default: - break; - } -} + // looks stupid, and it is, but currently there's no way to detect + // silence-only buffers from the mixer + if (!silence) { + silence = true; -bool OSystem_Android::getFeatureState(Feature f) { - switch (f) { - case kFeatureVirtualKeyboard: - return _virtkeybd_on; - default: - return false; - } -} - -const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const { - static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - { "default", "Default", 1 }, - { 0, 0, 0 }, - }; - - return s_supportedGraphicsModes; -} - - -int OSystem_Android::getDefaultGraphicsMode() const { - return 1; -} - -bool OSystem_Android::setGraphicsMode(const char *mode) { - ENTER("%s", mode); - return true; -} - -bool OSystem_Android::setGraphicsMode(int mode) { - ENTER("%d", mode); - return true; -} - -int OSystem_Android::getGraphicsMode() const { - return 1; -} - -void OSystem_Android::setupScummVMSurface() { - ENTER(); - - JNIEnv *env = JNU_GetEnv(); - env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface); - - if (env->ExceptionCheck()) - return; - - // EGL set up with a new surface. Initialise OpenGLES context. - GLESTexture::initGLExtensions(); - - // Turn off anything that looks like 3D ;) - GLCALL(glDisable(GL_CULL_FACE)); - GLCALL(glDisable(GL_DEPTH_TEST)); - GLCALL(glDisable(GL_LIGHTING)); - GLCALL(glDisable(GL_FOG)); - GLCALL(glDisable(GL_DITHER)); - - GLCALL(glShadeModel(GL_FLAT)); - GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); - - GLCALL(glEnable(GL_BLEND)); - GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - - GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); - GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - - GLCALL(glEnable(GL_TEXTURE_2D)); - - if (!_game_texture) - _game_texture = new GLESPaletteTexture(); - else - _game_texture->reinitGL(); - - if (!_overlay_texture) - _overlay_texture = new GLES4444Texture(); - else - _overlay_texture->reinitGL(); - - if (!_mouse_texture) - _mouse_texture = new GLESPaletteATexture(); - else - _mouse_texture->reinitGL(); - - GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height)); - - GLCALL(glMatrixMode(GL_PROJECTION)); - GLCALL(glLoadIdentity()); - GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1)); - GLCALL(glMatrixMode(GL_MODELVIEW)); - GLCALL(glLoadIdentity()); - - clearFocusRectangle(); -} - -void OSystem_Android::destroyScummVMSurface() { - JNIEnv *env = JNU_GetEnv(); - env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface); - // Can't use OpenGLES functions after this -} - -void OSystem_Android::initSize(uint width, uint height, - const Graphics::PixelFormat *format) { - ENTER("%d, %d, %p", width, height, format); - - _game_texture->allocBuffer(width, height); - - // Cap at 320x200 or the ScummVM themes abort :/ - GLuint overlay_width = MIN(_egl_surface_width, 320); - GLuint overlay_height = MIN(_egl_surface_height, 200); - _overlay_texture->allocBuffer(overlay_width, overlay_height); - - // Don't know mouse size yet - it gets reallocated in - // setMouseCursor. We need the palette allocated before - // setMouseCursor however, so just take a guess at the desired - // size (it's small). - _mouse_texture->allocBuffer(20, 20); -} - -int16 OSystem_Android::getHeight() { - return _game_texture->height(); -} - -int16 OSystem_Android::getWidth() { - return _game_texture->width(); -} - -void OSystem_Android::setPalette(const byte *colors, uint start, uint num) { - ENTER("%p, %u, %u", colors, start, num); - - if (!_use_mouse_palette) - _setCursorPalette(colors, start, num); - - memcpy(_game_texture->palette() + start * 3, colors, num * 3); -} - -void OSystem_Android::grabPalette(byte *colors, uint start, uint num) { - ENTER("%p, %u, %u", colors, start, num); - memcpy(colors, _game_texture->palette_const() + start * 3, num * 3); -} - -void OSystem_Android::copyRectToScreen(const byte *buf, int pitch, - int x, int y, int w, int h) { - ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h); - - _game_texture->updateBuffer(x, y, w, h, buf, pitch); -} - -void OSystem_Android::updateScreen() { - //ENTER(); - - if (!_force_redraw && - !_game_texture->dirty() && - !_overlay_texture->dirty() && - !_mouse_texture->dirty()) - return; - - _force_redraw = false; - - GLCALL(glPushMatrix()); - - if (_shake_offset != 0 || - (!_focus_rect.isEmpty() && - !Common::Rect(_game_texture->width(), - _game_texture->height()).contains(_focus_rect))) { - // These are the only cases where _game_texture doesn't - // cover the entire screen. - GLCALL(glClearColorx(0, 0, 0, 1 << 16)); - GLCALL(glClear(GL_COLOR_BUFFER_BIT)); - - // Move everything up by _shake_offset (game) pixels - GLCALL(glTranslatex(0, -_shake_offset << 16, 0)); - } - - if (_focus_rect.isEmpty()) { - _game_texture->drawTexture(0, 0, - _egl_surface_width, _egl_surface_height); - } else { - GLCALL(glPushMatrix()); - GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()), - xdiv(_egl_surface_height, _focus_rect.height()), - 1 << 16)); - GLCALL(glTranslatex(-_focus_rect.left << 16, - -_focus_rect.top << 16, 0)); - GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width), - xdiv(_game_texture->height(), _egl_surface_height), - 1 << 16)); - - _game_texture->drawTexture(0, 0, - _egl_surface_width, _egl_surface_height); - GLCALL(glPopMatrix()); - } - - int cs = _mouse_targetscale; - - if (_show_overlay) { - // ugly, but the modern theme sets a wacko factor, only god knows why - cs = 1; - - GLCALL(_overlay_texture->drawTexture(0, 0, - _egl_surface_width, - _egl_surface_height)); - } - - if (_show_mouse) { - GLCALL(glPushMatrix()); - - // Scale up ScummVM -> OpenGL (pixel) coordinates - int texwidth, texheight; - - if (_show_overlay) { - texwidth = getOverlayWidth(); - texheight = getOverlayHeight(); - } else { - texwidth = getWidth(); - texheight = getHeight(); + for (i = 0; i < samples; i += 2) + // SID streams constant crap + if (READ_UINT16(buf + i) > 32) { + silence = false; + break; + } } - GLCALL(glScalex(xdiv(_egl_surface_width, texwidth), - xdiv(_egl_surface_height, texheight), - 1 << 16)); - - GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16, - (-_mouse_hotspot.y * cs) << 16, - 0)); - - // Note the extra half texel to position the mouse in - // the middle of the x,y square: - const Common::Point& mouse = getEventManager()->getMousePos(); - GLCALL(glTranslatex((mouse.x << 16) | 1 << 15, - (mouse.y << 16) | 1 << 15, 0)); - - GLCALL(glScalex(cs << 16, cs << 16, 1 << 16)); + env->ReleasePrimitiveArrayCritical(bufa, buf, 0); - _mouse_texture->drawTexture(); + if (silence) { + if (!paused) + silence_count++; - GLCALL(glPopMatrix()); - } + // only pause after a while to prevent toggle mania + if (silence_count > 32) { + if (!paused) { + LOGD("AudioTrack pause"); - GLCALL(glPopMatrix()); + JNI::setAudioPause(); + paused = true; + } - JNIEnv *env = JNU_GetEnv(); - if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) { - // Context lost -> need to reinit GL - destroyScummVMSurface(); - setupScummVMSurface(); - } -} + nanosleep(&tv_full, 0); -Graphics::Surface *OSystem_Android::lockScreen() { - ENTER(); + continue; + } + } - Graphics::Surface *surface = _game_texture->surface(); - assert(surface->pixels); + if (paused) { + LOGD("AudioTrack play"); - return surface; -} + JNI::setAudioPlay(); + paused = false; -void OSystem_Android::unlockScreen() { - ENTER(); + silence_count = 0; + } - assert(_game_texture->dirty()); -} + offset = 0; + left = buf_size; + written = 0; -void OSystem_Android::setShakePos(int shake_offset) { - ENTER("%d", shake_offset); + while (left > 0) { + written = JNI::writeAudio(env, bufa, offset, left); - if (_shake_offset != shake_offset) { - _shake_offset = shake_offset; - _force_redraw = true; - } -} + if (written < 0) { + LOGE("AudioTrack error: %d", written); + break; + } -void OSystem_Android::fillScreen(uint32 col) { - ENTER("%u", col); + // buffer full + if (written < left) + nanosleep(&tv_delay, 0); - assert(col < 256); - _game_texture->fillBuffer(col); -} + offset += written; + left -= written; + } -void OSystem_Android::setFocusRectangle(const Common::Rect& rect) { - ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom); + if (written < 0) + break; - if (_enable_zoning) { - _focus_rect = rect; - _force_redraw = true; + // prepare the next buffer, and run into the blocking AudioTrack.write } -} -void OSystem_Android::clearFocusRectangle() { - ENTER(); + JNI::setAudioStop(); - if (_enable_zoning) { - _focus_rect = Common::Rect(); - _force_redraw = true; - } -} + env->DeleteLocalRef(bufa); -void OSystem_Android::showOverlay() { - ENTER(); + JNI::detachThread(); - _show_overlay = true; - _force_redraw = true; + return 0; } -void OSystem_Android::hideOverlay() { +void OSystem_Android::initBackend() { ENTER(); - _show_overlay = false; - _force_redraw = true; -} - -void OSystem_Android::clearOverlay() { - ENTER(); + _main_thread = pthread_self(); - _overlay_texture->fillBuffer(0); + ConfMan.registerDefault("fullscreen", true); + ConfMan.registerDefault("aspect_ratio", true); - // Shouldn't need this, but works around a 'blank screen' bug on Nexus1 - updateScreen(); -} - -void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) { - ENTER("%p, %d", buf, pitch); - - // We support overlay alpha blending, so the pixel data here - // shouldn't actually be used. Let's fill it with zeros, I'm sure - // it will be fine... - const Graphics::Surface *surface = _overlay_texture->surface_const(); - assert(surface->bytesPerPixel == sizeof(buf[0])); - - int h = surface->h; - - do { - memset(buf, 0, surface->w * sizeof(buf[0])); - - // This 'pitch' is pixels not bytes - buf += pitch; - } while (--h); -} - -void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch, - int x, int y, int w, int h) { - ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h); - - const Graphics::Surface *surface = _overlay_texture->surface_const(); - assert(surface->bytesPerPixel == sizeof(buf[0])); - - // This 'pitch' is pixels not bytes - _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0])); - - // Shouldn't need this, but works around a 'blank screen' bug on Nexus1? - updateScreen(); -} - -int16 OSystem_Android::getOverlayHeight() { - return _overlay_texture->height(); -} - -int16 OSystem_Android::getOverlayWidth() { - return _overlay_texture->width(); -} - -bool OSystem_Android::showMouse(bool visible) { - ENTER("%d", visible); - - _show_mouse = visible; - - return true; -} - -void OSystem_Android::warpMouse(int x, int y) { - ENTER("%d, %d", x, y); - - // We use only the eventmanager's idea of the current mouse - // position, so there is nothing extra to do here. -} - -void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h, - int hotspotX, int hotspotY, - uint32 keycolor, int cursorTargetScale, - const Graphics::PixelFormat *format) { - ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY, - keycolor, cursorTargetScale, format); - - assert(keycolor < 256); + ConfMan.setInt("autosave_period", 0); + ConfMan.setBool("FM_high_quality", false); + ConfMan.setBool("FM_medium_quality", true); - _mouse_texture->allocBuffer(w, h); + // TODO hackity hack + if (ConfMan.hasKey("multi_midi")) + _touchpad_mode = !ConfMan.getBool("multi_midi"); - // Update palette alpha based on keycolor - byte *palette = _mouse_texture->palette(); - int i = 256; + // must happen before creating TimerManager to avoid race in + // creating EventManager + setupKeymapper(); - do { - palette[3] = 0xff; - palette += 4; - } while (--i); + // BUG: "transient" ConfMan settings get nuked by the options + // screen. Passing the savepath in this way makes it stick + // (via ConfMan.registerDefault) + _savefile = new DefaultSaveFileManager(ConfMan.get("savepath")); + _timer = new DefaultTimerManager(); - palette = _mouse_texture->palette(); - palette[keycolor * 4 + 3] = 0x00; + gettimeofday(&_startTime, 0); - _mouse_texture->updateBuffer(0, 0, w, h, buf, w); + _mixer = new Audio::MixerImpl(this, _audio_sample_rate); + _mixer->setReady(true); - _mouse_hotspot = Common::Point(hotspotX, hotspotY); - _mouse_targetscale = cursorTargetScale; -} + _timer_thread_exit = false; + pthread_create(&_timer_thread, 0, timerThreadFunc, this); -void OSystem_Android::_setCursorPalette(const byte *colors, - uint start, uint num) { - byte *palette = _mouse_texture->palette() + start * 4; + _audio_thread_exit = false; + pthread_create(&_audio_thread, 0, audioThreadFunc, this); - do { - for (int i = 0; i < 3; ++i) - palette[i] = colors[i]; + initSurface(); + initViewport(); - // Leave alpha untouched to preserve keycolor + _game_texture = new GLESFakePalette565Texture(); + _overlay_texture = new GLES4444Texture(); + _mouse_texture_palette = new GLESFakePalette5551Texture(); + _mouse_texture = _mouse_texture_palette; - palette += 4; - colors += 3; - } while (--num); -} + initOverlay(); -void OSystem_Android::setCursorPalette(const byte *colors, - uint start, uint num) { - ENTER("%p, %u, %u", colors, start, num); + // renice this thread to boost the audio thread + if (setpriority(PRIO_PROCESS, 0, 19) < 0) + warning("couldn't renice the main thread"); - _setCursorPalette(colors, start, num); - _use_mouse_palette = true; + JNI::setReadyForEvents(true); } -void OSystem_Android::disableCursorPalette(bool disable) { - ENTER("%d", disable); +void OSystem_Android::addPluginDirectories(Common::FSList &dirs) const { + ENTER(); - _use_mouse_palette = !disable; + JNI::getPluginDirectories(dirs); } -void OSystem_Android::setupKeymapper() { -#ifdef ENABLE_KEYMAPPER - using namespace Common; - - Keymapper *mapper = getEventManager()->getKeymapper(); - - HardwareKeySet *keySet = new HardwareKeySet(); - - keySet->addHardwareKey( - new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)", - kTriggerLeftKeyType, - kVirtualKeyboardActionType)); - - mapper->registerHardwareKeySet(keySet); - - Keymap *globalMap = new Keymap("global"); - Action *act; - - act = new Action(globalMap, "VIRT", "Display keyboard", - kVirtualKeyboardActionType); - act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - - mapper->addGlobalKeymap(globalMap); - - mapper->pushKeymap("global"); -#endif +bool OSystem_Android::hasFeature(Feature f) { + return (f == kFeatureFullscreenMode || + f == kFeatureAspectRatioCorrection || + f == kFeatureCursorHasPalette || + f == kFeatureVirtualKeyboard || + f == kFeatureOverlaySupportsAlpha); } -bool OSystem_Android::pollEvent(Common::Event &event) { - //ENTER(); - - lockMutex(_event_queue_lock); - - if (_event_queue.empty()) { - unlockMutex(_event_queue_lock); - return false; - } +void OSystem_Android::setFeatureState(Feature f, bool enable) { + ENTER("%d, %d", f, enable); - event = _event_queue.pop(); - unlockMutex(_event_queue_lock); - - switch (event.type) { - case Common::EVENT_MOUSEMOVE: - // TODO: only dirty/redraw move bounds - _force_redraw = true; - // fallthrough - case Common::EVENT_LBUTTONDOWN: - case Common::EVENT_LBUTTONUP: - case Common::EVENT_RBUTTONDOWN: - case Common::EVENT_RBUTTONUP: - case Common::EVENT_WHEELUP: - case Common::EVENT_WHEELDOWN: - case Common::EVENT_MBUTTONDOWN: - case Common::EVENT_MBUTTONUP: { - // relative mouse hack - if (event.kbd.flags == 1) { - // Relative (trackball) mouse hack. - const Common::Point& mouse_pos = - getEventManager()->getMousePos(); - event.mouse.x += mouse_pos.x; - event.mouse.y += mouse_pos.y; - event.mouse.x = CLIP(event.mouse.x, (int16)0, _show_overlay ? - getOverlayWidth() : getWidth()); - event.mouse.y = CLIP(event.mouse.y, (int16)0, _show_overlay ? - getOverlayHeight() : getHeight()); - } else { - // Touchscreen events need to be converted - // from device to game coords first. - const GLESTexture *tex = _show_overlay - ? static_cast<GLESTexture *>(_overlay_texture) - : static_cast<GLESTexture *>(_game_texture); - event.mouse.x = scalef(event.mouse.x, tex->width(), - _egl_surface_width); - event.mouse.y = scalef(event.mouse.y, tex->height(), - _egl_surface_height); - event.mouse.x -= _shake_offset; - } + switch (f) { + case kFeatureFullscreenMode: + _fullscreen = enable; + updateScreenRect(); break; - } - case Common::EVENT_SCREEN_CHANGED: - debug("EVENT_SCREEN_CHANGED"); - _screen_changeid++; - destroyScummVMSurface(); - setupScummVMSurface(); + case kFeatureAspectRatioCorrection: + _ar_correction = enable; + updateScreenRect(); + break; + case kFeatureVirtualKeyboard: + _virtkeybd_on = enable; + showVirtualKeyboard(enable); break; default: break; } - - return true; } -void OSystem_Android::pushEvent(const Common::Event& event) { - lockMutex(_event_queue_lock); - - // Try to combine multiple queued mouse move events - if (event.type == Common::EVENT_MOUSEMOVE && - !_event_queue.empty() && - _event_queue.back().type == Common::EVENT_MOUSEMOVE) { - Common::Event tail = _event_queue.back(); - if (event.kbd.flags) { - // relative movement hack - tail.mouse.x += event.mouse.x; - tail.mouse.y += event.mouse.y; - } else { - // absolute position, clear relative flag - tail.kbd.flags = 0; - tail.mouse.x = event.mouse.x; - tail.mouse.y = event.mouse.y; - } - } else { - _event_queue.push(event); - } - - unlockMutex(_event_queue_lock); -} - -static void ScummVM_pushEvent(JNIEnv *env, jobject self, jobject java_event) { - OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self); - - Common::Event event; - event.type = (Common::EventType)env->GetIntField(java_event, - FID_Event_type); - - event.synthetic = - env->GetBooleanField(java_event, FID_Event_synthetic); - - switch (event.type) { - case Common::EVENT_KEYDOWN: - case Common::EVENT_KEYUP: - event.kbd.keycode = (Common::KeyCode)env->GetIntField( - java_event, FID_Event_kbd_keycode); - event.kbd.ascii = static_cast<int>(env->GetIntField( - java_event, FID_Event_kbd_ascii)); - event.kbd.flags = static_cast<int>(env->GetIntField( - java_event, FID_Event_kbd_flags)); - break; - case Common::EVENT_MOUSEMOVE: - case Common::EVENT_LBUTTONDOWN: - case Common::EVENT_LBUTTONUP: - case Common::EVENT_RBUTTONDOWN: - case Common::EVENT_RBUTTONUP: - case Common::EVENT_WHEELUP: - case Common::EVENT_WHEELDOWN: - case Common::EVENT_MBUTTONDOWN: - case Common::EVENT_MBUTTONUP: - event.mouse.x = - env->GetIntField(java_event, FID_Event_mouse_x); - event.mouse.y = - env->GetIntField(java_event, FID_Event_mouse_y); - // This is a terrible hack. We stash "relativeness" - // in the kbd.flags field until pollEvent() can work - // it out. - event.kbd.flags = env->GetBooleanField( - java_event, FID_Event_mouse_relative) ? 1 : 0; - break; +bool OSystem_Android::getFeatureState(Feature f) { + switch (f) { + case kFeatureFullscreenMode: + return _fullscreen; + case kFeatureAspectRatioCorrection: + return _ar_correction; + case kFeatureVirtualKeyboard: + return _virtkeybd_on; default: - break; + return false; } - - cpp_obj->pushEvent(event); } uint32 OSystem_Android::getMillis() { @@ -1219,7 +446,7 @@ uint32 OSystem_Android::getMillis() { gettimeofday(&curTime, 0); - return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + \ + return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + ((curTime.tv_usec - _startTime.tv_usec) / 1000)); } @@ -1229,6 +456,7 @@ void OSystem_Android::delayMillis(uint msecs) { OSystem::MutexRef OSystem_Android::createMutex() { pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); @@ -1267,58 +495,38 @@ void OSystem_Android::deleteMutex(MutexRef mutex) { void OSystem_Android::quit() { ENTER(); + JNI::setReadyForEvents(false); + + _audio_thread_exit = true; + pthread_join(_audio_thread, 0); + _timer_thread_exit = true; pthread_join(_timer_thread, 0); + + delete _game_texture; + delete _overlay_texture; + delete _mouse_texture_palette; + delete _mouse_texture_rgb; + + deinitSurface(); } void OSystem_Android::setWindowCaption(const char *caption) { ENTER("%s", caption); - JNIEnv *env = JNU_GetEnv(); - jstring java_caption = env->NewStringUTF(caption); - env->CallVoidMethod(_back_ptr, MID_setWindowCaption, java_caption); - - if (env->ExceptionCheck()) { - warning("Failed to set window caption"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } - - env->DeleteLocalRef(java_caption); + JNI::setWindowCaption(caption); } void OSystem_Android::displayMessageOnOSD(const char *msg) { ENTER("%s", msg); - JNIEnv *env = JNU_GetEnv(); - jstring java_msg = env->NewStringUTF(msg); - - env->CallVoidMethod(_back_ptr, MID_displayMessageOnOSD, java_msg); - - if (env->ExceptionCheck()) { - warning("Failed to display OSD message"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } - - env->DeleteLocalRef(java_msg); + JNI::displayMessageOnOSD(msg); } void OSystem_Android::showVirtualKeyboard(bool enable) { ENTER("%d", enable); - JNIEnv *env = JNU_GetEnv(); - - env->CallVoidMethod(_back_ptr, MID_showVirtualKeyboard, enable); - - if (env->ExceptionCheck()) { - error("Error trying to show virtual keyboard"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - } + JNI::showVirtualKeyboard(enable); } Common::SaveFileManager *OSystem_Android::getSavefileManager() { @@ -1355,37 +563,13 @@ FilesystemFactory *OSystem_Android::getFilesystemFactory() { void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { - s.add("ASSET", _asset_archive, priority, false); - - JNIEnv *env = JNU_GetEnv(); - - jobjectArray array = - (jobjectArray)env->CallObjectMethod(_back_ptr, MID_getSysArchives); - - if (env->ExceptionCheck()) { - warning("Error finding system archive path"); - - env->ExceptionDescribe(); - env->ExceptionClear(); - - return; - } - - jsize size = env->GetArrayLength(array); - for (jsize i = 0; i < size; ++i) { - jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); - const char *path = env->GetStringUTFChars(path_obj, 0); - - if (path != 0) { - s.addDirectory(path, path, priority); - env->ReleaseStringUTFChars(path_obj, path); - } + ENTER(""); - env->DeleteLocalRef(path_obj); - } + JNI::addSysArchivesToSearchSet(s, priority); } -void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) { +void OSystem_Android::logMessage(LogMessageType::Type type, + const char *message) { switch (type) { case LogMessageType::kDebug: __android_log_write(ANDROID_LOG_DEBUG, android_log_tag, message); @@ -1401,177 +585,25 @@ void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) } } -static jint ScummVM_scummVMMain(JNIEnv *env, jobject self, jobjectArray args) { - OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self); - - const int MAX_NARGS = 32; - int res = -1; - - int argc = env->GetArrayLength(args); - if (argc > MAX_NARGS) { - JNU_ThrowByName(env, "java/lang/IllegalArgumentException", - "too many arguments"); - return 0; - } - - char *argv[MAX_NARGS]; - - // note use in cleanup loop below - int nargs; - - for (nargs = 0; nargs < argc; ++nargs) { - jstring arg = (jstring)env->GetObjectArrayElement(args, nargs); - - if (arg == 0) { - argv[nargs] = 0; - } else { - const char *cstr = env->GetStringUTFChars(arg, 0); - - argv[nargs] = const_cast<char *>(cstr); - - // exception already thrown? - if (cstr == 0) - goto cleanup; - } - - env->DeleteLocalRef(arg); - } - - g_system = cpp_obj; - assert(g_system); - - LOGI("Entering scummvm_main with %d args", argc); - - res = scummvm_main(argc, argv); - - LOGI("Exiting scummvm_main"); - - g_system->quit(); - -cleanup: - nargs--; - - for (int i = 0; i < nargs; ++i) { - if (argv[i] == 0) - continue; - - jstring arg = (jstring)env->GetObjectArrayElement(args, nargs); +Common::String OSystem_Android::getSystemLanguage() const { + return Common::String::format("%s_%s", + getSystemProperty("persist.sys.language").c_str(), + getSystemProperty("persist.sys.country").c_str()); +} - // Exception already thrown? - if (arg == 0) - return res; +Common::String OSystem_Android::getSystemProperty(const char *name) const { + char value[PROP_VALUE_MAX]; - env->ReleaseStringUTFChars(arg, argv[i]); - env->DeleteLocalRef(arg); - } + int len = __system_property_get(name, value); - return res; + return Common::String(value, len); } #ifdef DYNAMIC_MODULES void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const { - OSystem_Android *g_system_android = (OSystem_Android *)g_system; - g_system_android->addPluginDirectories(dirs); + ((OSystem_Android *)g_system)->addPluginDirectories(dirs); } #endif -static void ScummVM_enableZoning(JNIEnv *env, jobject self, jboolean enable) { - OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self); - cpp_obj->enableZoning(enable); -} - -static void ScummVM_setSurfaceSize(JNIEnv *env, jobject self, - jint width, jint height) { - OSystem_Android *cpp_obj = OSystem_Android::fromJavaObject(env, self); - cpp_obj->setSurfaceSize(width, height); -} - -const static JNINativeMethod gMethods[] = { - { "create", "(Landroid/content/res/AssetManager;)V", - (void *)ScummVM_create }, - { "nativeDestroy", "()V", - (void *)ScummVM_nativeDestroy }, - { "scummVMMain", "([Ljava/lang/String;)I", - (void *)ScummVM_scummVMMain }, - { "pushEvent", "(Lorg/inodes/gus/scummvm/Event;)V", - (void *)ScummVM_pushEvent }, - { "audioMixCallback", "([B)V", - (void *)ScummVM_audioMixCallback }, - { "setConfMan", "(Ljava/lang/String;I)V", - (void *)ScummVM_setConfManInt }, - { "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V", - (void *)ScummVM_setConfManString }, - { "enableZoning", "(Z)V", - (void *)ScummVM_enableZoning }, - { "setSurfaceSize", "(II)V", - (void *)ScummVM_setSurfaceSize }, -}; - -JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *jvm, void *reserved) { - cached_jvm = jvm; - - JNIEnv *env; - - if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2)) - return JNI_ERR; - - jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM"); - if (cls == 0) - return JNI_ERR; - - if (env->RegisterNatives(cls, gMethods, ARRAYSIZE(gMethods)) < 0) - return JNI_ERR; - - FID_ScummVM_nativeScummVM = env->GetFieldID(cls, "nativeScummVM", "J"); - if (FID_ScummVM_nativeScummVM == 0) - return JNI_ERR; - - jclass event = env->FindClass("org/inodes/gus/scummvm/Event"); - if (event == 0) - return JNI_ERR; - - FID_Event_type = env->GetFieldID(event, "type", "I"); - if (FID_Event_type == 0) - return JNI_ERR; - - FID_Event_synthetic = env->GetFieldID(event, "synthetic", "Z"); - if (FID_Event_synthetic == 0) - return JNI_ERR; - - FID_Event_kbd_keycode = env->GetFieldID(event, "kbd_keycode", "I"); - if (FID_Event_kbd_keycode == 0) - return JNI_ERR; - - FID_Event_kbd_ascii = env->GetFieldID(event, "kbd_ascii", "I"); - if (FID_Event_kbd_ascii == 0) - return JNI_ERR; - - FID_Event_kbd_flags = env->GetFieldID(event, "kbd_flags", "I"); - if (FID_Event_kbd_flags == 0) - return JNI_ERR; - - FID_Event_mouse_x = env->GetFieldID(event, "mouse_x", "I"); - if (FID_Event_mouse_x == 0) - return JNI_ERR; - - FID_Event_mouse_y = env->GetFieldID(event, "mouse_y", "I"); - if (FID_Event_mouse_y == 0) - return JNI_ERR; - - FID_Event_mouse_relative = env->GetFieldID(event, "mouse_relative", "Z"); - if (FID_Event_mouse_relative == 0) - return JNI_ERR; - - cls = env->FindClass("java/lang/Object"); - if (cls == 0) - return JNI_ERR; - - MID_Object_wait = env->GetMethodID(cls, "wait", "()V"); - if (MID_Object_wait == 0) - return JNI_ERR; - - return JNI_VERSION_1_2; -} - #endif + diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index 855fb04b5d..109d252a99 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -23,8 +23,24 @@ * */ +#ifndef _ANDROID_H_ +#define _ANDROID_H_ + #if defined(__ANDROID__) +#include "common/fs.h" +#include "common/archive.h" +#include "audio/mixer_intern.h" +#include "graphics/palette.h" +#include "graphics/surface.h" +#include "backends/base-backend.h" +#include "backends/plugins/posix/posix-provider.h" +#include "backends/fs/posix/posix-fs-factory.h" + +#include "backends/platform/android/texture.h" + +#include <pthread.h> + #include <android/log.h> #include <GLES/gl.h> @@ -33,6 +49,7 @@ // toggles start //#define ANDROID_DEBUG_ENTER //#define ANDROID_DEBUG_GL +//#define ANDROID_DEBUG_GL_CALLS // toggles end extern const char *android_log_tag; @@ -46,25 +63,246 @@ extern const char *android_log_tag; #ifdef ANDROID_DEBUG_ENTER #define ENTER(fmt, args...) LOGD("%s(" fmt ")", __FUNCTION__, ##args) #else -#define ENTER(fmt, args...) /**/ +#define ENTER(fmt, args...) do { } while (false) #endif #ifdef ANDROID_DEBUG_GL extern void checkGlError(const char *expr, const char *file, int line); +#ifdef ANDROID_DEBUG_GL_CALLS +#define GLCALLLOG(x, before) \ + do { \ + if (before) \ + LOGD("calling '%s' (%s:%d)", x, __FILE__, __LINE__); \ + else \ + LOGD("returned from '%s' (%s:%d)", x, __FILE__, __LINE__); \ + } while (false) +#else +#define GLCALLLOG(x, before) do { } while (false) +#endif + #define GLCALL(x) \ do { \ + GLCALLLOG(#x, true); \ (x); \ + GLCALLLOG(#x, false); \ checkGlError(#x, __FILE__, __LINE__); \ } while (false) +#define GLTHREADCHECK \ + do { \ + assert(pthread_self() == _main_thread); \ + } while (false) + #else #define GLCALL(x) do { (x); } while (false) +#define GLTHREADCHECK do { } while (false) +#endif + +#ifdef DYNAMIC_MODULES +class AndroidPluginProvider : public POSIXPluginProvider { +protected: + virtual void addCustomDirectories(Common::FSList &dirs) const; +}; +#endif + +class OSystem_Android : public BaseBackend, public PaletteManager { +private: + // passed from the dark side + int _audio_sample_rate; + int _audio_buffer_size; + + int _screen_changeid; + int _egl_surface_width; + int _egl_surface_height; + bool _htc_fail; + + bool _force_redraw; + + // Game layer + GLESBaseTexture *_game_texture; + int _shake_offset; + Common::Rect _focus_rect; + + // Overlay layer + GLES4444Texture *_overlay_texture; + bool _show_overlay; + + // Mouse layer + GLESBaseTexture *_mouse_texture; + GLESBaseTexture *_mouse_texture_palette; + GLES5551Texture *_mouse_texture_rgb; + Common::Point _mouse_hotspot; + uint32 _mouse_keycolor; + int _mouse_targetscale; + bool _show_mouse; + bool _use_mouse_palette; + + int _graphicsMode; + bool _fullscreen; + bool _ar_correction; + + pthread_t _main_thread; + + bool _timer_thread_exit; + pthread_t _timer_thread; + static void *timerThreadFunc(void *arg); + + bool _audio_thread_exit; + pthread_t _audio_thread; + static void *audioThreadFunc(void *arg); + + bool _enable_zoning; + bool _virtkeybd_on; + + Common::SaveFileManager *_savefile; + Audio::MixerImpl *_mixer; + Common::TimerManager *_timer; + FilesystemFactory *_fsFactory; + timeval _startTime; + + Common::String getSystemProperty(const char *name) const; + + void initSurface(); + void deinitSurface(); + void initViewport(); + + void initOverlay(); + +#ifdef USE_RGB_COLOR + Common::String getPixelFormatName(const Graphics::PixelFormat &format) const; + void initTexture(GLESBaseTexture **texture, uint width, uint height, + const Graphics::PixelFormat *format); #endif -// Fix JNIEXPORT declaration to actually do something useful -#undef JNIEXPORT -#define JNIEXPORT __attribute__ ((visibility("default"))) + void setupKeymapper(); + void setCursorPaletteInternal(const byte *colors, uint start, uint num); + +public: + OSystem_Android(int audio_sample_rate, int audio_buffer_size); + virtual ~OSystem_Android(); + + virtual void initBackend(); + void addPluginDirectories(Common::FSList &dirs) const; + void enableZoning(bool enable) { _enable_zoning = enable; } + + virtual bool hasFeature(Feature f); + virtual void setFeatureState(Feature f, bool enable); + virtual bool getFeatureState(Feature f); + + virtual const GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual bool setGraphicsMode(int mode); + virtual int getGraphicsMode() const; + +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; +#endif + + virtual void initSize(uint width, uint height, + const Graphics::PixelFormat *format); + + enum FixupType { + kClear = 0, // glClear + kClearSwap, // glClear + swapBuffers + kClearUpdate // glClear + updateScreen + }; + + void clearScreen(FixupType type, byte count = 1); + + void updateScreenRect(); + virtual int getScreenChangeID() const; + + virtual int16 getHeight(); + virtual int16 getWidth(); + + virtual PaletteManager *getPaletteManager() { + return this; + } + +public: + void pushEvent(int type, int arg1, int arg2, int arg3, int arg4, int arg5); +private: + Common::Queue<Common::Event> _event_queue; + MutexRef _event_queue_lock; + + Common::Point _touch_pt_down, _touch_pt_scroll, _touch_pt_dt; + int _eventScaleX; + int _eventScaleY; + bool _touchpad_mode; + int _touchpad_scale; + int _trackball_scale; + int _dpad_scale; + int _fingersDown; + + void clipMouse(Common::Point &p); + void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true); + void updateEventScale(); + +protected: + // PaletteManager API + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + +public: + virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, + int w, int h); + virtual void updateScreen(); + virtual Graphics::Surface *lockScreen(); + virtual void unlockScreen(); + virtual void setShakePos(int shakeOffset); + virtual void fillScreen(uint32 col); + virtual void setFocusRectangle(const Common::Rect& rect); + virtual void clearFocusRectangle(); + + virtual void showOverlay(); + virtual void hideOverlay(); + virtual void clearOverlay(); + virtual void grabOverlay(OverlayColor *buf, int pitch); + virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, + int x, int y, int w, int h); + virtual int16 getOverlayHeight(); + virtual int16 getOverlayWidth(); + virtual Graphics::PixelFormat getOverlayFormat() const; + + virtual bool showMouse(bool visible); + + virtual void warpMouse(int x, int y); + virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, + int hotspotY, uint32 keycolor, + int cursorTargetScale, + const Graphics::PixelFormat *format); + virtual void setCursorPalette(const byte *colors, uint start, uint num); + virtual void disableCursorPalette(bool disable); + + virtual bool pollEvent(Common::Event &event); + virtual uint32 getMillis(); + virtual void delayMillis(uint msecs); + + virtual MutexRef createMutex(void); + virtual void lockMutex(MutexRef mutex); + virtual void unlockMutex(MutexRef mutex); + virtual void deleteMutex(MutexRef mutex); + + virtual void quit(); + + virtual void setWindowCaption(const char *caption); + virtual void displayMessageOnOSD(const char *msg); + virtual void showVirtualKeyboard(bool enable); + + virtual Common::SaveFileManager *getSavefileManager(); + virtual Audio::Mixer *getMixer(); + virtual void getTimeAndDate(TimeDate &t) const; + virtual Common::TimerManager *getTimerManager(); + virtual FilesystemFactory *getFilesystemFactory(); + virtual void logMessage(LogMessageType::Type type, const char *message); + virtual void addSysArchivesToSearchSet(Common::SearchSet &s, + int priority = 0); + virtual Common::String getSystemLanguage() const; +}; + +#endif #endif diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index 1bc3c3d21a..77fdb139d8 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -1,11 +1,12 @@ # Android specific build targets # These must be incremented for each market upload -#ANDROID_VERSIONCODE = 6 Specified in dists/android/AndroidManifest.xml.in +ANDROID_VERSIONCODE = 6 ANDROID_PLUGIN_VERSIONCODE = 6 JAVA_FILES = \ ScummVM.java \ + ScummVMEvents.java \ ScummVMApplication.java \ ScummVMActivity.java \ EditableSurfaceView.java \ @@ -21,6 +22,8 @@ JAVA_FILES_GEN = \ PATH_DIST = $(srcdir)/dists/android PATH_RESOURCES = $(PATH_DIST)/res +PORT_DISTFILES = $(PATH_DIST)/README.Android + RESOURCES = \ $(PATH_RESOURCES)/values/strings.xml \ $(PATH_RESOURCES)/layout/main.xml \ @@ -69,7 +72,8 @@ PATH_GEN = $(PATH_GEN_TOP)/$(PATH_REL) PATH_CLASSES_MAIN = $(PATH_BUILD_CLASSES_MAIN_TOP)/$(PATH_REL) PATH_CLASSES_PLUGIN = $(PATH_BUILD_CLASSES_PLUGIN_TOP)/$(PATH_REL) -FILE_MANIFEST = $(srcdir)/dists/android/AndroidManifest.xml +FILE_MANIFEST_SRC = $(srcdir)/dists/android/AndroidManifest.xml +FILE_MANIFEST = $(PATH_BUILD)/AndroidManifest.xml FILE_DEX = $(PATH_BUILD)/classes.dex FILE_DEX_PLUGIN = $(PATH_BUILD)/plugins/classes.dex FILE_RESOURCES = resources.ap_ @@ -84,6 +88,10 @@ CLASSES_PLUGIN = $(addprefix $(PATH_CLASSES_PLUGIN)/, $(JAVA_FILES_PLUGIN:%.java APK_MAIN = scummvm.apk APK_PLUGINS = $(patsubst plugins/lib%.so, scummvm-engine-%.apk, $(PLUGINS)) +$(FILE_MANIFEST): $(FILE_MANIFEST_SRC) + @$(MKDIR) -p $(@D) + sed "s/@ANDROID_VERSIONCODE@/$(ANDROID_VERSIONCODE)/" < $< > $@ + $(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8) @$(MKDIR) -p $(PATH_GEN_TOP) $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR8) @@ -107,14 +115,13 @@ $(FILE_DEX_PLUGIN): $(CLASSES_PLUGIN) @$(MKDIR) -p $(@D) $(DX) --dex --output=$@ $(PATH_BUILD_CLASSES_PLUGIN_TOP) -$(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml: $(PATH_DIST)/mkmanifest.pl $(srcdir)/configure $(PATH_DIST)/AndroidManifest.xml - $(PATH_DIST)/mkmanifest.pl --id=$* --configure=$(srcdir)/configure \ - --version-name=$(VERSION) \ - --version-code=$(ANDROID_PLUGIN_VERSIONCODE) \ - --stringres=$(PATH_STAGE_PREFIX).$*/res/values/strings.xml \ - --manifest=$(PATH_BUILD)/$*/AndroidManifest.xml \ - --master-manifest=$(PATH_DIST)/AndroidManifest.xml \ - --unpacklib=mylib/armeabi/lib$*.so +$(PATH_BUILD)/%/AndroidManifest.xml: $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $(PATH_DIST)/plugin-manifest.xml + @$(MKDIR) -p $(@D) + $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $* $(PATH_DIST)/plugin-manifest.xml $(ANDROID_PLUGIN_VERSIONCODE) $@ + +$(PATH_STAGE_PREFIX).%/res/values/strings.xml: $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $(PATH_DIST)/plugin-manifest.xml + @$(MKDIR) -p $(@D) + $(PATH_DIST)/mkplugin.sh $(srcdir)/configure $* $(PATH_DIST)/plugin-strings.xml $(ANDROID_PLUGIN_VERSIONCODE) $@ $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png: $(PATH_RESOURCES)/drawable/scummvm.png @$(MKDIR) -p $(@D) @@ -163,6 +170,10 @@ release/%.apk: %.apk androidrelease: $(addprefix release/, $(APK_MAIN) $(APK_PLUGINS)) +androidtestmain: $(APK_MAIN) + $(ADB) install -r $(APK_MAIN) + $(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker + androidtest: $(APK_MAIN) $(APK_PLUGINS) @set -e; for apk in $^; do \ $(ADB) install -r $$apk; \ @@ -173,7 +184,7 @@ androidtest: $(APK_MAIN) $(APK_PLUGINS) androiddistdebug: all $(MKDIR) debug $(CP) $(APK_MAIN) $(APK_PLUGINS) debug/ - for i in $(DIST_FILES_DOCS); do \ + for i in $(DIST_FILES_DOCS) $(PORT_DISTFILES); do \ sed 's/$$/\r/' < $$i > debug/`basename $$i`.txt; \ done diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp index 71ce25aa72..7c21b35281 100644 --- a/backends/platform/android/asset-archive.cpp +++ b/backends/platform/android/asset-archive.cpp @@ -35,11 +35,11 @@ #include "common/util.h" #include "common/archive.h" #include "common/debug.h" +#include "common/textconsole.h" +#include "backends/platform/android/jni.h" #include "backends/platform/android/asset-archive.h" -extern JNIEnv *JNU_GetEnv(); - // Must match android.content.res.AssetManager.ACCESS_* const jint ACCESS_UNKNOWN = 0; const jint ACCESS_RANDOM = 1; @@ -100,7 +100,7 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) : { _input_stream = env->NewGlobalRef(is); _buflen = 8192; - _buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen))); + _buf = (jbyteArray)env->NewGlobalRef(env->NewByteArray(_buflen)); jclass cls = env->GetObjectClass(_input_stream); MID_mark = env->GetMethodID(cls, "mark", "(I)V"); @@ -124,7 +124,7 @@ JavaInputStream::JavaInputStream(JNIEnv *env, jobject is) : } JavaInputStream::~JavaInputStream() { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); close(env); env->DeleteGlobalRef(_buf); @@ -139,11 +139,11 @@ void JavaInputStream::close(JNIEnv *env) { } uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); if (_buflen < jint(dataSize)) { _buflen = dataSize; - + env->DeleteGlobalRef(_buf); _buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen))); } @@ -171,7 +171,7 @@ uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) { } bool JavaInputStream::seek(int32 offset, int whence) { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); uint32 newpos; switch (whence) { @@ -305,7 +305,8 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) : _declared_len = env->CallLongMethod(_assetfd, MID_getDeclaredLength); jmethodID MID_getFileDescriptor = - env->GetMethodID(cls, "getFileDescriptor", "()Ljava/io/FileDescriptor;"); + env->GetMethodID(cls, "getFileDescriptor", + "()Ljava/io/FileDescriptor;"); assert(MID_getFileDescriptor); jobject javafd = env->CallObjectMethod(_assetfd, MID_getFileDescriptor); assert(javafd); @@ -318,7 +319,7 @@ AssetFdReadStream::AssetFdReadStream(JNIEnv *env, jobject assetfd) : } AssetFdReadStream::~AssetFdReadStream() { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); env->CallVoidMethod(_assetfd, MID_close); if (env->ExceptionCheck()) @@ -369,7 +370,7 @@ bool AssetFdReadStream::seek(int32 offset, int whence) { } AndroidAssetArchive::AndroidAssetArchive(jobject am) { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); _am = env->NewGlobalRef(am); jclass cls = env->GetObjectClass(_am); @@ -377,8 +378,8 @@ AndroidAssetArchive::AndroidAssetArchive(jobject am) { "(Ljava/lang/String;I)Ljava/io/InputStream;"); assert(MID_open); - MID_openFd = env->GetMethodID(cls, "openFd", - "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;"); + MID_openFd = env->GetMethodID(cls, "openFd", "(Ljava/lang/String;)" + "Landroid/content/res/AssetFileDescriptor;"); assert(MID_openFd); MID_list = env->GetMethodID(cls, "list", @@ -387,12 +388,12 @@ AndroidAssetArchive::AndroidAssetArchive(jobject am) { } AndroidAssetArchive::~AndroidAssetArchive() { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); env->DeleteGlobalRef(_am); } bool AndroidAssetArchive::hasFile(const Common::String &name) { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); jstring path = env->NewStringUTF(name.c_str()); jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN); if (env->ExceptionCheck()) { @@ -412,7 +413,7 @@ bool AndroidAssetArchive::hasFile(const Common::String &name) { } int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); Common::List<Common::String> dirlist; dirlist.push_back(""); @@ -422,7 +423,8 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) { dirlist.pop_back(); jstring jpath = env->NewStringUTF(dir.c_str()); - jobjectArray jpathlist = static_cast<jobjectArray>(env->CallObjectMethod(_am, MID_list, jpath)); + jobjectArray jpathlist = + (jobjectArray)env->CallObjectMethod(_am, MID_list, jpath); if (env->ExceptionCheck()) { warning("Error while calling AssetManager->list(%s). Ignoring.", @@ -439,19 +441,22 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) { for (jsize i = 0; i < env->GetArrayLength(jpathlist); ++i) { jstring elem = (jstring)env->GetObjectArrayElement(jpathlist, i); const char *p = env->GetStringUTFChars(elem, 0); - Common::String thispath = dir; - if (!thispath.empty()) - thispath += "/"; + if (strlen(p)) { + Common::String thispath = dir; + + if (!thispath.empty()) + thispath += "/"; - thispath += p; + thispath += p; - // Assume files have a . in them, and directories don't - if (strchr(p, '.')) { - member_list.push_back(getMember(thispath)); - ++count; - } else { - dirlist.push_back(thispath); + // Assume files have a . in them, and directories don't + if (strchr(p, '.')) { + member_list.push_back(getMember(thispath)); + ++count; + } else { + dirlist.push_back(thispath); + } } env->ReleaseStringUTFChars(elem, p); @@ -469,7 +474,7 @@ Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &na } Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const { - JNIEnv *env = JNU_GetEnv(); + JNIEnv *env = JNI::getEnv(); jstring jpath = env->NewStringUTF(path.c_str()); // Try openFd() first ... diff --git a/backends/platform/android/asset-archive.h b/backends/platform/android/asset-archive.h index 28e48426e9..6ec86e4cd0 100644 --- a/backends/platform/android/asset-archive.h +++ b/backends/platform/android/asset-archive.h @@ -23,6 +23,9 @@ * */ +#ifndef _ANDROID_ASSET_H_ +#define _ANDROID_ASSET_H_ + #if defined(__ANDROID__) #include <jni.h> @@ -51,3 +54,5 @@ private: }; #endif +#endif + diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp new file mode 100644 index 0000000000..2f140f0c0b --- /dev/null +++ b/backends/platform/android/events.cpp @@ -0,0 +1,822 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(__ANDROID__) + +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +// Disable printf override in common/forbidden.h to avoid +// clashes with log.h from the Android SDK. +// That header file uses +// __attribute__ ((format(printf, 3, 4))) +// which gets messed up by our override mechanism; this could +// be avoided by either changing the Android SDK to use the equally +// legal and valid +// __attribute__ ((format(printf, 3, 4))) +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the Android port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + +#include "common/events.h" + +#include "backends/platform/android/android.h" +#include "backends/platform/android/jni.h" + +// $ANDROID_NDK/platforms/android-9/arch-arm/usr/include/android/keycodes.h +// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=libs/ui/Input.cpp +// http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/KeyEvent.java + +// event type +enum { + JE_SYS_KEY = 0, + JE_KEY = 1, + JE_DPAD = 2, + JE_DOWN = 3, + JE_SCROLL = 4, + JE_TAP = 5, + JE_DOUBLE_TAP = 6, + JE_MULTI = 7, + JE_BALL = 8, + JE_QUIT = 0x1000 +}; + +// action type +enum { + JACTION_DOWN = 0, + JACTION_UP = 1, + JACTION_MULTIPLE = 2, + JACTION_POINTER_DOWN = 5, + JACTION_POINTER_UP = 6 +}; + +// system keys +enum { + JKEYCODE_SOFT_RIGHT = 2, + JKEYCODE_HOME = 3, + JKEYCODE_BACK = 4, + JKEYCODE_CALL = 5, + JKEYCODE_ENDCALL = 6, + JKEYCODE_VOLUME_UP = 24, + JKEYCODE_VOLUME_DOWN = 25, + JKEYCODE_POWER = 26, + JKEYCODE_CAMERA = 27, + JKEYCODE_HEADSETHOOK = 79, + JKEYCODE_FOCUS = 80, + JKEYCODE_MENU = 82, + JKEYCODE_SEARCH = 84, + JKEYCODE_MUTE = 91, + JKEYCODE_MEDIA_PLAY_PAUSE = 85, + JKEYCODE_MEDIA_STOP = 86, + JKEYCODE_MEDIA_NEXT = 87, + JKEYCODE_MEDIA_PREVIOUS = 88, + JKEYCODE_MEDIA_REWIND = 89, + JKEYCODE_MEDIA_FAST_FORWARD = 90 +}; + +// five-way navigation control +enum { + JKEYCODE_DPAD_UP = 19, + JKEYCODE_DPAD_DOWN = 20, + JKEYCODE_DPAD_LEFT = 21, + JKEYCODE_DPAD_RIGHT = 22, + JKEYCODE_DPAD_CENTER = 23 +}; + +// meta modifier +enum { + JMETA_SHIFT = 0x01, + JMETA_ALT = 0x02, + JMETA_SYM = 0x04, + JMETA_CTRL = 0x1000 +}; + +// map android key codes to our kbd codes +static const Common::KeyCode jkeymap[] = { + Common::KEYCODE_INVALID, // KEYCODE_UNKNOWN + Common::KEYCODE_INVALID, // KEYCODE_SOFT_LEFT + Common::KEYCODE_INVALID, // KEYCODE_SOFT_RIGHT + Common::KEYCODE_INVALID, // KEYCODE_HOME + Common::KEYCODE_INVALID, // KEYCODE_BACK + Common::KEYCODE_INVALID, // KEYCODE_CALL + Common::KEYCODE_INVALID, // KEYCODE_ENDCALL + Common::KEYCODE_0, // KEYCODE_0 + Common::KEYCODE_1, // KEYCODE_1 + Common::KEYCODE_2, // KEYCODE_2 + Common::KEYCODE_3, // KEYCODE_3 + Common::KEYCODE_4, // KEYCODE_4 + Common::KEYCODE_5, // KEYCODE_5 + Common::KEYCODE_6, // KEYCODE_6 + Common::KEYCODE_7, // KEYCODE_7 + Common::KEYCODE_8, // KEYCODE_8 + Common::KEYCODE_9, // KEYCODE_9 + Common::KEYCODE_ASTERISK, // KEYCODE_STAR + Common::KEYCODE_HASH, // KEYCODE_POUND + Common::KEYCODE_INVALID, // KEYCODE_DPAD_UP + Common::KEYCODE_INVALID, // KEYCODE_DPAD_DOWN + Common::KEYCODE_INVALID, // KEYCODE_DPAD_LEFT + Common::KEYCODE_INVALID, // KEYCODE_DPAD_RIGHT + Common::KEYCODE_INVALID, // KEYCODE_DPAD_CENTER + Common::KEYCODE_INVALID, // KEYCODE_VOLUME_UP + Common::KEYCODE_INVALID, // KEYCODE_VOLUME_DOWN + Common::KEYCODE_INVALID, // KEYCODE_POWER + Common::KEYCODE_INVALID, // KEYCODE_CAMERA + Common::KEYCODE_INVALID, // KEYCODE_CLEAR + Common::KEYCODE_a, // KEYCODE_A + Common::KEYCODE_b, // KEYCODE_B + Common::KEYCODE_c, // KEYCODE_C + Common::KEYCODE_d, // KEYCODE_D + Common::KEYCODE_e, // KEYCODE_E + Common::KEYCODE_f, // KEYCODE_F + Common::KEYCODE_g, // KEYCODE_G + Common::KEYCODE_h, // KEYCODE_H + Common::KEYCODE_i, // KEYCODE_I + Common::KEYCODE_j, // KEYCODE_J + Common::KEYCODE_k, // KEYCODE_K + Common::KEYCODE_l, // KEYCODE_L + Common::KEYCODE_m, // KEYCODE_M + Common::KEYCODE_n, // KEYCODE_N + Common::KEYCODE_o, // KEYCODE_O + Common::KEYCODE_p, // KEYCODE_P + Common::KEYCODE_q, // KEYCODE_Q + Common::KEYCODE_r, // KEYCODE_R + Common::KEYCODE_s, // KEYCODE_S + Common::KEYCODE_t, // KEYCODE_T + Common::KEYCODE_u, // KEYCODE_U + Common::KEYCODE_v, // KEYCODE_V + Common::KEYCODE_w, // KEYCODE_W + Common::KEYCODE_x, // KEYCODE_X + Common::KEYCODE_y, // KEYCODE_Y + Common::KEYCODE_z, // KEYCODE_Z + Common::KEYCODE_COMMA, // KEYCODE_COMMA + Common::KEYCODE_PERIOD, // KEYCODE_PERIOD + Common::KEYCODE_LALT, // KEYCODE_ALT_LEFT + Common::KEYCODE_RALT, // KEYCODE_ALT_RIGHT + Common::KEYCODE_LSHIFT, // KEYCODE_SHIFT_LEFT + Common::KEYCODE_RSHIFT, // KEYCODE_SHIFT_RIGHT + Common::KEYCODE_TAB, // KEYCODE_TAB + Common::KEYCODE_SPACE, // KEYCODE_SPACE + Common::KEYCODE_LCTRL, // KEYCODE_SYM + Common::KEYCODE_INVALID, // KEYCODE_EXPLORER + Common::KEYCODE_INVALID, // KEYCODE_ENVELOPE + Common::KEYCODE_RETURN, // KEYCODE_ENTER + Common::KEYCODE_BACKSPACE, // KEYCODE_DEL + Common::KEYCODE_BACKQUOTE, // KEYCODE_GRAVE + Common::KEYCODE_MINUS, // KEYCODE_MINUS + Common::KEYCODE_EQUALS, // KEYCODE_EQUALS + Common::KEYCODE_LEFTPAREN, // KEYCODE_LEFT_BRACKET + Common::KEYCODE_RIGHTPAREN, // KEYCODE_RIGHT_BRACKET + Common::KEYCODE_BACKSLASH, // KEYCODE_BACKSLASH + Common::KEYCODE_SEMICOLON, // KEYCODE_SEMICOLON + Common::KEYCODE_QUOTE, // KEYCODE_APOSTROPHE + Common::KEYCODE_SLASH, // KEYCODE_SLASH + Common::KEYCODE_AT, // KEYCODE_AT + Common::KEYCODE_INVALID, // KEYCODE_NUM + Common::KEYCODE_INVALID, // KEYCODE_HEADSETHOOK + Common::KEYCODE_INVALID, // KEYCODE_FOCUS + Common::KEYCODE_PLUS, // KEYCODE_PLUS + Common::KEYCODE_INVALID, // KEYCODE_MENU + Common::KEYCODE_INVALID, // KEYCODE_NOTIFICATION + Common::KEYCODE_INVALID, // KEYCODE_SEARCH + Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PLAY_PAUSE + Common::KEYCODE_INVALID, // KEYCODE_MEDIA_STOP + Common::KEYCODE_INVALID, // KEYCODE_MEDIA_NEXT + Common::KEYCODE_INVALID, // KEYCODE_MEDIA_PREVIOUS + Common::KEYCODE_INVALID, // KEYCODE_MEDIA_REWIND + Common::KEYCODE_INVALID, // KEYCODE_MEDIA_FAST_FORWARD + Common::KEYCODE_INVALID, // KEYCODE_MUTE + Common::KEYCODE_PAGEUP, // KEYCODE_PAGE_UP + Common::KEYCODE_PAGEDOWN // KEYCODE_PAGE_DOWN +}; + +// floating point. use sparingly +template <class T> +static inline T scalef(T in, float numerator, float denominator) { + return static_cast<float>(in) * numerator / denominator; +} + +void OSystem_Android::setupKeymapper() { +#ifdef ENABLE_KEYMAPPER + using namespace Common; + + Keymapper *mapper = getEventManager()->getKeymapper(); + + HardwareKeySet *keySet = new HardwareKeySet(); + + keySet->addHardwareKey( + new HardwareKey("n", KeyState(KEYCODE_n), "n (vk)", + kTriggerLeftKeyType, + kVirtualKeyboardActionType)); + + mapper->registerHardwareKeySet(keySet); + + Keymap *globalMap = new Keymap("global"); + Action *act; + + act = new Action(globalMap, "VIRT", "Display keyboard", + kVirtualKeyboardActionType); + act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); + + mapper->addGlobalKeymap(globalMap); + + mapper->pushKeymap("global"); +#endif +} + +void OSystem_Android::warpMouse(int x, int y) { + ENTER("%d, %d", x, y); + + Common::Event e; + + e.type = Common::EVENT_MOUSEMOVE; + e.mouse.x = x; + e.mouse.y = y; + + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); +} + +void OSystem_Android::clipMouse(Common::Point &p) { + const GLESBaseTexture *tex; + + if (_show_overlay) + tex = _overlay_texture; + else + tex = _game_texture; + + p.x = CLIP(p.x, int16(0), int16(tex->width() - 1)); + p.y = CLIP(p.y, int16(0), int16(tex->height() - 1)); +} + +void OSystem_Android::scaleMouse(Common::Point &p, int x, int y, + bool deductDrawRect) { + const GLESBaseTexture *tex; + + if (_show_overlay) + tex = _overlay_texture; + else + tex = _game_texture; + + const Common::Rect &r = tex->getDrawRect(); + + if (_touchpad_mode) { + x = x * 100 / _touchpad_scale; + y = y * 100 / _touchpad_scale; + } + + if (deductDrawRect) { + x -= r.left; + y -= r.top; + } + + p.x = scalef(x, tex->width(), r.width()); + p.y = scalef(y, tex->height(), r.height()); +} + +void OSystem_Android::updateEventScale() { + const GLESBaseTexture *tex; + + if (_show_overlay) + tex = _overlay_texture; + else + tex = _game_texture; + + _eventScaleY = 100 * 480 / tex->height(); + _eventScaleX = 100 * 640 / tex->width(); +} + +void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, + int arg4, int arg5) { + Common::Event e; + + switch (type) { + case JE_SYS_KEY: + switch (arg1) { + case JACTION_DOWN: + e.type = Common::EVENT_KEYDOWN; + break; + case JACTION_UP: + e.type = Common::EVENT_KEYUP; + break; + default: + LOGE("unhandled jaction on system key: %d", arg1); + return; + } + + switch (arg2) { + case JKEYCODE_BACK: + e.kbd.keycode = Common::KEYCODE_ESCAPE; + e.kbd.ascii = Common::ASCII_ESCAPE; + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + // special case. we'll only get it's up event + case JKEYCODE_MENU: + e.type = Common::EVENT_MAINMENU; + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JKEYCODE_CAMERA: + case JKEYCODE_SEARCH: + if (arg1 == JACTION_DOWN) + e.type = Common::EVENT_RBUTTONDOWN; + else + e.type = Common::EVENT_RBUTTONUP; + + e.mouse = getEventManager()->getMousePos(); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + default: + LOGW("unmapped system key: %d", arg2); + return; + } + + break; + + case JE_KEY: + switch (arg1) { + case JACTION_DOWN: + e.type = Common::EVENT_KEYDOWN; + break; + case JACTION_UP: + e.type = Common::EVENT_KEYUP; + break; + default: + LOGE("unhandled jaction on key: %d", arg1); + return; + } + + if (arg2 < 1 || arg2 > ARRAYSIZE(jkeymap)) { + if (arg3 < 1) { + LOGE("received invalid keycode: %d (%d)", arg2, arg3); + return; + } else { + // lets bet on the ascii code + e.kbd.keycode = Common::KEYCODE_INVALID; + } + } else { + e.kbd.keycode = jkeymap[arg2]; + } + + if (arg5 > 0) + e.synthetic = true; + + // map special keys to 'our' ascii codes + switch (e.kbd.keycode) { + case Common::KEYCODE_BACKSPACE: + e.kbd.ascii = Common::ASCII_BACKSPACE; + break; + case Common::KEYCODE_TAB: + e.kbd.ascii = Common::ASCII_TAB; + break; + case Common::KEYCODE_RETURN: + e.kbd.ascii = Common::ASCII_RETURN; + break; + case Common::KEYCODE_ESCAPE: + e.kbd.ascii = Common::ASCII_ESCAPE; + break; + case Common::KEYCODE_SPACE: + e.kbd.ascii = Common::ASCII_SPACE; + break; + case Common::KEYCODE_F1: + e.kbd.ascii = Common::ASCII_F1; + break; + case Common::KEYCODE_F2: + e.kbd.ascii = Common::ASCII_F2; + break; + case Common::KEYCODE_F3: + e.kbd.ascii = Common::ASCII_F3; + break; + case Common::KEYCODE_F4: + e.kbd.ascii = Common::ASCII_F4; + break; + case Common::KEYCODE_F5: + e.kbd.ascii = Common::ASCII_F5; + break; + case Common::KEYCODE_F6: + e.kbd.ascii = Common::ASCII_F6; + break; + case Common::KEYCODE_F7: + e.kbd.ascii = Common::ASCII_F7; + break; + case Common::KEYCODE_F8: + e.kbd.ascii = Common::ASCII_F8; + break; + case Common::KEYCODE_F9: + e.kbd.ascii = Common::ASCII_F9; + break; + case Common::KEYCODE_F10: + e.kbd.ascii = Common::ASCII_F10; + break; + case Common::KEYCODE_F11: + e.kbd.ascii = Common::ASCII_F11; + break; + case Common::KEYCODE_F12: + e.kbd.ascii = Common::ASCII_F12; + break; + default: + e.kbd.ascii = arg3; + break; + } + + if (arg4 & JMETA_SHIFT) + e.kbd.flags |= Common::KBD_SHIFT; + if (arg4 & JMETA_ALT) + e.kbd.flags |= Common::KBD_ALT; + if (arg4 & (JMETA_SYM | JMETA_CTRL)) + e.kbd.flags |= Common::KBD_CTRL; + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_DPAD: + switch (arg2) { + case JKEYCODE_DPAD_UP: + case JKEYCODE_DPAD_DOWN: + case JKEYCODE_DPAD_LEFT: + case JKEYCODE_DPAD_RIGHT: + if (arg1 != JACTION_DOWN) + return; + + e.type = Common::EVENT_MOUSEMOVE; + + e.mouse = getEventManager()->getMousePos(); + + { + int16 *c; + int s; + + if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_DOWN) { + c = &e.mouse.y; + s = _eventScaleY; + } else { + c = &e.mouse.x; + s = _eventScaleX; + } + + // the longer the button held, the faster the pointer is + // TODO put these values in some option dlg? + int f = CLIP(arg4, 1, 8) * _dpad_scale * 100 / s; + + if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_LEFT) + *c -= f; + else + *c += f; + } + + clipMouse(e.mouse); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JKEYCODE_DPAD_CENTER: + switch (arg1) { + case JACTION_DOWN: + e.type = Common::EVENT_LBUTTONDOWN; + break; + case JACTION_UP: + e.type = Common::EVENT_LBUTTONUP; + break; + default: + LOGE("unhandled jaction on dpad key: %d", arg1); + return; + } + + e.mouse = getEventManager()->getMousePos(); + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + } + + case JE_DOWN: + _touch_pt_down = getEventManager()->getMousePos(); + _touch_pt_scroll.x = -1; + _touch_pt_scroll.y = -1; + break; + + case JE_SCROLL: + e.type = Common::EVENT_MOUSEMOVE; + + if (_touchpad_mode) { + if (_touch_pt_scroll.x == -1 && _touch_pt_scroll.y == -1) { + _touch_pt_scroll.x = arg3; + _touch_pt_scroll.y = arg4; + return; + } + + scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x, + arg4 - _touch_pt_scroll.y, false); + e.mouse += _touch_pt_down; + clipMouse(e.mouse); + } else { + scaleMouse(e.mouse, arg3, arg4); + clipMouse(e.mouse); + } + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_TAP: + if (_fingersDown > 0) { + _fingersDown = 0; + return; + } + + e.type = Common::EVENT_MOUSEMOVE; + + if (_touchpad_mode) { + e.mouse = getEventManager()->getMousePos(); + } else { + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + } + + { + Common::EventType down, up; + + // TODO put these values in some option dlg? + if (arg3 > 1000) { + down = Common::EVENT_MBUTTONDOWN; + up = Common::EVENT_MBUTTONUP; + } else if (arg3 > 500) { + down = Common::EVENT_RBUTTONDOWN; + up = Common::EVENT_RBUTTONUP; + } else { + down = Common::EVENT_LBUTTONDOWN; + up = Common::EVENT_LBUTTONUP; + } + + lockMutex(_event_queue_lock); + + if (!_touchpad_mode) + _event_queue.push(e); + + e.type = down; + _event_queue.push(e); + e.type = up; + _event_queue.push(e); + + unlockMutex(_event_queue_lock); + } + + return; + + case JE_DOUBLE_TAP: + e.type = Common::EVENT_MOUSEMOVE; + + if (_touchpad_mode) { + e.mouse = getEventManager()->getMousePos(); + } else { + scaleMouse(e.mouse, arg1, arg2); + clipMouse(e.mouse); + } + + { + Common::EventType dptype = Common::EVENT_INVALID; + + switch (arg3) { + case JACTION_DOWN: + dptype = Common::EVENT_LBUTTONDOWN; + _touch_pt_dt.x = -1; + _touch_pt_dt.y = -1; + break; + case JACTION_UP: + dptype = Common::EVENT_LBUTTONUP; + break; + // held and moved + case JACTION_MULTIPLE: + if (_touch_pt_dt.x == -1 && _touch_pt_dt.y == -1) { + _touch_pt_dt.x = arg1; + _touch_pt_dt.y = arg2; + return; + } + + dptype = Common::EVENT_MOUSEMOVE; + + if (_touchpad_mode) { + scaleMouse(e.mouse, arg1 - _touch_pt_dt.x, + arg2 - _touch_pt_dt.y, false); + e.mouse += _touch_pt_down; + + clipMouse(e.mouse); + } + + break; + default: + LOGE("unhandled jaction on double tap: %d", arg3); + return; + } + + lockMutex(_event_queue_lock); + _event_queue.push(e); + e.type = dptype; + _event_queue.push(e); + unlockMutex(_event_queue_lock); + } + + return; + + case JE_MULTI: + switch (arg2) { + case JACTION_POINTER_DOWN: + if (arg1 > _fingersDown) + _fingersDown = arg1; + + return; + + case JACTION_POINTER_UP: + if (arg1 != _fingersDown) + return; + + { + Common::EventType up; + + switch (_fingersDown) { + case 1: + e.type = Common::EVENT_RBUTTONDOWN; + up = Common::EVENT_RBUTTONUP; + break; + case 2: + e.type = Common::EVENT_MBUTTONDOWN; + up = Common::EVENT_MBUTTONUP; + break; + default: + LOGD("unmapped multi tap: %d", _fingersDown); + return; + } + + e.mouse = getEventManager()->getMousePos(); + + lockMutex(_event_queue_lock); + + _event_queue.push(e); + e.type = up; + _event_queue.push(e); + + unlockMutex(_event_queue_lock); + return; + + default: + LOGE("unhandled jaction on multi tap: %d", arg2); + return; + } + } + + return; + + case JE_BALL: + e.mouse = getEventManager()->getMousePos(); + + switch (arg1) { + case JACTION_DOWN: + e.type = Common::EVENT_LBUTTONDOWN; + break; + case JACTION_UP: + e.type = Common::EVENT_LBUTTONUP; + break; + case JACTION_MULTIPLE: + e.type = Common::EVENT_MOUSEMOVE; + + // already multiplied by 100 + e.mouse.x += arg2 * _trackball_scale / _eventScaleX; + e.mouse.y += arg3 * _trackball_scale / _eventScaleY; + + clipMouse(e.mouse); + + break; + default: + LOGE("unhandled jaction on system key: %d", arg1); + return; + } + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_QUIT: + e.type = Common::EVENT_QUIT; + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + default: + LOGE("unknown jevent type: %d", type); + + break; + } +} + +bool OSystem_Android::pollEvent(Common::Event &event) { + //ENTER(); + + if (pthread_self() == _main_thread) { + if (_screen_changeid != JNI::surface_changeid) { + if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) { + // surface changed + JNI::deinitSurface(); + initSurface(); + initViewport(); + updateScreenRect(); + updateEventScale(); + + // double buffered, flip twice + clearScreen(kClearUpdate, 2); + + event.type = Common::EVENT_SCREEN_CHANGED; + + return true; + } else { + // surface lost + deinitSurface(); + } + } + + if (JNI::pause) { + deinitSurface(); + + LOGD("main thread going to sleep"); + sem_wait(&JNI::pause_sem); + LOGD("main thread woke up"); + } + } + + lockMutex(_event_queue_lock); + + if (_event_queue.empty()) { + unlockMutex(_event_queue_lock); + return false; + } + + event = _event_queue.pop(); + + unlockMutex(_event_queue_lock); + + if (event.type == Common::EVENT_MOUSEMOVE) { + const Common::Point &m = getEventManager()->getMousePos(); + + if (m != event.mouse) + _force_redraw = true; + } + + return true; +} + +#endif + diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp new file mode 100644 index 0000000000..ebce58e291 --- /dev/null +++ b/backends/platform/android/gfx.cpp @@ -0,0 +1,836 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(__ANDROID__) + +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +// Disable printf override in common/forbidden.h to avoid +// clashes with log.h from the Android SDK. +// That header file uses +// __attribute__ ((format(printf, 3, 4))) +// which gets messed up by our override mechanism; this could +// be avoided by either changing the Android SDK to use the equally +// legal and valid +// __attribute__ ((format(printf, 3, 4))) +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the Android port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + +#include "common/endian.h" +#include "graphics/conversion.h" + +#include "backends/platform/android/android.h" +#include "backends/platform/android/jni.h" + +static inline GLfixed xdiv(int numerator, int denominator) { + assert(numerator < (1 << 16)); + return (numerator << 16) / denominator; +} + +const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const { + static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { + { "default", "Default", 0 }, + { "filter", "Linear filtering", 1 }, + { 0, 0, 0 }, + }; + + return s_supportedGraphicsModes; +} + +int OSystem_Android::getDefaultGraphicsMode() const { + return 0; +} + +bool OSystem_Android::setGraphicsMode(int mode) { + ENTER("%d", mode); + + if (_game_texture) + _game_texture->setLinearFilter(mode == 1); + + if (_overlay_texture) + _overlay_texture->setLinearFilter(mode == 1); + + if (_mouse_texture) + _mouse_texture->setLinearFilter(mode == 1); + + _graphicsMode = mode; + + return true; +} + +int OSystem_Android::getGraphicsMode() const { + return _graphicsMode; +} + +#ifdef USE_RGB_COLOR +Graphics::PixelFormat OSystem_Android::getScreenFormat() const { + return _game_texture->getPixelFormat(); +} + +Common::List<Graphics::PixelFormat> OSystem_Android::getSupportedFormats() const { + Common::List<Graphics::PixelFormat> res; + res.push_back(GLES565Texture::pixelFormat()); + res.push_back(GLES5551Texture::pixelFormat()); + res.push_back(GLES4444Texture::pixelFormat()); + res.push_back(Graphics::PixelFormat::createFormatCLUT8()); + + return res; +} + +Common::String OSystem_Android::getPixelFormatName(const Graphics::PixelFormat &format) const { + if (format.bytesPerPixel == 1) + return "CLUT8"; + + if (format.aLoss == 8) + return Common::String::format("RGB%u%u%u", + 8 - format.rLoss, + 8 - format.gLoss, + 8 - format.bLoss); + + return Common::String::format("RGBA%u%u%u%u", + 8 - format.rLoss, + 8 - format.gLoss, + 8 - format.bLoss, + 8 - format.aLoss); +} + +void OSystem_Android::initTexture(GLESBaseTexture **texture, + uint width, uint height, + const Graphics::PixelFormat *format) { + assert(texture); + Graphics::PixelFormat format_clut8 = + Graphics::PixelFormat::createFormatCLUT8(); + Graphics::PixelFormat format_current; + Graphics::PixelFormat format_new; + + if (*texture) + format_current = (*texture)->getPixelFormat(); + else + format_current = Graphics::PixelFormat(); + + if (format) + format_new = *format; + else + format_new = format_clut8; + + if (format_current != format_new) { + if (*texture) + LOGD("switching pixel format from: %s", + getPixelFormatName((*texture)->getPixelFormat()).c_str()); + + delete *texture; + + if (format_new == GLES565Texture::pixelFormat()) + *texture = new GLES565Texture(); + else if (format_new == GLES5551Texture::pixelFormat()) + *texture = new GLES5551Texture(); + else if (format_new == GLES4444Texture::pixelFormat()) + *texture = new GLES4444Texture(); + else { + // TODO what now? + if (format_new != format_clut8) + LOGE("unsupported pixel format: %s", + getPixelFormatName(format_new).c_str()); + + *texture = new GLESFakePalette565Texture; + } + + LOGD("new pixel format: %s", + getPixelFormatName((*texture)->getPixelFormat()).c_str()); + } + + (*texture)->allocBuffer(width, height); +} +#endif + +void OSystem_Android::initSurface() { + LOGD("initializing surface"); + + assert(!JNI::haveSurface()); + + _screen_changeid = JNI::surface_changeid; + _egl_surface_width = JNI::egl_surface_width; + _egl_surface_height = JNI::egl_surface_height; + + assert(_egl_surface_width > 0 && _egl_surface_height > 0); + + JNI::initSurface(); + + // Initialise OpenGLES context. + GLESTexture::initGLExtensions(); + + if (_game_texture) + _game_texture->reinit(); + + if (_overlay_texture) { + _overlay_texture->reinit(); + initOverlay(); + } + + if (_mouse_texture) + _mouse_texture->reinit(); +} + +void OSystem_Android::deinitSurface() { + if (!JNI::haveSurface()) + return; + + LOGD("deinitializing surface"); + + _screen_changeid = JNI::surface_changeid; + _egl_surface_width = 0; + _egl_surface_height = 0; + + // release texture resources + if (_game_texture) + _game_texture->release(); + + if (_overlay_texture) + _overlay_texture->release(); + + if (_mouse_texture) + _mouse_texture->release(); + + JNI::deinitSurface(); +} + +void OSystem_Android::initViewport() { + LOGD("initializing viewport"); + + assert(JNI::haveSurface()); + + // Turn off anything that looks like 3D ;) + GLCALL(glDisable(GL_CULL_FACE)); + GLCALL(glDisable(GL_DEPTH_TEST)); + GLCALL(glDisable(GL_LIGHTING)); + GLCALL(glDisable(GL_FOG)); + GLCALL(glDisable(GL_DITHER)); + + GLCALL(glShadeModel(GL_FLAT)); + GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); + + GLCALL(glEnable(GL_BLEND)); + GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + + GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); + GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + + GLCALL(glEnable(GL_TEXTURE_2D)); + + GLCALL(glViewport(0, 0, _egl_surface_width, _egl_surface_height)); + + GLCALL(glMatrixMode(GL_PROJECTION)); + GLCALL(glLoadIdentity()); + GLCALL(glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1)); + GLCALL(glMatrixMode(GL_MODELVIEW)); + GLCALL(glLoadIdentity()); + + clearFocusRectangle(); +} + +void OSystem_Android::initOverlay() { + // minimum of 320x200 + // (surface can get smaller when opening the virtual keyboard on *QVGA*) + int overlay_width = MAX(_egl_surface_width, 320); + int overlay_height = MAX(_egl_surface_height, 200); + + // the 'normal' theme layout uses a max height of 400 pixels. if the + // surface is too big we use only a quarter of the size so that the widgets + // don't get too small. if the surface height has less than 800 pixels, this + // enforces the 'lowres' layout, which will be scaled back up by factor 2x, + // but this looks way better than the 'normal' layout scaled by some + // calculated factors + while (overlay_height > 480) { + overlay_width /= 2; + overlay_height /= 2; + } + + LOGI("overlay size is %ux%u", overlay_width, overlay_height); + + _overlay_texture->allocBuffer(overlay_width, overlay_height); + _overlay_texture->setDrawRect(0, 0, + _egl_surface_width, _egl_surface_height); +} + +void OSystem_Android::initSize(uint width, uint height, + const Graphics::PixelFormat *format) { + ENTER("%d, %d, %p", width, height, format); + + GLTHREADCHECK; + +#ifdef USE_RGB_COLOR + initTexture(&_game_texture, width, height, format); +#else + _game_texture->allocBuffer(width, height); +#endif + + updateScreenRect(); + updateEventScale(); + + // Don't know mouse size yet - it gets reallocated in + // setMouseCursor. We need the palette allocated before + // setMouseCursor however, so just take a guess at the desired + // size (it's small). + _mouse_texture_palette->allocBuffer(20, 20); + + clearScreen(kClear); +} + +void OSystem_Android::clearScreen(FixupType type, byte count) { + assert(count > 0); + + bool sm = _show_mouse; + _show_mouse = false; + + GLCALL(glDisable(GL_SCISSOR_TEST)); + + for (byte i = 0; i < count; ++i) { + // clear screen + GLCALL(glClearColorx(0, 0, 0, 1 << 16)); + GLCALL(glClear(GL_COLOR_BUFFER_BIT)); + + switch (type) { + case kClear: + break; + + case kClearSwap: + JNI::swapBuffers(); + break; + + case kClearUpdate: + _force_redraw = true; + updateScreen(); + break; + } + } + + if (!_show_overlay) + GLCALL(glEnable(GL_SCISSOR_TEST)); + + _show_mouse = sm; + _force_redraw = true; +} + +void OSystem_Android::updateScreenRect() { + Common::Rect rect(0, 0, _egl_surface_width, _egl_surface_height); + + _overlay_texture->setDrawRect(rect); + + uint16 w = _game_texture->width(); + uint16 h = _game_texture->height(); + + if (w && h && !_fullscreen) { + if (_ar_correction && w == 320 && h == 200) + h = 240; + + float dpi[2]; + JNI::getDPI(dpi); + + float screen_ar; + if (dpi[0] != 0.0 && dpi[1] != 0.0) { + // horizontal orientation + screen_ar = (dpi[1] * _egl_surface_width) / + (dpi[0] * _egl_surface_height); + } else { + screen_ar = float(_egl_surface_width) / float(_egl_surface_height); + } + + float game_ar = float(w) / float(h); + + if (screen_ar > game_ar) { + rect.setWidth(round(_egl_surface_height * game_ar)); + rect.moveTo((_egl_surface_width - rect.width()) / 2, 0); + } else { + rect.setHeight(round(_egl_surface_width / game_ar)); + rect.moveTo((_egl_surface_height - rect.height()) / 2, 0); + } + } + + glScissor(rect.left, rect.top, rect.width(), rect.height()); + + _game_texture->setDrawRect(rect); +} + +int OSystem_Android::getScreenChangeID() const { + return _screen_changeid; +} + +int16 OSystem_Android::getHeight() { + return _game_texture->height(); +} + +int16 OSystem_Android::getWidth() { + return _game_texture->width(); +} + +void OSystem_Android::setPalette(const byte *colors, uint start, uint num) { + ENTER("%p, %u, %u", colors, start, num); + +#ifdef USE_RGB_COLOR + assert(_game_texture->hasPalette()); +#endif + + GLTHREADCHECK; + + if (!_use_mouse_palette) + setCursorPaletteInternal(colors, start, num); + + const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat(); + byte *p = _game_texture->palette() + start * 2; + + for (uint i = 0; i < num; ++i, colors += 3, p += 2) + WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2])); +} + +void OSystem_Android::grabPalette(byte *colors, uint start, uint num) { + ENTER("%p, %u, %u", colors, start, num); + +#ifdef USE_RGB_COLOR + assert(_game_texture->hasPalette()); +#endif + + GLTHREADCHECK; + + const Graphics::PixelFormat &pf = _game_texture->getPalettePixelFormat(); + const byte *p = _game_texture->palette_const() + start * 2; + + for (uint i = 0; i < num; ++i, colors += 3, p += 2) + pf.colorToRGB(READ_UINT16(p), colors[0], colors[1], colors[2]); +} + +void OSystem_Android::copyRectToScreen(const byte *buf, int pitch, + int x, int y, int w, int h) { + ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h); + + GLTHREADCHECK; + + _game_texture->updateBuffer(x, y, w, h, buf, pitch); +} + +void OSystem_Android::updateScreen() { + //ENTER(); + + GLTHREADCHECK; + + if (!JNI::haveSurface()) + return; + + if (!_force_redraw && + !_game_texture->dirty() && + !_overlay_texture->dirty() && + !_mouse_texture->dirty()) + return; + + _force_redraw = false; + + // clear pointer leftovers in dead areas + // also, HTC's GLES drivers are made of fail and don't preserve the buffer + // ( http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html ) + if ((_show_overlay || _htc_fail) && !_fullscreen) + clearScreen(kClear); + + GLCALL(glPushMatrix()); + + if (_shake_offset != 0 || + (!_focus_rect.isEmpty() && + !Common::Rect(_game_texture->width(), + _game_texture->height()).contains(_focus_rect))) { + // These are the only cases where _game_texture doesn't + // cover the entire screen. + clearScreen(kClear); + + // Move everything up by _shake_offset (game) pixels + GLCALL(glTranslatex(0, -_shake_offset << 16, 0)); + } + +// TODO this doesnt work on those sucky drivers, do it differently +// if (_show_overlay) +// GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f)); + + if (_focus_rect.isEmpty()) { + _game_texture->drawTextureRect(); + } else { + GLCALL(glPushMatrix()); + + GLCALL(glScalex(xdiv(_egl_surface_width, _focus_rect.width()), + xdiv(_egl_surface_height, _focus_rect.height()), + 1 << 16)); + GLCALL(glTranslatex(-_focus_rect.left << 16, + -_focus_rect.top << 16, 0)); + GLCALL(glScalex(xdiv(_game_texture->width(), _egl_surface_width), + xdiv(_game_texture->height(), _egl_surface_height), + 1 << 16)); + + _game_texture->drawTextureRect(); + + GLCALL(glPopMatrix()); + } + + int cs = _mouse_targetscale; + + if (_show_overlay) { +// TODO see above +// GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff)); + + // ugly, but the modern theme sets a wacko factor, only god knows why + cs = 1; + + GLCALL(_overlay_texture->drawTextureRect()); + } + + if (_show_mouse && !_mouse_texture->isEmpty()) { + GLCALL(glPushMatrix()); + + const Common::Point &mouse = getEventManager()->getMousePos(); + + // Scale up ScummVM -> OpenGL (pixel) coordinates + if (_show_overlay) { + GLCALL(glScalex(xdiv(_egl_surface_width, + _overlay_texture->width()), + xdiv(_egl_surface_height, + _overlay_texture->height()), + 1 << 16)); + } else { + const Common::Rect &r = _game_texture->getDrawRect(); + + GLCALL(glTranslatex(r.left << 16, + r.top << 16, + 0)); + GLCALL(glScalex(xdiv(r.width(), _game_texture->width()), + xdiv(r.height(), _game_texture->height()), + 1 << 16)); + } + + GLCALL(glTranslatex((-_mouse_hotspot.x * cs) << 16, + (-_mouse_hotspot.y * cs) << 16, + 0)); + + // Note the extra half texel to position the mouse in + // the middle of the x,y square: + GLCALL(glTranslatex((mouse.x << 16) | 1 << 15, + (mouse.y << 16) | 1 << 15, 0)); + + GLCALL(glScalex(cs << 16, cs << 16, 1 << 16)); + + _mouse_texture->drawTextureOrigin(); + + GLCALL(glPopMatrix()); + } + + GLCALL(glPopMatrix()); + + if (!JNI::swapBuffers()) + LOGW("swapBuffers failed: 0x%x", glGetError()); +} + +Graphics::Surface *OSystem_Android::lockScreen() { + ENTER(); + + GLTHREADCHECK; + + Graphics::Surface *surface = _game_texture->surface(); + assert(surface->pixels); + + return surface; +} + +void OSystem_Android::unlockScreen() { + ENTER(); + + GLTHREADCHECK; + + assert(_game_texture->dirty()); +} + +void OSystem_Android::setShakePos(int shake_offset) { + ENTER("%d", shake_offset); + + if (_shake_offset != shake_offset) { + _shake_offset = shake_offset; + _force_redraw = true; + } +} + +void OSystem_Android::fillScreen(uint32 col) { + ENTER("%u", col); + + GLTHREADCHECK; + + _game_texture->fillBuffer(col); +} + +void OSystem_Android::setFocusRectangle(const Common::Rect& rect) { + ENTER("%d, %d, %d, %d", rect.left, rect.top, rect.right, rect.bottom); + + if (_enable_zoning) { + _focus_rect = rect; + _force_redraw = true; + } +} + +void OSystem_Android::clearFocusRectangle() { + ENTER(); + + if (_enable_zoning) { + _focus_rect = Common::Rect(); + _force_redraw = true; + } +} + +void OSystem_Android::showOverlay() { + ENTER(); + + _show_overlay = true; + _force_redraw = true; + + updateEventScale(); + + warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2); + + GLCALL(glDisable(GL_SCISSOR_TEST)); +} + +void OSystem_Android::hideOverlay() { + ENTER(); + + _show_overlay = false; + + updateEventScale(); + + warpMouse(_game_texture->width() / 2, _game_texture->height() / 2); + + // double buffered, flip twice + clearScreen(kClearUpdate, 2); + + GLCALL(glEnable(GL_SCISSOR_TEST)); +} + +void OSystem_Android::clearOverlay() { + ENTER(); + + GLTHREADCHECK; + + _overlay_texture->fillBuffer(0); +} + +void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) { + ENTER("%p, %d", buf, pitch); + + GLTHREADCHECK; + + const Graphics::Surface *surface = _overlay_texture->surface_const(); + assert(surface->format.bytesPerPixel == sizeof(buf[0])); + + const byte *src = (const byte *)surface->pixels; + uint h = surface->h; + + do { + memcpy(buf, src, surface->w * surface->format.bytesPerPixel); + src += surface->pitch; + // This 'pitch' is pixels not bytes + buf += pitch; + } while (--h); +} + +void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch, + int x, int y, int w, int h) { + ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h); + + GLTHREADCHECK; + + // This 'pitch' is pixels not bytes + _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0])); +} + +int16 OSystem_Android::getOverlayHeight() { + return _overlay_texture->height(); +} + +int16 OSystem_Android::getOverlayWidth() { + return _overlay_texture->width(); +} + +Graphics::PixelFormat OSystem_Android::getOverlayFormat() const { + return _overlay_texture->getPixelFormat(); +} + +bool OSystem_Android::showMouse(bool visible) { + ENTER("%d", visible); + + _show_mouse = visible; + + return true; +} + +void OSystem_Android::setMouseCursor(const byte *buf, uint w, uint h, + int hotspotX, int hotspotY, + uint32 keycolor, int cursorTargetScale, + const Graphics::PixelFormat *format) { + ENTER("%p, %u, %u, %d, %d, %u, %d, %p", buf, w, h, hotspotX, hotspotY, + keycolor, cursorTargetScale, format); + + GLTHREADCHECK; + +#ifdef USE_RGB_COLOR + if (format && format->bytesPerPixel > 1) { + if (_mouse_texture != _mouse_texture_rgb) { + LOGD("switching to rgb mouse cursor"); + + assert(!_mouse_texture_rgb); + _mouse_texture_rgb = new GLES5551Texture(); + _mouse_texture_rgb->setLinearFilter(_graphicsMode == 1); + } + + _mouse_texture = _mouse_texture_rgb; + } else { + if (_mouse_texture != _mouse_texture_palette) + LOGD("switching to paletted mouse cursor"); + + _mouse_texture = _mouse_texture_palette; + + delete _mouse_texture_rgb; + _mouse_texture_rgb = 0; + } +#endif + + _mouse_texture->allocBuffer(w, h); + + if (_mouse_texture == _mouse_texture_palette) { + assert(keycolor < 256); + + byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; + WRITE_UINT16(p, READ_UINT16(p) | 1); + + _mouse_keycolor = keycolor; + + p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; + WRITE_UINT16(p, READ_UINT16(p) & ~1); + } + + if (w == 0 || h == 0) + return; + + if (_mouse_texture == _mouse_texture_palette) { + _mouse_texture->updateBuffer(0, 0, w, h, buf, w); + } else { + uint16 pitch = _mouse_texture->pitch(); + + byte *tmp = new byte[pitch * h]; + + // meh, a 16bit cursor without alpha bits... this is so silly + if (!crossBlit(tmp, buf, pitch, w * 2, w, h, + _mouse_texture->getPixelFormat(), + *format)) { + LOGE("crossblit failed"); + + delete[] tmp; + + _mouse_texture->allocBuffer(0, 0); + + return; + } + + uint16 *s = (uint16 *)buf; + uint16 *d = (uint16 *)tmp; + for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w) + for (uint16 x = 0; x < w; ++x, d++) + if (*s++ != (keycolor & 0xffff)) + *d |= 1; + + _mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch); + + delete[] tmp; + } + + _mouse_hotspot = Common::Point(hotspotX, hotspotY); + _mouse_targetscale = cursorTargetScale; +} + +void OSystem_Android::setCursorPaletteInternal(const byte *colors, + uint start, uint num) { + const Graphics::PixelFormat &pf = + _mouse_texture_palette->getPalettePixelFormat(); + byte *p = _mouse_texture_palette->palette() + start * 2; + + for (uint i = 0; i < num; ++i, colors += 3, p += 2) + WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2])); + + p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; + WRITE_UINT16(p, READ_UINT16(p) & ~1); +} + +void OSystem_Android::setCursorPalette(const byte *colors, + uint start, uint num) { + ENTER("%p, %u, %u", colors, start, num); + + GLTHREADCHECK; + + if (!_mouse_texture->hasPalette()) { + LOGD("switching to paletted mouse cursor"); + + _mouse_texture = _mouse_texture_palette; + + delete _mouse_texture_rgb; + _mouse_texture_rgb = 0; + } + + setCursorPaletteInternal(colors, start, num); + _use_mouse_palette = true; +} + +void OSystem_Android::disableCursorPalette(bool disable) { + ENTER("%d", disable); + + // when disabling the cursor palette, and we're running a clut8 game, + // it expects the game palette to be used for the cursor + if (disable && _game_texture->hasPalette()) { + const byte *src = _game_texture->palette_const(); + byte *dst = _mouse_texture_palette->palette(); + + const Graphics::PixelFormat &pf_src = + _game_texture->getPalettePixelFormat(); + const Graphics::PixelFormat &pf_dst = + _mouse_texture_palette->getPalettePixelFormat(); + + uint8 r, g, b; + + for (uint i = 0; i < 256; ++i, src += 2, dst += 2) { + pf_src.colorToRGB(READ_UINT16(src), r, g, b); + WRITE_UINT16(dst, pf_dst.RGBToColor(r, g, b)); + } + + byte *p = _mouse_texture_palette->palette() + _mouse_keycolor * 2; + WRITE_UINT16(p, READ_UINT16(p) & ~1); + } + + _use_mouse_palette = !disable; +} + +#endif + diff --git a/backends/platform/android/jni.cpp b/backends/platform/android/jni.cpp new file mode 100644 index 0000000000..13aef11fa2 --- /dev/null +++ b/backends/platform/android/jni.cpp @@ -0,0 +1,624 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(__ANDROID__) + +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +// Disable printf override in common/forbidden.h to avoid +// clashes with log.h from the Android SDK. +// That header file uses +// __attribute__ ((format(printf, 3, 4))) +// which gets messed up by our override mechanism; this could +// be avoided by either changing the Android SDK to use the equally +// legal and valid +// __attribute__ ((format(printf, 3, 4))) +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the Android port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + +#include "base/main.h" +#include "base/version.h" +#include "common/config-manager.h" +#include "common/error.h" +#include "common/textconsole.h" +#include "engines/engine.h" + +#include "backends/platform/android/android.h" +#include "backends/platform/android/asset-archive.h" +#include "backends/platform/android/jni.h" + +__attribute__ ((visibility("default"))) +jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + return JNI::onLoad(vm); +} + +JavaVM *JNI::_vm = 0; +jobject JNI::_jobj = 0; +jobject JNI::_jobj_audio_track = 0; +jobject JNI::_jobj_egl = 0; +jobject JNI::_jobj_egl_display = 0; +jobject JNI::_jobj_egl_surface = 0; + +Common::Archive *JNI::_asset_archive = 0; +OSystem_Android *JNI::_system = 0; + +bool JNI::pause = false; +sem_t JNI::pause_sem = { 0 }; + +int JNI::surface_changeid = 0; +int JNI::egl_surface_width = 0; +int JNI::egl_surface_height = 0; +bool JNI::_ready_for_events = 0; + +jmethodID JNI::_MID_getDPI = 0; +jmethodID JNI::_MID_displayMessageOnOSD = 0; +jmethodID JNI::_MID_setWindowCaption = 0; +jmethodID JNI::_MID_showVirtualKeyboard = 0; +jmethodID JNI::_MID_getSysArchives = 0; +jmethodID JNI::_MID_getPluginDirectories = 0; +jmethodID JNI::_MID_initSurface = 0; +jmethodID JNI::_MID_deinitSurface = 0; + +jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0; + +jmethodID JNI::_MID_AudioTrack_flush = 0; +jmethodID JNI::_MID_AudioTrack_pause = 0; +jmethodID JNI::_MID_AudioTrack_play = 0; +jmethodID JNI::_MID_AudioTrack_stop = 0; +jmethodID JNI::_MID_AudioTrack_write = 0; + +const JNINativeMethod JNI::_natives[] = { + { "create", "(Landroid/content/res/AssetManager;" + "Ljavax/microedition/khronos/egl/EGL10;" + "Ljavax/microedition/khronos/egl/EGLDisplay;" + "Landroid/media/AudioTrack;II)V", + (void *)JNI::create }, + { "destroy", "()V", + (void *)JNI::destroy }, + { "setSurface", "(II)V", + (void *)JNI::setSurface }, + { "main", "([Ljava/lang/String;)I", + (void *)JNI::main }, + { "pushEvent", "(IIIIII)V", + (void *)JNI::pushEvent }, + { "enableZoning", "(Z)V", + (void *)JNI::enableZoning }, + { "setPause", "(Z)V", + (void *)JNI::setPause } +}; + +JNI::JNI() { +} + +JNI::~JNI() { +} + +jint JNI::onLoad(JavaVM *vm) { + _vm = vm; + + JNIEnv *env; + + if (_vm->GetEnv((void **)&env, JNI_VERSION_1_2)) + return JNI_ERR; + + jclass cls = env->FindClass("org/inodes/gus/scummvm/ScummVM"); + if (cls == 0) + return JNI_ERR; + + if (env->RegisterNatives(cls, _natives, ARRAYSIZE(_natives)) < 0) + return JNI_ERR; + + return JNI_VERSION_1_2; +} + +JNIEnv *JNI::getEnv() { + JNIEnv *env = 0; + + jint res = _vm->GetEnv((void **)&env, JNI_VERSION_1_2); + + if (res != JNI_OK) { + LOGE("GetEnv() failed: %d", res); + abort(); + } + + return env; +} + +void JNI::attachThread() { + JNIEnv *env = 0; + + jint res = _vm->AttachCurrentThread(&env, 0); + + if (res != JNI_OK) { + LOGE("AttachCurrentThread() failed: %d", res); + abort(); + } +} + +void JNI::detachThread() { + jint res = _vm->DetachCurrentThread(); + + if (res != JNI_OK) { + LOGE("DetachCurrentThread() failed: %d", res); + abort(); + } +} + +void JNI::setReadyForEvents(bool ready) { + _ready_for_events = ready; +} + +void JNI::throwByName(JNIEnv *env, const char *name, const char *msg) { + jclass cls = env->FindClass(name); + + // if cls is 0, an exception has already been thrown + if (cls != 0) + env->ThrowNew(cls, msg); + + env->DeleteLocalRef(cls); +} + +void JNI::throwRuntimeException(JNIEnv *env, const char *msg) { + throwByName(env, "java/lang/RuntimeException", msg); +} + +// calls to the dark side + +void JNI::getDPI(float *values) { + values[0] = 0.0; + values[1] = 0.0; + + JNIEnv *env = JNI::getEnv(); + + jfloatArray array = env->NewFloatArray(2); + + env->CallVoidMethod(_jobj, _MID_getDPI, array); + + if (env->ExceptionCheck()) { + LOGE("Failed to get DPIs"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } else { + jfloat *res = env->GetFloatArrayElements(array, 0); + + if (res) { + values[0] = res[0]; + values[1] = res[1]; + + env->ReleaseFloatArrayElements(array, res, 0); + } + } + + env->DeleteLocalRef(array); +} + +void JNI::displayMessageOnOSD(const char *msg) { + JNIEnv *env = JNI::getEnv(); + jstring java_msg = env->NewStringUTF(msg); + + env->CallVoidMethod(_jobj, _MID_displayMessageOnOSD, java_msg); + + if (env->ExceptionCheck()) { + LOGE("Failed to display OSD message"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } + + env->DeleteLocalRef(java_msg); +} + +void JNI::setWindowCaption(const char *caption) { + JNIEnv *env = JNI::getEnv(); + jstring java_caption = env->NewStringUTF(caption); + + env->CallVoidMethod(_jobj, _MID_setWindowCaption, java_caption); + + if (env->ExceptionCheck()) { + LOGE("Failed to set window caption"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } + + env->DeleteLocalRef(java_caption); +} + +void JNI::showVirtualKeyboard(bool enable) { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj, _MID_showVirtualKeyboard, enable); + + if (env->ExceptionCheck()) { + LOGE("Error trying to show virtual keyboard"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + JNIEnv *env = JNI::getEnv(); + + s.add("ASSET", _asset_archive, priority, false); + + jobjectArray array = + (jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives); + + if (env->ExceptionCheck()) { + LOGE("Error finding system archive path"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return; + } + + jsize size = env->GetArrayLength(array); + for (jsize i = 0; i < size; ++i) { + jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); + const char *path = env->GetStringUTFChars(path_obj, 0); + + if (path != 0) { + s.addDirectory(path, path, priority); + env->ReleaseStringUTFChars(path_obj, path); + } + + env->DeleteLocalRef(path_obj); + } +} + +void JNI::getPluginDirectories(Common::FSList &dirs) { + JNIEnv *env = JNI::getEnv(); + + jobjectArray array = + (jobjectArray)env->CallObjectMethod(_jobj, _MID_getPluginDirectories); + + if (env->ExceptionCheck()) { + LOGE("Error finding plugin directories"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return; + } + + jsize size = env->GetArrayLength(array); + for (jsize i = 0; i < size; ++i) { + jstring path_obj = (jstring)env->GetObjectArrayElement(array, i); + + if (path_obj == 0) + continue; + + const char *path = env->GetStringUTFChars(path_obj, 0); + + if (path == 0) { + LOGE("Error getting string characters from plugin directory"); + + env->ExceptionClear(); + env->DeleteLocalRef(path_obj); + + continue; + } + + dirs.push_back(Common::FSNode(path)); + + env->ReleaseStringUTFChars(path_obj, path); + env->DeleteLocalRef(path_obj); + } +} + +bool JNI::initSurface() { + JNIEnv *env = JNI::getEnv(); + + jobject obj = env->CallObjectMethod(_jobj, _MID_initSurface); + + if (!obj || env->ExceptionCheck()) { + LOGE("initSurface failed"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + + return false; + } + + _jobj_egl_surface = env->NewGlobalRef(obj); + + return true; +} + +void JNI::deinitSurface() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj, _MID_deinitSurface); + + if (env->ExceptionCheck()) { + LOGE("deinitSurface failed"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } + + env->DeleteGlobalRef(_jobj_egl_surface); + _jobj_egl_surface = 0; +} + +void JNI::setAudioPause() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_flush); + + if (env->ExceptionCheck()) { + LOGE("Error flushing AudioTrack"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } + + env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_pause); + + if (env->ExceptionCheck()) { + LOGE("Error setting AudioTrack: pause"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void JNI::setAudioPlay() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_play); + + if (env->ExceptionCheck()) { + LOGE("Error setting AudioTrack: play"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void JNI::setAudioStop() { + JNIEnv *env = JNI::getEnv(); + + env->CallVoidMethod(_jobj_audio_track, _MID_AudioTrack_stop); + + if (env->ExceptionCheck()) { + LOGE("Error setting AudioTrack: stop"); + + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +// natives for the dark side + +void JNI::create(JNIEnv *env, jobject self, jobject asset_manager, + jobject egl, jobject egl_display, + jobject at, jint audio_sample_rate, jint audio_buffer_size) { + LOGI(gScummVMFullVersion); + + assert(!_system); + + pause = false; + // initial value of zero! + sem_init(&pause_sem, 0, 0); + + _asset_archive = new AndroidAssetArchive(asset_manager); + assert(_asset_archive); + + _system = new OSystem_Android(audio_sample_rate, audio_buffer_size); + assert(_system); + + // weak global ref to allow class to be unloaded + // ... except dalvik implements NewWeakGlobalRef only on froyo + //_jobj = env->NewWeakGlobalRef(self); + + _jobj = env->NewGlobalRef(self); + + jclass cls = env->GetObjectClass(_jobj); + +#define FIND_METHOD(prefix, name, signature) do { \ + _MID_ ## prefix ## name = env->GetMethodID(cls, #name, signature); \ + if (_MID_ ## prefix ## name == 0) \ + return; \ + } while (0) + + FIND_METHOD(, setWindowCaption, "(Ljava/lang/String;)V"); + FIND_METHOD(, getDPI, "([F)V"); + FIND_METHOD(, displayMessageOnOSD, "(Ljava/lang/String;)V"); + FIND_METHOD(, showVirtualKeyboard, "(Z)V"); + FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;"); + FIND_METHOD(, getPluginDirectories, "()[Ljava/lang/String;"); + FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;"); + FIND_METHOD(, deinitSurface, "()V"); + + _jobj_egl = env->NewGlobalRef(egl); + _jobj_egl_display = env->NewGlobalRef(egl_display); + + cls = env->GetObjectClass(_jobj_egl); + + FIND_METHOD(EGL10_, eglSwapBuffers, + "(Ljavax/microedition/khronos/egl/EGLDisplay;" + "Ljavax/microedition/khronos/egl/EGLSurface;)Z"); + + _jobj_audio_track = env->NewGlobalRef(at); + + cls = env->GetObjectClass(_jobj_audio_track); + + FIND_METHOD(AudioTrack_, flush, "()V"); + FIND_METHOD(AudioTrack_, pause, "()V"); + FIND_METHOD(AudioTrack_, play, "()V"); + FIND_METHOD(AudioTrack_, stop, "()V"); + FIND_METHOD(AudioTrack_, write, "([BII)I"); + +#undef FIND_METHOD + + g_system = _system; +} + +void JNI::destroy(JNIEnv *env, jobject self) { + delete _asset_archive; + _asset_archive = 0; + + delete _system; + g_system = 0; + _system = 0; + + sem_destroy(&pause_sem); + + // see above + //JNI::getEnv()->DeleteWeakGlobalRef(_jobj); + + JNI::getEnv()->DeleteGlobalRef(_jobj_egl_display); + JNI::getEnv()->DeleteGlobalRef(_jobj_egl); + JNI::getEnv()->DeleteGlobalRef(_jobj_audio_track); + JNI::getEnv()->DeleteGlobalRef(_jobj); +} + +void JNI::setSurface(JNIEnv *env, jobject self, jint width, jint height) { + egl_surface_width = width; + egl_surface_height = height; + surface_changeid++; +} + +jint JNI::main(JNIEnv *env, jobject self, jobjectArray args) { + assert(_system); + + const int MAX_NARGS = 32; + int res = -1; + + int argc = env->GetArrayLength(args); + if (argc > MAX_NARGS) { + throwByName(env, "java/lang/IllegalArgumentException", + "too many arguments"); + return 0; + } + + char *argv[MAX_NARGS]; + + // note use in cleanup loop below + int nargs; + + for (nargs = 0; nargs < argc; ++nargs) { + jstring arg = (jstring)env->GetObjectArrayElement(args, nargs); + + if (arg == 0) { + argv[nargs] = 0; + } else { + const char *cstr = env->GetStringUTFChars(arg, 0); + + argv[nargs] = const_cast<char *>(cstr); + + // exception already thrown? + if (cstr == 0) + goto cleanup; + } + + env->DeleteLocalRef(arg); + } + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new AndroidPluginProvider()); +#endif + + LOGI("Entering scummvm_main with %d args", argc); + + res = scummvm_main(argc, argv); + + LOGI("scummvm_main exited with code %d", res); + + _system->quit(); + +cleanup: + nargs--; + + for (int i = 0; i < nargs; ++i) { + if (argv[i] == 0) + continue; + + jstring arg = (jstring)env->GetObjectArrayElement(args, nargs); + + // Exception already thrown? + if (arg == 0) + return res; + + env->ReleaseStringUTFChars(arg, argv[i]); + env->DeleteLocalRef(arg); + } + + return res; +} + +void JNI::pushEvent(JNIEnv *env, jobject self, int type, int arg1, int arg2, + int arg3, int arg4, int arg5) { + // drop events until we're ready and after we quit + if (!_ready_for_events) { + LOGW("dropping event"); + return; + } + + assert(_system); + + _system->pushEvent(type, arg1, arg2, arg3, arg4, arg5); +} + +void JNI::enableZoning(JNIEnv *env, jobject self, jboolean enable) { + assert(_system); + + _system->enableZoning(enable); +} + +void JNI::setPause(JNIEnv *env, jobject self, jboolean value) { + if (!_system) + return; + + if (g_engine) { + LOGD("pauseEngine: %d", value); + + g_engine->pauseEngine(value); + + if (value && + g_engine->hasFeature(Engine::kSupportsSavingDuringRuntime) && + g_engine->canSaveGameStateCurrently()) + g_engine->saveGameState(0, "Android parachute"); + } + + pause = value; + + if (!pause) { + // wake up all threads + for (uint i = 0; i < 3; ++i) + sem_post(&pause_sem); + } +} + +#endif + diff --git a/backends/platform/android/jni.h b/backends/platform/android/jni.h new file mode 100644 index 0000000000..d029f1a2a8 --- /dev/null +++ b/backends/platform/android/jni.h @@ -0,0 +1,151 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef _ANDROID_JNI_H_ +#define _ANDROID_JNI_H_ + +#if defined(__ANDROID__) + +#include <jni.h> +#include <semaphore.h> + +#include "common/fs.h" +#include "common/archive.h" + +class OSystem_Android; + +class JNI { +private: + JNI(); + virtual ~JNI(); + +public: + static bool pause; + static sem_t pause_sem; + + static int surface_changeid; + static int egl_surface_width; + static int egl_surface_height; + + static jint onLoad(JavaVM *vm); + + static JNIEnv *getEnv(); + + static void attachThread(); + static void detachThread(); + + static void setReadyForEvents(bool ready); + + static void getPluginDirectories(Common::FSList &dirs); + static void setWindowCaption(const char *caption); + static void getDPI(float *values); + static void displayMessageOnOSD(const char *msg); + static void showVirtualKeyboard(bool enable); + static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); + + static inline bool haveSurface(); + static inline bool swapBuffers(); + static bool initSurface(); + static void deinitSurface(); + + static void setAudioPause(); + static void setAudioPlay(); + static void setAudioStop(); + + static inline int writeAudio(JNIEnv *env, jbyteArray &data, int offset, + int size); + +private: + static JavaVM *_vm; + // back pointer to (java) peer instance + static jobject _jobj; + static jobject _jobj_audio_track; + static jobject _jobj_egl; + static jobject _jobj_egl_display; + static jobject _jobj_egl_surface; + + static Common::Archive *_asset_archive; + static OSystem_Android *_system; + + static bool _ready_for_events; + + static jmethodID _MID_getDPI; + static jmethodID _MID_displayMessageOnOSD; + static jmethodID _MID_setWindowCaption; + static jmethodID _MID_showVirtualKeyboard; + static jmethodID _MID_getSysArchives; + static jmethodID _MID_getPluginDirectories; + static jmethodID _MID_initSurface; + static jmethodID _MID_deinitSurface; + + static jmethodID _MID_EGL10_eglSwapBuffers; + + static jmethodID _MID_AudioTrack_flush; + static jmethodID _MID_AudioTrack_pause; + static jmethodID _MID_AudioTrack_play; + static jmethodID _MID_AudioTrack_stop; + static jmethodID _MID_AudioTrack_write; + + static const JNINativeMethod _natives[]; + + static void throwByName(JNIEnv *env, const char *name, const char *msg); + static void throwRuntimeException(JNIEnv *env, const char *msg); + + // natives for the dark side + static void create(JNIEnv *env, jobject self, jobject asset_manager, + jobject egl, jobject egl_display, + jobject at, jint audio_sample_rate, + jint audio_buffer_size); + static void destroy(JNIEnv *env, jobject self); + + static void setSurface(JNIEnv *env, jobject self, jint width, jint height); + static jint main(JNIEnv *env, jobject self, jobjectArray args); + + static void pushEvent(JNIEnv *env, jobject self, int type, int arg1, + int arg2, int arg3, int arg4, int arg5); + static void enableZoning(JNIEnv *env, jobject self, jboolean enable); + + static void setPause(JNIEnv *env, jobject self, jboolean value); +}; + +inline bool JNI::haveSurface() { + return _jobj_egl_surface != 0; +} + +inline bool JNI::swapBuffers() { + JNIEnv *env = JNI::getEnv(); + + return env->CallBooleanMethod(_jobj_egl, _MID_EGL10_eglSwapBuffers, + _jobj_egl_display, _jobj_egl_surface); +} + +inline int JNI::writeAudio(JNIEnv *env, jbyteArray &data, int offset, int size) { + return env->CallIntMethod(_jobj_audio_track, _MID_AudioTrack_write, data, + offset, size); +} + +#endif +#endif + diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk index 8b120b21ff..2fe4b40585 100644 --- a/backends/platform/android/module.mk +++ b/backends/platform/android/module.mk @@ -1,9 +1,12 @@ MODULE := backends/platform/android MODULE_OBJS := \ - android.o \ + jni.o \ + texture.o \ asset-archive.o \ - video.o + android.o \ + gfx.o \ + events.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java index 5b71d4a3a5..cede7eedd4 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java +++ b/backends/platform/android/org/inodes/gus/scummvm/EditableSurfaceView.java @@ -19,13 +19,13 @@ public class EditableSurfaceView extends SurfaceView { } public EditableSurfaceView(Context context, AttributeSet attrs, - int defStyle) { + int defStyle) { super(context, attrs, defStyle); } @Override public boolean onCheckIsTextEditor() { - return true; + return false; } private class MyInputConnection extends BaseInputConnection { @@ -40,7 +40,9 @@ public class EditableSurfaceView extends SurfaceView { getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindowToken(), 0); } - return super.performEditorAction(actionCode); // Sends enter key + + // Sends enter key + return super.performEditorAction(actionCode); } } @@ -49,11 +51,12 @@ public class EditableSurfaceView extends SurfaceView { outAttrs.initialCapsMode = 0; outAttrs.initialSelEnd = outAttrs.initialSelStart = -1; outAttrs.inputType = (InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_NORMAL | - InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); + InputType.TYPE_TEXT_VARIATION_NORMAL | + InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); outAttrs.imeOptions = (EditorInfo.IME_ACTION_DONE | - EditorInfo.IME_FLAG_NO_EXTRACT_UI); + EditorInfo.IME_FLAG_NO_EXTRACT_UI); return new MyInputConnection(); } } + diff --git a/backends/platform/android/org/inodes/gus/scummvm/Event.java b/backends/platform/android/org/inodes/gus/scummvm/Event.java deleted file mode 100644 index f9c7aba93b..0000000000 --- a/backends/platform/android/org/inodes/gus/scummvm/Event.java +++ /dev/null @@ -1,330 +0,0 @@ -package org.inodes.gus.scummvm; - -import android.view.KeyEvent; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class Event { - // Common::EventType enum. - // Must be kept in sync with common/events.h - public final static int EVENT_INVALID = 0; - public final static int EVENT_KEYDOWN = 1; - public final static int EVENT_KEYUP = 2; - public final static int EVENT_MOUSEMOVE = 3; - public final static int EVENT_LBUTTONDOWN = 4; - public final static int EVENT_LBUTTONUP = 5; - public final static int EVENT_RBUTTONDOWN = 6; - public final static int EVENT_RBUTTONUP = 7; - public final static int EVENT_WHEELUP = 8; - public final static int EVENT_WHEELDOWN = 9; - public final static int EVENT_QUIT = 10; - public final static int EVENT_SCREEN_CHANGED = 11; - public final static int EVENT_PREDICTIVE_DIALOG = 12; - public final static int EVENT_MBUTTONDOWN = 13; - public final static int EVENT_MBUTTONUP = 14; - public final static int EVENT_MAINMENU = 15; - public final static int EVENT_RTL = 16; - - // common/keyboard.h - public final static int ASCII_F1 = 315; - public final static int ASCII_F2 = 316; - public final static int ASCII_F3 = 317; - public final static int ASCII_F4 = 318; - public final static int ASCII_F5 = 319; - public final static int ASCII_F6 = 320; - public final static int ASCII_F7 = 321; - public final static int ASCII_F8 = 322; - public final static int ASCII_F9 = 323; - public final static int ASCII_F10 = 324; - public final static int ASCII_F11 = 325; - public final static int ASCII_F12 = 326; - public final static int KBD_CTRL = 1 << 0; - public final static int KBD_ALT = 1 << 1; - public final static int KBD_SHIFT = 1 << 2; - - public final static int KEYCODE_INVALID = 0; - public final static int KEYCODE_BACKSPACE = 8; - public final static int KEYCODE_TAB = 9; - public final static int KEYCODE_CLEAR = 12; - public final static int KEYCODE_RETURN = 13; - public final static int KEYCODE_PAUSE = 19; - public final static int KEYCODE_ESCAPE = 27; - public final static int KEYCODE_SPACE = 32; - public final static int KEYCODE_EXCLAIM = 33; - public final static int KEYCODE_QUOTEDBL = 34; - public final static int KEYCODE_HASH = 35; - public final static int KEYCODE_DOLLAR = 36; - public final static int KEYCODE_AMPERSAND = 38; - public final static int KEYCODE_QUOTE = 39; - public final static int KEYCODE_LEFTPAREN = 40; - public final static int KEYCODE_RIGHTPAREN = 41; - public final static int KEYCODE_ASTERISK = 42; - public final static int KEYCODE_PLUS = 43; - public final static int KEYCODE_COMMA = 44; - public final static int KEYCODE_MINUS = 45; - public final static int KEYCODE_PERIOD = 46; - public final static int KEYCODE_SLASH = 47; - public final static int KEYCODE_0 = 48; - public final static int KEYCODE_1 = 49; - public final static int KEYCODE_2 = 50; - public final static int KEYCODE_3 = 51; - public final static int KEYCODE_4 = 52; - public final static int KEYCODE_5 = 53; - public final static int KEYCODE_6 = 54; - public final static int KEYCODE_7 = 55; - public final static int KEYCODE_8 = 56; - public final static int KEYCODE_9 = 57; - public final static int KEYCODE_COLON = 58; - public final static int KEYCODE_SEMICOLON = 59; - public final static int KEYCODE_LESS = 60; - public final static int KEYCODE_EQUALS = 61; - public final static int KEYCODE_GREATER = 62; - public final static int KEYCODE_QUESTION = 63; - public final static int KEYCODE_AT = 64; - public final static int KEYCODE_LEFTBRACKET = 91; - public final static int KEYCODE_BACKSLASH = 92; - public final static int KEYCODE_RIGHTBRACKET = 93; - public final static int KEYCODE_CARET = 94; - public final static int KEYCODE_UNDERSCORE = 95; - public final static int KEYCODE_BACKQUOTE = 96; - public final static int KEYCODE_a = 97; - public final static int KEYCODE_b = 98; - public final static int KEYCODE_c = 99; - public final static int KEYCODE_d = 100; - public final static int KEYCODE_e = 101; - public final static int KEYCODE_f = 102; - public final static int KEYCODE_g = 103; - public final static int KEYCODE_h = 104; - public final static int KEYCODE_i = 105; - public final static int KEYCODE_j = 106; - public final static int KEYCODE_k = 107; - public final static int KEYCODE_l = 108; - public final static int KEYCODE_m = 109; - public final static int KEYCODE_n = 110; - public final static int KEYCODE_o = 111; - public final static int KEYCODE_p = 112; - public final static int KEYCODE_q = 113; - public final static int KEYCODE_r = 114; - public final static int KEYCODE_s = 115; - public final static int KEYCODE_t = 116; - public final static int KEYCODE_u = 117; - public final static int KEYCODE_v = 118; - public final static int KEYCODE_w = 119; - public final static int KEYCODE_x = 120; - public final static int KEYCODE_y = 121; - public final static int KEYCODE_z = 122; - public final static int KEYCODE_DELETE = 127; - // Numeric keypad - public final static int KEYCODE_KP0 = 256; - public final static int KEYCODE_KP1 = 257; - public final static int KEYCODE_KP2 = 258; - public final static int KEYCODE_KP3 = 259; - public final static int KEYCODE_KP4 = 260; - public final static int KEYCODE_KP5 = 261; - public final static int KEYCODE_KP6 = 262; - public final static int KEYCODE_KP7 = 263; - public final static int KEYCODE_KP8 = 264; - public final static int KEYCODE_KP9 = 265; - public final static int KEYCODE_KP_PERIOD = 266; - public final static int KEYCODE_KP_DIVIDE = 267; - public final static int KEYCODE_KP_MULTIPLY = 268; - public final static int KEYCODE_KP_MINUS = 269; - public final static int KEYCODE_KP_PLUS = 270; - public final static int KEYCODE_KP_ENTER = 271; - public final static int KEYCODE_KP_EQUALS = 272; - // Arrows + Home/End pad - public final static int KEYCODE_UP = 273; - public final static int KEYCODE_DOWN = 274; - public final static int KEYCODE_RIGHT = 275; - public final static int KEYCODE_LEFT = 276; - public final static int KEYCODE_INSERT = 277; - public final static int KEYCODE_HOME = 278; - public final static int KEYCODE_END = 279; - public final static int KEYCODE_PAGEUP = 280; - public final static int KEYCODE_PAGEDOWN = 281; - // Function keys - public final static int KEYCODE_F1 = 282; - public final static int KEYCODE_F2 = 283; - public final static int KEYCODE_F3 = 284; - public final static int KEYCODE_F4 = 285; - public final static int KEYCODE_F5 = 286; - public final static int KEYCODE_F6 = 287; - public final static int KEYCODE_F7 = 288; - public final static int KEYCODE_F8 = 289; - public final static int KEYCODE_F9 = 290; - public final static int KEYCODE_F10 = 291; - public final static int KEYCODE_F11 = 292; - public final static int KEYCODE_F12 = 293; - public final static int KEYCODE_F13 = 294; - public final static int KEYCODE_F14 = 295; - public final static int KEYCODE_F15 = 296; - // Key state modifier keys - public final static int KEYCODE_NUMLOCK = 300; - public final static int KEYCODE_CAPSLOCK = 301; - public final static int KEYCODE_SCROLLOCK = 302; - public final static int KEYCODE_RSHIFT = 303; - public final static int KEYCODE_LSHIFT = 304; - public final static int KEYCODE_RCTRL = 305; - public final static int KEYCODE_LCTRL = 306; - public final static int KEYCODE_RALT = 307; - public final static int KEYCODE_LALT = 308; - public final static int KEYCODE_RMETA = 309; - public final static int KEYCODE_LMETA = 310; - public final static int KEYCODE_LSUPER = 311; // Left "Windows" key - public final static int KEYCODE_RSUPER = 312; // Right "Windows" key - public final static int KEYCODE_MODE = 313; // "Alt Gr" key - public final static int KEYCODE_COMPOSE = 314; // Multi-key compose key - // Miscellaneous function keys - public final static int KEYCODE_HELP = 315; - public final static int KEYCODE_PRINT = 316; - public final static int KEYCODE_SYSREQ = 317; - public final static int KEYCODE_BREAK = 318; - public final static int KEYCODE_MENU = 319; - public final static int KEYCODE_POWER = 320; // Power Macintosh power key - public final static int KEYCODE_EURO = 321; // Some european keyboards - public final static int KEYCODE_UNDO = 322; // Atari keyboard has Undo - - // Android KeyEvent keycode -> ScummVM keycode - public final static Map<Integer, Integer> androidKeyMap; - static { - Map<Integer, Integer> map = new HashMap<Integer, Integer>(); - - map.put(KeyEvent.KEYCODE_DEL, KEYCODE_BACKSPACE); - map.put(KeyEvent.KEYCODE_TAB, KEYCODE_TAB); - map.put(KeyEvent.KEYCODE_CLEAR, KEYCODE_CLEAR); - map.put(KeyEvent.KEYCODE_ENTER, KEYCODE_RETURN); - //map.put(??, KEYCODE_PAUSE); - map.put(KeyEvent.KEYCODE_BACK, KEYCODE_ESCAPE); - map.put(KeyEvent.KEYCODE_SPACE, KEYCODE_SPACE); - //map.put(??, KEYCODE_EXCLAIM); - //map.put(??, KEYCODE_QUOTEDBL); - map.put(KeyEvent.KEYCODE_POUND, KEYCODE_HASH); - //map.put(??, KEYCODE_DOLLAR); - //map.put(??, KEYCODE_AMPERSAND); - map.put(KeyEvent.KEYCODE_APOSTROPHE, KEYCODE_QUOTE); - //map.put(??, KEYCODE_LEFTPAREN); - //map.put(??, KEYCODE_RIGHTPAREN); - //map.put(??, KEYCODE_ASTERISK); - map.put(KeyEvent.KEYCODE_PLUS, KEYCODE_PLUS); - map.put(KeyEvent.KEYCODE_COMMA, KEYCODE_COMMA); - map.put(KeyEvent.KEYCODE_MINUS, KEYCODE_MINUS); - map.put(KeyEvent.KEYCODE_PERIOD, KEYCODE_PERIOD); - map.put(KeyEvent.KEYCODE_SLASH, KEYCODE_SLASH); - map.put(KeyEvent.KEYCODE_0, KEYCODE_0); - map.put(KeyEvent.KEYCODE_1, KEYCODE_1); - map.put(KeyEvent.KEYCODE_2, KEYCODE_2); - map.put(KeyEvent.KEYCODE_3, KEYCODE_3); - map.put(KeyEvent.KEYCODE_4, KEYCODE_4); - map.put(KeyEvent.KEYCODE_5, KEYCODE_5); - map.put(KeyEvent.KEYCODE_6, KEYCODE_6); - map.put(KeyEvent.KEYCODE_7, KEYCODE_7); - map.put(KeyEvent.KEYCODE_8, KEYCODE_8); - map.put(KeyEvent.KEYCODE_9, KEYCODE_9); - //map.put(??, KEYCODE_COLON); - map.put(KeyEvent.KEYCODE_SEMICOLON, KEYCODE_SEMICOLON); - //map.put(??, KEYCODE_LESS); - map.put(KeyEvent.KEYCODE_EQUALS, KEYCODE_EQUALS); - //map.put(??, KEYCODE_GREATER); - //map.put(??, KEYCODE_QUESTION); - map.put(KeyEvent.KEYCODE_AT, KEYCODE_AT); - map.put(KeyEvent.KEYCODE_LEFT_BRACKET, KEYCODE_LEFTBRACKET); - map.put(KeyEvent.KEYCODE_BACKSLASH, KEYCODE_BACKSLASH); - map.put(KeyEvent.KEYCODE_RIGHT_BRACKET, KEYCODE_RIGHTBRACKET); - //map.put(??, KEYCODE_CARET); - //map.put(??, KEYCODE_UNDERSCORE); - //map.put(??, KEYCODE_BACKQUOTE); - map.put(KeyEvent.KEYCODE_A, KEYCODE_a); - map.put(KeyEvent.KEYCODE_B, KEYCODE_b); - map.put(KeyEvent.KEYCODE_C, KEYCODE_c); - map.put(KeyEvent.KEYCODE_D, KEYCODE_d); - map.put(KeyEvent.KEYCODE_E, KEYCODE_e); - map.put(KeyEvent.KEYCODE_F, KEYCODE_f); - map.put(KeyEvent.KEYCODE_G, KEYCODE_g); - map.put(KeyEvent.KEYCODE_H, KEYCODE_h); - map.put(KeyEvent.KEYCODE_I, KEYCODE_i); - map.put(KeyEvent.KEYCODE_J, KEYCODE_j); - map.put(KeyEvent.KEYCODE_K, KEYCODE_k); - map.put(KeyEvent.KEYCODE_L, KEYCODE_l); - map.put(KeyEvent.KEYCODE_M, KEYCODE_m); - map.put(KeyEvent.KEYCODE_N, KEYCODE_n); - map.put(KeyEvent.KEYCODE_O, KEYCODE_o); - map.put(KeyEvent.KEYCODE_P, KEYCODE_p); - map.put(KeyEvent.KEYCODE_Q, KEYCODE_q); - map.put(KeyEvent.KEYCODE_R, KEYCODE_r); - map.put(KeyEvent.KEYCODE_S, KEYCODE_s); - map.put(KeyEvent.KEYCODE_T, KEYCODE_t); - map.put(KeyEvent.KEYCODE_U, KEYCODE_u); - map.put(KeyEvent.KEYCODE_V, KEYCODE_v); - map.put(KeyEvent.KEYCODE_W, KEYCODE_w); - map.put(KeyEvent.KEYCODE_X, KEYCODE_x); - map.put(KeyEvent.KEYCODE_Y, KEYCODE_y); - map.put(KeyEvent.KEYCODE_Z, KEYCODE_z); - //map.put(KeyEvent.KEYCODE_DEL, KEYCODE_DELETE); use BACKSPACE instead - //map.put(??, KEYCODE_KP_*); - map.put(KeyEvent.KEYCODE_DPAD_UP, KEYCODE_UP); - map.put(KeyEvent.KEYCODE_DPAD_DOWN, KEYCODE_DOWN); - map.put(KeyEvent.KEYCODE_DPAD_RIGHT, KEYCODE_RIGHT); - map.put(KeyEvent.KEYCODE_DPAD_LEFT, KEYCODE_LEFT); - //map.put(??, KEYCODE_INSERT); - //map.put(??, KEYCODE_HOME); - //map.put(??, KEYCODE_END); - //map.put(??, KEYCODE_PAGEUP); - //map.put(??, KEYCODE_PAGEDOWN); - //map.put(??, KEYCODE_F{1-15}); - map.put(KeyEvent.KEYCODE_NUM, KEYCODE_NUMLOCK); - //map.put(??, KEYCODE_CAPSLOCK); - //map.put(??, KEYCODE_SCROLLLOCK); - map.put(KeyEvent.KEYCODE_SHIFT_RIGHT, KEYCODE_RSHIFT); - map.put(KeyEvent.KEYCODE_SHIFT_LEFT, KEYCODE_LSHIFT); - //map.put(??, KEYCODE_RCTRL); - //map.put(??, KEYCODE_LCTRL); - map.put(KeyEvent.KEYCODE_ALT_RIGHT, KEYCODE_RALT); - map.put(KeyEvent.KEYCODE_ALT_LEFT, KEYCODE_LALT); - // ?? META, SUPER - // ?? MODE, COMPOSE - // ?? HELP, PRINT, SYSREQ, BREAK, EURO, UNDO - map.put(KeyEvent.KEYCODE_MENU, KEYCODE_MENU); - map.put(KeyEvent.KEYCODE_POWER, KEYCODE_POWER); - - androidKeyMap = Collections.unmodifiableMap(map); - } - - public int type; - public boolean synthetic; - public int kbd_keycode; - public int kbd_ascii; - public int kbd_flags; - public int mouse_x; - public int mouse_y; - public boolean mouse_relative; // Used for trackball events - - public Event() { - type = EVENT_INVALID; - synthetic = false; - } - - public Event(int type) { - this.type = type; - synthetic = false; - } - - public static Event KeyboardEvent(int type, int keycode, int ascii, - int flags) { - Event e = new Event(); - e.type = type; - e.kbd_keycode = keycode; - e.kbd_ascii = ascii; - e.kbd_flags = flags; - return e; - } - - public static Event MouseEvent(int type, int x, int y) { - Event e = new Event(); - e.type = type; - e.mouse_x = x; - e.mouse_y = y; - return e; - } -} diff --git a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java index c94ab0a3ff..3c91d9f5dc 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java +++ b/backends/platform/android/org/inodes/gus/scummvm/PluginProvider.java @@ -28,7 +28,7 @@ public class PluginProvider extends BroadcastReceiver { try { info = context.getPackageManager() .getReceiverInfo(new ComponentName(context, this.getClass()), - PackageManager.GET_META_DATA); + PackageManager.GET_META_DATA); } catch (PackageManager.NameNotFoundException e) { Log.e(LOG_TAG, "Error finding my own info?", e); return; @@ -38,17 +38,17 @@ public class PluginProvider extends BroadcastReceiver { if (mylib != null) { ArrayList<String> all_libs = extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS); - all_libs.add(new Uri.Builder() - .scheme("plugin") - .authority(context.getPackageName()) - .path(mylib) - .toString()); + .scheme("plugin") + .authority(context.getPackageName()) + .path(mylib) + .toString()); extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS, - all_libs); + all_libs); } setResultExtras(extras); } } + diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java index 0e905f43a5..c4de6d62f8 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java @@ -1,446 +1,435 @@ package org.inodes.gus.scummvm; -import android.content.Context; +import android.util.Log; import android.content.res.AssetManager; +import android.view.SurfaceHolder; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Process; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; -import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import java.io.File; -import java.util.concurrent.Semaphore; -import java.util.Map; import java.util.LinkedHashMap; +public abstract class ScummVM implements SurfaceHolder.Callback, Runnable { + final protected static String LOG_TAG = "ScummVM"; + final private AssetManager _asset_manager; + final private Object _sem_surface; + + private EGL10 _egl; + private EGLDisplay _egl_display = EGL10.EGL_NO_DISPLAY; + private EGLConfig _egl_config; + private EGLContext _egl_context = EGL10.EGL_NO_CONTEXT; + private EGLSurface _egl_surface = EGL10.EGL_NO_SURFACE; + + private SurfaceHolder _surface_holder; + private AudioTrack _audio_track; + private int _sample_rate = 0; + private int _buffer_size = 0; + + private String[] _args; + + final private native void create(AssetManager asset_manager, + EGL10 egl, EGLDisplay egl_display, + AudioTrack audio_track, + int sample_rate, int buffer_size); + final private native void destroy(); + final private native void setSurface(int width, int height); + final private native int main(String[] args); + + // pause the engine and all native threads + final public native void setPause(boolean pause); + final public native void enableZoning(boolean enable); + // Feed an event to ScummVM. Safe to call from other threads. + final public native void pushEvent(int type, int arg1, int arg2, int arg3, + int arg4, int arg5); -// At least in Android 2.1, eglCreateWindowSurface() requires an -// EGLNativeWindowSurface object, which is hidden deep in the bowels -// of libui. Until EGL is properly exposed, it's probably safer to -// use the Java versions of most EGL functions :( - -public class ScummVM implements SurfaceHolder.Callback { - protected final static String LOG_TAG = "ScummVM"; + // Callbacks from C++ peer instance + abstract protected void getDPI(float[] values); + abstract protected void displayMessageOnOSD(String msg); + abstract protected void setWindowCaption(String caption); + abstract protected String[] getPluginDirectories(); + abstract protected void showVirtualKeyboard(boolean enable); + abstract protected String[] getSysArchives(); - private final int AUDIO_FRAME_SIZE = 2 * 2; // bytes. 16bit audio * stereo - public static class AudioSetupException extends Exception {} + public ScummVM(AssetManager asset_manager, SurfaceHolder holder) { + _asset_manager = asset_manager; + _sem_surface = new Object(); - private long nativeScummVM; // native code hangs itself here - boolean scummVMRunning = false; + holder.addCallback(this); + } - private native void create(AssetManager am); + // SurfaceHolder callback + final public void surfaceCreated(SurfaceHolder holder) { + Log.d(LOG_TAG, "surfaceCreated"); - public ScummVM(Context context) { - create(context.getAssets()); // Init C++ code, set nativeScummVM + // no need to do anything, surfaceChanged() will be called in any case } - private native void nativeDestroy(); + // SurfaceHolder callback + final public void surfaceChanged(SurfaceHolder holder, int format, + int width, int height) { + // the orientation may reset on standby mode and the theme manager + // could assert when using a portrait resolution. so lets not do that. + if (height > width) { + Log.d(LOG_TAG, String.format("Ignoring surfaceChanged: %dx%d (%d)", + width, height, format)); + return; + } + + Log.d(LOG_TAG, String.format("surfaceChanged: %dx%d (%d)", + width, height, format)); - public synchronized void destroy() { - if (nativeScummVM != 0) { - nativeDestroy(); - nativeScummVM = 0; + synchronized(_sem_surface) { + _surface_holder = holder; + _sem_surface.notifyAll(); } - } - protected void finalize() { - destroy(); - } - // Surface creation: - // GUI thread: create surface, release lock - // ScummVM thread: acquire lock (block), read surface - // - // Surface deletion: - // GUI thread: post event, acquire lock (block), return - // ScummVM thread: read event, free surface, release lock - // - // In other words, ScummVM thread does this: - // acquire lock - // setup surface - // when SCREEN_CHANGED arrives: - // destroy surface - // release lock - // back to acquire lock - static final int configSpec[] = { - EGL10.EGL_RED_SIZE, 5, - EGL10.EGL_GREEN_SIZE, 5, - EGL10.EGL_BLUE_SIZE, 5, - EGL10.EGL_DEPTH_SIZE, 0, - EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, - EGL10.EGL_NONE, - }; - EGL10 egl; - EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY; - EGLConfig eglConfig; - EGLContext eglContext = EGL10.EGL_NO_CONTEXT; - EGLSurface eglSurface = EGL10.EGL_NO_SURFACE; - Semaphore surfaceLock = new Semaphore(0, true); - SurfaceHolder nativeSurface; - - public void surfaceCreated(SurfaceHolder holder) { - nativeSurface = holder; - surfaceLock.release(); + // store values for the native code + setSurface(width, height); } - public void surfaceChanged(SurfaceHolder holder, int format, - int width, int height) { - // Disabled while I debug GL problems - pushEvent(new Event(Event.EVENT_SCREEN_CHANGED)); - } + // SurfaceHolder callback + final public void surfaceDestroyed(SurfaceHolder holder) { + Log.d(LOG_TAG, "surfaceDestroyed"); - public void surfaceDestroyed(SurfaceHolder holder) { - try { - surfaceLock.acquire(); - } catch (InterruptedException e) { - Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e); + synchronized(_sem_surface) { + _surface_holder = null; + _sem_surface.notifyAll(); } + + // clear values for the native code + setSurface(0, 0); } - // For debugging - private static final Map<String, Integer> attribs; - static { - attribs = new LinkedHashMap<String, Integer>(); - attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID); - attribs.put("BUFFER_SIZE", EGL10.EGL_BUFFER_SIZE); - attribs.put("RED_SIZE", EGL10.EGL_RED_SIZE); - attribs.put("GREEN_SIZE", EGL10.EGL_GREEN_SIZE); - attribs.put("BLUE_SIZE", EGL10.EGL_BLUE_SIZE); - attribs.put("ALPHA_SIZE", EGL10.EGL_ALPHA_SIZE); - //attribs.put("BIND_TO_RGB", EGL10.EGL_BIND_TO_TEXTURE_RGB); - //attribs.put("BIND_TO_RGBA", EGL10.EGL_BIND_TO_TEXTURE_RGBA); - attribs.put("CONFIG_CAVEAT", EGL10.EGL_CONFIG_CAVEAT); - attribs.put("DEPTH_SIZE", EGL10.EGL_DEPTH_SIZE); - attribs.put("LEVEL", EGL10.EGL_LEVEL); - attribs.put("MAX_PBUFFER_WIDTH", EGL10.EGL_MAX_PBUFFER_WIDTH); - attribs.put("MAX_PBUFFER_HEIGHT", EGL10.EGL_MAX_PBUFFER_HEIGHT); - attribs.put("MAX_PBUFFER_PIXELS", EGL10.EGL_MAX_PBUFFER_PIXELS); - //attribs.put("MAX_SWAP_INTERVAL", EGL10.EGL_MAX_SWAP_INTERVAL); - //attribs.put("MIN_SWAP_INTERVAL", EGL10.EGL_MIN_SWAP_INTERVAL); - attribs.put("NATIVE_RENDERABLE", EGL10.EGL_NATIVE_RENDERABLE); - attribs.put("NATIVE_VISUAL_ID", EGL10.EGL_NATIVE_VISUAL_ID); - attribs.put("NATIVE_VISUAL_TYPE", EGL10.EGL_NATIVE_VISUAL_TYPE); - attribs.put("SAMPLE_BUFFERS", EGL10.EGL_SAMPLE_BUFFERS); - attribs.put("SAMPLES", EGL10.EGL_SAMPLES); - attribs.put("STENCIL_SIZE", EGL10.EGL_STENCIL_SIZE); - attribs.put("SURFACE_TYPE", EGL10.EGL_SURFACE_TYPE); - attribs.put("TRANSPARENT_TYPE", EGL10.EGL_TRANSPARENT_TYPE); - attribs.put("TRANSPARENT_RED_VALUE", EGL10.EGL_TRANSPARENT_RED_VALUE); - attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE); - attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE); + final public void setArgs(String[] args) { + _args = args; } - private void dumpEglConfig(EGLConfig config) { - int[] value = new int[1]; - for (Map.Entry<String, Integer> entry : attribs.entrySet()) { - egl.eglGetConfigAttrib(eglDisplay, config, - entry.getValue(), value); - if (value[0] == EGL10.EGL_NONE) - Log.d(LOG_TAG, entry.getKey() + ": NONE"); - else - Log.d(LOG_TAG, String.format("%s: %d", entry.getKey(), value[0])); + + final public void run() { + try { + initAudio(); + initEGL(); + + // wait for the surfaceChanged callback + synchronized(_sem_surface) { + while (_surface_holder == null) + _sem_surface.wait(); + } + } catch (Exception e) { + deinitEGL(); + deinitAudio(); + + throw new RuntimeException("Error preparing the ScummVM thread", e); } + + create(_asset_manager, _egl, _egl_display, + _audio_track, _sample_rate, _buffer_size); + + int res = main(_args); + + destroy(); + + deinitEGL(); + deinitAudio(); + + // On exit, tear everything down for a fresh restart next time. + System.exit(res); } - // Called by ScummVM thread (from initBackend) - private void createScummVMGLContext() { - egl = (EGL10)EGLContext.getEGL(); - eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + final private void initEGL() throws Exception { + _egl = (EGL10)EGLContext.getEGL(); + _egl_display = _egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + int[] version = new int[2]; - egl.eglInitialize(eglDisplay, version); + _egl.eglInitialize(_egl_display, version); + int[] num_config = new int[1]; - egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config); + _egl.eglGetConfigs(_egl_display, null, 0, num_config); final int numConfigs = num_config[0]; + if (numConfigs <= 0) - throw new IllegalArgumentException("No configs match configSpec"); + throw new IllegalArgumentException("No EGL configs"); EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs, - num_config); - - if (false) { - Log.d(LOG_TAG, String.format("Found %d EGL configurations.", numConfigs)); - for (EGLConfig config : configs) - dumpEglConfig(config); - } + _egl.eglGetConfigs(_egl_display, configs, numConfigs, num_config); // Android's eglChooseConfig is busted in several versions and - // devices so we have to filter/rank the configs again ourselves. - eglConfig = chooseEglConfig(configs); - if (false) { - Log.d(LOG_TAG, String.format("Chose EGL config from %d possibilities.", numConfigs)); - dumpEglConfig(eglConfig); - } + // devices so we have to filter/rank the configs ourselves. + _egl_config = chooseEglConfig(configs); - eglContext = egl.eglCreateContext(eglDisplay, eglConfig, - EGL10.EGL_NO_CONTEXT, null); - if (eglContext == EGL10.EGL_NO_CONTEXT) - throw new RuntimeException("Failed to create context"); - } + _egl_context = _egl.eglCreateContext(_egl_display, _egl_config, + EGL10.EGL_NO_CONTEXT, null); - private EGLConfig chooseEglConfig(EGLConfig[] configs) { - int best = 0; - int bestScore = -1; - int[] value = new int[1]; + if (_egl_context == EGL10.EGL_NO_CONTEXT) + throw new Exception(String.format("Failed to create context: 0x%x", + _egl.eglGetError())); + } - for (int i = 0; i < configs.length; i++) { - EGLConfig config = configs[i]; - int score = 10000; - egl.eglGetConfigAttrib(eglDisplay, config, - EGL10.EGL_SURFACE_TYPE, value); - if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0) - continue; // must have - - egl.eglGetConfigAttrib(eglDisplay, config, - EGL10.EGL_CONFIG_CAVEAT, value); - if (value[0] != EGL10.EGL_NONE) - score -= 1000; + // Callback from C++ peer instance + final protected EGLSurface initSurface() throws Exception { + _egl_surface = _egl.eglCreateWindowSurface(_egl_display, _egl_config, + _surface_holder, null); - // Must be at least 555, but then smaller is better - final int[] colorBits = {EGL10.EGL_RED_SIZE, - EGL10.EGL_GREEN_SIZE, - EGL10.EGL_BLUE_SIZE, - EGL10.EGL_ALPHA_SIZE}; - for (int component : colorBits) { - egl.eglGetConfigAttrib(eglDisplay, config, - component, value); - if (value[0] >= 5) - score += 10; // boost if >5 bits accuracy - score -= value[0]; // penalize for wasted bits - } + if (_egl_surface == EGL10.EGL_NO_SURFACE) + throw new Exception(String.format( + "eglCreateWindowSurface failed: 0x%x", _egl.eglGetError())); - egl.eglGetConfigAttrib(eglDisplay, config, - EGL10.EGL_DEPTH_SIZE, value); - score -= value[0]; // penalize for wasted bits + _egl.eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, + _egl_context); - if (score > bestScore) { - best = i; - bestScore = score; - } - } + GL10 gl = (GL10)_egl_context.getGL(); - if (bestScore < 0) { - Log.e(LOG_TAG, "Unable to find an acceptable EGL config, expect badness."); - return configs[0]; - } + Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)", + _egl.eglQueryString(_egl_display, EGL10.EGL_VERSION), + _egl.eglQueryString(_egl_display, EGL10.EGL_VENDOR), + gl.glGetString(GL10.GL_VERSION), + gl.glGetString(GL10.GL_RENDERER), + gl.glGetString(GL10.GL_VENDOR))); - return configs[best]; + return _egl_surface; } - // Called by ScummVM thread - static private boolean _log_version = true; - protected void setupScummVMSurface() { - try { - surfaceLock.acquire(); - } catch (InterruptedException e) { - Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e); - return; - } - eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, - nativeSurface, null); - if (eglSurface == EGL10.EGL_NO_SURFACE) - Log.e(LOG_TAG, "CreateWindowSurface failed!"); - egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); - - GL10 gl = (GL10)eglContext.getGL(); - - if (_log_version) { - Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)", - egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION), - egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR), - gl.glGetString(GL10.GL_VERSION), - gl.glGetString(GL10.GL_RENDERER), - gl.glGetString(GL10.GL_VENDOR))); - _log_version = false; // only log this once + // Callback from C++ peer instance + final protected void deinitSurface() { + if (_egl_display != EGL10.EGL_NO_DISPLAY) { + _egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + + if (_egl_surface != EGL10.EGL_NO_SURFACE) + _egl.eglDestroySurface(_egl_display, _egl_surface); } - int[] value = new int[1]; - egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value); - int width = value[0]; - egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value); - int height = value[0]; - Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height)); - setSurfaceSize(width, height); + _egl_surface = EGL10.EGL_NO_SURFACE; } - // Called by ScummVM thread - protected void destroyScummVMSurface() { - if (eglSurface != null) { - egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - egl.eglDestroySurface(eglDisplay, eglSurface); - eglSurface = EGL10.EGL_NO_SURFACE; + final private void deinitEGL() { + if (_egl_display != EGL10.EGL_NO_DISPLAY) { + _egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + + if (_egl_surface != EGL10.EGL_NO_SURFACE) + _egl.eglDestroySurface(_egl_display, _egl_surface); + + if (_egl_context != EGL10.EGL_NO_CONTEXT) + _egl.eglDestroyContext(_egl_display, _egl_context); + + _egl.eglTerminate(_egl_display); } - surfaceLock.release(); + _egl_surface = EGL10.EGL_NO_SURFACE; + _egl_context = EGL10.EGL_NO_CONTEXT; + _egl_config = null; + _egl_display = EGL10.EGL_NO_DISPLAY; + _egl = null; } - public void setSurface(SurfaceHolder holder) { - holder.addCallback(this); - } + final private void initAudio() throws Exception { + _sample_rate = AudioTrack.getNativeOutputSampleRate( + AudioManager.STREAM_MUSIC); + _buffer_size = AudioTrack.getMinBufferSize(_sample_rate, + AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.ENCODING_PCM_16BIT); + + // ~50ms + int buffer_size_want = (_sample_rate * 2 * 2 / 20) & ~1023; + + if (_buffer_size < buffer_size_want) { + Log.w(LOG_TAG, String.format( + "adjusting audio buffer size (was: %d)", _buffer_size)); - final public boolean swapBuffers() { - if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) { - int error = egl.eglGetError(); - Log.w(LOG_TAG, String.format("eglSwapBuffers exited with error 0x%x", error)); - if (error == EGL11.EGL_CONTEXT_LOST) - return false; + _buffer_size = buffer_size_want; } - return true; - } - // Set scummvm config options - final public native static void loadConfigFile(String path); - final public native static void setConfMan(String key, int value); - final public native static void setConfMan(String key, String value); - final public native void enableZoning(boolean enable); - final public native void setSurfaceSize(int width, int height); + Log.i(LOG_TAG, String.format("Using %d bytes buffer for %dHz audio", + _buffer_size, _sample_rate)); - // Feed an event to ScummVM. Safe to call from other threads. - final public native void pushEvent(Event e); + _audio_track = new AudioTrack(AudioManager.STREAM_MUSIC, + _sample_rate, + AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.ENCODING_PCM_16BIT, + _buffer_size, + AudioTrack.MODE_STREAM); - final private native void audioMixCallback(byte[] buf); + if (_audio_track.getState() != AudioTrack.STATE_INITIALIZED) + throw new Exception( + String.format("Error initialising AudioTrack: %d", + _audio_track.getState())); + } - // Runs the actual ScummVM program and returns when it does. - // This should not be called from multiple threads simultaneously... - final public native int scummVMMain(String[] argv); + final private void deinitAudio() { + if (_audio_track != null) + _audio_track.stop(); - // Callbacks from C++ peer instance - //protected GraphicsMode[] getSupportedGraphicsModes() {} - protected void displayMessageOnOSD(String msg) {} - protected void setWindowCaption(String caption) {} - protected void showVirtualKeyboard(boolean enable) {} - protected String[] getSysArchives() { return new String[0]; } - protected String[] getPluginDirectories() { return new String[0]; } - protected void initBackend() throws AudioSetupException { - createScummVMGLContext(); - initAudio(); + _audio_track = null; + _buffer_size = 0; + _sample_rate = 0; } - private static class AudioThread extends Thread { - final private int buf_size; - private boolean is_paused = false; - final private ScummVM scummvm; - final private AudioTrack audio_track; - - AudioThread(ScummVM scummvm, AudioTrack audio_track, int buf_size) { - super("AudioThread"); - this.scummvm = scummvm; - this.audio_track = audio_track; - this.buf_size = buf_size; - setPriority(Thread.MAX_PRIORITY); - setDaemon(true); - } + private static final int[] s_eglAttribs = { + EGL10.EGL_CONFIG_ID, + EGL10.EGL_BUFFER_SIZE, + EGL10.EGL_RED_SIZE, + EGL10.EGL_GREEN_SIZE, + EGL10.EGL_BLUE_SIZE, + EGL10.EGL_ALPHA_SIZE, + EGL10.EGL_CONFIG_CAVEAT, + EGL10.EGL_DEPTH_SIZE, + EGL10.EGL_LEVEL, + EGL10.EGL_MAX_PBUFFER_WIDTH, + EGL10.EGL_MAX_PBUFFER_HEIGHT, + EGL10.EGL_MAX_PBUFFER_PIXELS, + EGL10.EGL_NATIVE_RENDERABLE, + EGL10.EGL_NATIVE_VISUAL_ID, + EGL10.EGL_NATIVE_VISUAL_TYPE, + EGL10.EGL_SAMPLE_BUFFERS, + EGL10.EGL_SAMPLES, + EGL10.EGL_STENCIL_SIZE, + EGL10.EGL_SURFACE_TYPE, + EGL10.EGL_TRANSPARENT_TYPE, + EGL10.EGL_TRANSPARENT_RED_VALUE, + EGL10.EGL_TRANSPARENT_GREEN_VALUE, + EGL10.EGL_TRANSPARENT_BLUE_VALUE + }; + + final private class EglAttribs extends LinkedHashMap<Integer, Integer> { + public EglAttribs(EGLConfig config) { + super(s_eglAttribs.length); + + int[] value = new int[1]; + + for (int i : s_eglAttribs) { + _egl.eglGetConfigAttrib(_egl_display, config, i, value); - public void pauseAudio() { - synchronized (this) { - is_paused = true; + put(i, value[0]); } - audio_track.pause(); } - public void resumeAudio() { - synchronized (this) { - is_paused = false; - notifyAll(); - } - audio_track.play(); + private int weightBits(int attr, int size) { + final int value = get(attr); + + int score = 0; + + if (value == size || (size > 0 && value > size)) + score += 10; + + // penalize for wasted bits + score -= value - size; + + return score; } - public void run() { - byte[] buf = new byte[buf_size]; - audio_track.play(); - int offset = 0; - try { - while (true) { - synchronized (this) { - while (is_paused) - wait(); - } - - if (offset == buf.length) { - // Grab new audio data - scummvm.audioMixCallback(buf); - offset = 0; - } - int len = buf.length - offset; - int ret = audio_track.write(buf, offset, len); - if (ret < 0) { - Log.w(LOG_TAG, String.format( - "AudioTrack.write(%dB) returned error %d", - buf.length, ret)); - break; - } else if (ret != len) { - Log.w(LOG_TAG, String.format( - "Short audio write. Wrote %dB, not %dB", - ret, buf.length)); - // Buffer is full, so yield cpu for a while - Thread.sleep(100); - } - offset += ret; - } - } catch (InterruptedException e) { - Log.e(LOG_TAG, "Audio thread interrupted", e); - } + public int weight() { + int score = 10000; + + if (get(EGL10.EGL_CONFIG_CAVEAT) != EGL10.EGL_NONE) + score -= 1000; + + // less MSAA is better + score -= get(EGL10.EGL_SAMPLES) * 100; + + // Must be at least 565, but then smaller is better + score += weightBits(EGL10.EGL_RED_SIZE, 5); + score += weightBits(EGL10.EGL_GREEN_SIZE, 6); + score += weightBits(EGL10.EGL_BLUE_SIZE, 5); + score += weightBits(EGL10.EGL_ALPHA_SIZE, 0); + score += weightBits(EGL10.EGL_DEPTH_SIZE, 0); + score += weightBits(EGL10.EGL_STENCIL_SIZE, 0); + + return score; } - } - private AudioThread audio_thread; - final public int audioSampleRate() { - return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); - } + public String toString() { + String s; - private void initAudio() throws AudioSetupException { - int sample_rate = audioSampleRate(); - int buf_size = - AudioTrack.getMinBufferSize(sample_rate, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT); - if (buf_size < 0) { - int guess = AUDIO_FRAME_SIZE * sample_rate / 100; // 10ms of audio - Log.w(LOG_TAG, String.format( - "Unable to get min audio buffer size (error %d). Guessing %dB.", - buf_size, guess)); - buf_size = guess; + if (get(EGL10.EGL_ALPHA_SIZE) > 0) + s = String.format("[%d] RGBA%d%d%d%d", + get(EGL10.EGL_CONFIG_ID), + get(EGL10.EGL_RED_SIZE), + get(EGL10.EGL_GREEN_SIZE), + get(EGL10.EGL_BLUE_SIZE), + get(EGL10.EGL_ALPHA_SIZE)); + else + s = String.format("[%d] RGB%d%d%d", + get(EGL10.EGL_CONFIG_ID), + get(EGL10.EGL_RED_SIZE), + get(EGL10.EGL_GREEN_SIZE), + get(EGL10.EGL_BLUE_SIZE)); + + if (get(EGL10.EGL_DEPTH_SIZE) > 0) + s += String.format(" D%d", get(EGL10.EGL_DEPTH_SIZE)); + + if (get(EGL10.EGL_STENCIL_SIZE) > 0) + s += String.format(" S%d", get(EGL10.EGL_STENCIL_SIZE)); + + if (get(EGL10.EGL_SAMPLES) > 0) + s += String.format(" MSAAx%d", get(EGL10.EGL_SAMPLES)); + + if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) > 0) + s += " W"; + if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_PBUFFER_BIT) > 0) + s += " P"; + if ((get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_PIXMAP_BIT) > 0) + s += " X"; + + switch (get(EGL10.EGL_CONFIG_CAVEAT)) { + case EGL10.EGL_NONE: + break; + + case EGL10.EGL_SLOW_CONFIG: + s += " SLOW"; + break; + + case EGL10.EGL_NON_CONFORMANT_CONFIG: + s += " NON_CONFORMANT"; + + default: + s += String.format(" unknown CAVEAT 0x%x", + get(EGL10.EGL_CONFIG_CAVEAT)); + } + + return s; } - Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio", - buf_size, sample_rate)); - AudioTrack audio_track = - new AudioTrack(AudioManager.STREAM_MUSIC, - sample_rate, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - buf_size, - AudioTrack.MODE_STREAM); - if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) { - Log.e(LOG_TAG, "Error initialising Android audio system."); - throw new AudioSetupException(); + }; + + final private EGLConfig chooseEglConfig(EGLConfig[] configs) { + EGLConfig res = configs[0]; + int bestScore = -1; + + Log.d(LOG_TAG, "EGL configs:"); + + for (EGLConfig config : configs) { + EglAttribs attr = new EglAttribs(config); + + // must have + if ((attr.get(EGL10.EGL_SURFACE_TYPE) & EGL10.EGL_WINDOW_BIT) == 0) + continue; + + int score = attr.weight(); + + Log.d(LOG_TAG, String.format("%s (%d)", attr.toString(), score)); + + if (score > bestScore) { + res = config; + bestScore = score; + } } - audio_thread = new AudioThread(this, audio_track, buf_size); - audio_thread.start(); - } + if (bestScore < 0) + Log.e(LOG_TAG, + "Unable to find an acceptable EGL config, expect badness."); - public void pause() { - audio_thread.pauseAudio(); - // TODO: need to pause engine too - } + Log.d(LOG_TAG, String.format("Chosen EGL config: %s", + new EglAttribs(res).toString())); - public void resume() { - // TODO: need to resume engine too - audio_thread.resumeAudio(); + return res; } static { @@ -448,15 +437,16 @@ public class ScummVM implements SurfaceHolder.Callback { final boolean sleep_for_debugger = false; if (sleep_for_debugger) { try { - Thread.sleep(20*1000); + Thread.sleep(20 * 1000); } catch (InterruptedException e) { } } - //System.loadLibrary("scummvm"); File cache_dir = ScummVMApplication.getLastCacheDir(); String libname = System.mapLibraryName("scummvm"); File libpath = new File(cache_dir, libname); + System.load(libpath.getPath()); } } + diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java index fae35b6695..1978b690d0 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java @@ -3,41 +3,27 @@ package org.inodes.gus.scummvm; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; -import android.content.res.Configuration; import android.media.AudioManager; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; -import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; -import android.view.KeyEvent; -import android.view.MotionEvent; import android.view.SurfaceView; -import android.view.View; -import android.view.ViewConfiguration; +import android.view.SurfaceHolder; +import android.view.MotionEvent; import android.view.inputmethod.InputMethodManager; import android.widget.Toast; -import java.io.IOException; - public class ScummVMActivity extends Activity { - private boolean _do_right_click; - private boolean _last_click_was_right; - - // game pixels to move per trackball/dpad event. - // FIXME: replace this with proper mouse acceleration - private final static int TRACKBALL_SCALE = 2; private class MyScummVM extends ScummVM { - private boolean scummvmRunning = false; - private boolean usingSmallScreen() { // Multiple screen sizes came in with Android 1.6. Have // to use reflection in order to continue supporting 1.5 // devices :( DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); + try { // This 'density' term is very confusing. int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null); @@ -48,27 +34,22 @@ public class ScummVMActivity extends Activity { } } - public MyScummVM() { - super(ScummVMActivity.this); + public MyScummVM(SurfaceHolder holder) { + super(ScummVMActivity.this.getAssets(), holder); // Enable ScummVM zoning on 'small' screens. - enableZoning(usingSmallScreen()); + // FIXME make this optional for the user + // disabled for now since it crops too much + //enableZoning(usingSmallScreen()); } @Override - protected void initBackend() throws ScummVM.AudioSetupException { - synchronized (this) { - scummvmRunning = true; - notifyAll(); - } - super.initBackend(); - } + protected void getDPI(float[] values) { + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); - public void waitUntilRunning() throws InterruptedException { - synchronized (this) { - while (!scummvmRunning) - wait(); - } + values[0] = metrics.xdpi; + values[1] = metrics.ydpi; } @Override @@ -95,24 +76,28 @@ public class ScummVMActivity extends Activity { @Override protected void showVirtualKeyboard(final boolean enable) { - if (getResources().getConfiguration().keyboard == - Configuration.KEYBOARD_NOKEYS) { - runOnUiThread(new Runnable() { - public void run() { - showKeyboard(enable); - } - }); - } + runOnUiThread(new Runnable() { + public void run() { + showKeyboard(enable); + } + }); + } + + @Override + protected String[] getSysArchives() { + return new String[0]; } + } - private MyScummVM scummvm; - private Thread scummvm_thread; + + private MyScummVM _scummvm; + private ScummVMEvents _events; + private Thread _scummvm_thread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - _do_right_click = false; setVolumeControlStream(AudioManager.STREAM_MUSIC); setContentView(R.layout.main); @@ -126,336 +111,110 @@ public class ScummVMActivity extends Activity { .setIcon(android.R.drawable.ic_dialog_alert) .setMessage(R.string.no_sdcard) .setNegativeButton(R.string.quit, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, - int which) { - finish(); - } - }) + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + finish(); + } + }) .show(); + return; } SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface); - - main_surface.setOnTouchListener(new View.OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - return onTouchEvent(event); - } - }); - main_surface.setOnKeyListener(new View.OnKeyListener() { - public boolean onKey(View v, int code, KeyEvent ev) { - return onKeyDown(code, ev); - } - }); + main_surface.requestFocus(); - // Start ScummVM - scummvm = new MyScummVM(); - scummvm_thread = new Thread(new Runnable() { - public void run() { - try { - runScummVM(); - } catch (Exception e) { - Log.e(ScummVM.LOG_TAG, "Fatal error in ScummVM thread", e); - new AlertDialog.Builder(ScummVMActivity.this) - .setTitle("Error") - .setMessage(e.toString()) - .setIcon(android.R.drawable.ic_dialog_alert) - .show(); - finish(); - } - } - }, "ScummVM"); - scummvm_thread.start(); - - // Block UI thread until ScummVM has started. In particular, - // this means that surface and event callbacks should be safe - // after this point. - try { - scummvm.waitUntilRunning(); - } catch (InterruptedException e) { - Log.e(ScummVM.LOG_TAG, "Interrupted while waiting for ScummVM.initBackend", e); - finish(); - } + getFilesDir().mkdirs(); - scummvm.setSurface(main_surface.getHolder()); - } + // Start ScummVM + _scummvm = new MyScummVM(main_surface.getHolder()); - // Runs in another thread - private void runScummVM() throws IOException { - getFilesDir().mkdirs(); - String[] args = { - "ScummVM-lib", + _scummvm.setArgs(new String[] { + "ScummVM", "--config=" + getFileStreamPath("scummvmrc").getPath(), "--path=" + Environment.getExternalStorageDirectory().getPath(), "--gui-theme=scummmodern", "--savepath=" + getDir("saves", 0).getPath() - }; + }); - int ret = scummvm.scummVMMain(args); + _events = new ScummVMEvents(this, _scummvm); - // On exit, tear everything down for a fresh - // restart next time. - System.exit(ret); - } + main_surface.setOnKeyListener(_events); + main_surface.setOnTouchListener(_events); - private boolean was_paused = false; + _scummvm_thread = new Thread(_scummvm, "ScummVM"); + _scummvm_thread.start(); + } @Override - public void onPause() { - if (scummvm != null) { - was_paused = true; - scummvm.pause(); - } - super.onPause(); + public void onStart() { + Log.d(ScummVM.LOG_TAG, "onStart"); + + super.onStart(); } @Override public void onResume() { + Log.d(ScummVM.LOG_TAG, "onResume"); + super.onResume(); - if (scummvm != null && was_paused) - scummvm.resume(); - was_paused = false; + + if (_scummvm != null) + _scummvm.setPause(false); } @Override - public void onStop() { - if (scummvm != null) { - scummvm.pushEvent(new Event(Event.EVENT_QUIT)); - try { - scummvm_thread.join(1000); // 1s timeout - } catch (InterruptedException e) { - Log.i(ScummVM.LOG_TAG, "Error while joining ScummVM thread", e); - } - } - super.onStop(); - } + public void onPause() { + Log.d(ScummVM.LOG_TAG, "onPause"); - static final int MSG_MENU_LONG_PRESS = 1; - private final Handler keycodeMenuTimeoutHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - if (msg.what == MSG_MENU_LONG_PRESS) { - InputMethodManager imm = (InputMethodManager) - getSystemService(INPUT_METHOD_SERVICE); - if (imm != null) - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); - } - } - }; + super.onPause(); - @Override - public boolean onKeyUp(int keyCode, KeyEvent kevent) { - return onKeyDown(keyCode, kevent); + if (_scummvm != null) + _scummvm.setPause(true); } @Override - public boolean onKeyMultiple(int keyCode, int repeatCount, - KeyEvent kevent) { - return onKeyDown(keyCode, kevent); + public void onStop() { + Log.d(ScummVM.LOG_TAG, "onStop"); + + super.onStop(); } @Override - public boolean onKeyDown(int keyCode, KeyEvent kevent) { - // Filter out "special" keys - switch (keyCode) { - case KeyEvent.KEYCODE_MENU: - // Have to reimplement hold-down-menu-brings-up-softkeybd - // ourselves, since we are otherwise hijacking the menu - // key :( - // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel() - // for the usual Android implementation of this feature. - if (kevent.getRepeatCount() > 0) - // Ignore keyrepeat for menu - return false; - boolean timeout_fired = false; - if (getResources().getConfiguration().keyboard == - Configuration.KEYBOARD_NOKEYS) { - timeout_fired = !keycodeMenuTimeoutHandler.hasMessages(MSG_MENU_LONG_PRESS); - keycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS); - if (kevent.getAction() == KeyEvent.ACTION_DOWN) { - keycodeMenuTimeoutHandler.sendMessageDelayed( - keycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS), - ViewConfiguration.getLongPressTimeout()); - return true; - } - } - if (kevent.getAction() == KeyEvent.ACTION_UP) { - if (!timeout_fired) - scummvm.pushEvent(new Event(Event.EVENT_MAINMENU)); - return true; - } - return false; - case KeyEvent.KEYCODE_CAMERA: - case KeyEvent.KEYCODE_SEARCH: - _do_right_click = (kevent.getAction() == KeyEvent.ACTION_DOWN); - return true; - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: { - // HTC Hero doesn't seem to generate - // MotionEvent.ACTION_DOWN events on trackball press :( - // We'll have to just fake one here. - // Some other handsets lack a trackball, so the DPAD is - // the only way of moving the cursor. - int motion_action; - // FIXME: this logic is a mess. - if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { - switch (kevent.getAction()) { - case KeyEvent.ACTION_DOWN: - motion_action = MotionEvent.ACTION_DOWN; - break; - case KeyEvent.ACTION_UP: - motion_action = MotionEvent.ACTION_UP; - break; - default: // ACTION_MULTIPLE - return false; - } - } else - motion_action = MotionEvent.ACTION_MOVE; - - Event e = new Event(getEventType(motion_action)); - e.mouse_x = 0; - e.mouse_y = 0; - e.mouse_relative = true; - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_UP: - e.mouse_y = -TRACKBALL_SCALE; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - e.mouse_y = TRACKBALL_SCALE; - break; - case KeyEvent.KEYCODE_DPAD_LEFT: - e.mouse_x = -TRACKBALL_SCALE; - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - e.mouse_x = TRACKBALL_SCALE; - break; - } - scummvm.pushEvent(e); - return true; - } - case KeyEvent.KEYCODE_BACK: - // skip isSystem() check and fall through to main code - break; - default: - if (kevent.isSystem()) - return false; - } + public void onDestroy() { + Log.d(ScummVM.LOG_TAG, "onDestroy"); - // FIXME: what do I need to do for composed characters? - - Event e = new Event(); - - switch (kevent.getAction()) { - case KeyEvent.ACTION_DOWN: - e.type = Event.EVENT_KEYDOWN; - e.synthetic = false; - break; - case KeyEvent.ACTION_UP: - e.type = Event.EVENT_KEYUP; - e.synthetic = false; - break; - case KeyEvent.ACTION_MULTIPLE: - // e.type is handled below - e.synthetic = true; - break; - default: - return false; - } + super.onDestroy(); - e.kbd_keycode = Event.androidKeyMap.containsKey(keyCode) ? - Event.androidKeyMap.get(keyCode) : Event.KEYCODE_INVALID; - e.kbd_ascii = kevent.getUnicodeChar(); - if (e.kbd_ascii == 0) - e.kbd_ascii = e.kbd_keycode; // scummvm keycodes are mostly ascii - - - e.kbd_flags = 0; - if (kevent.isAltPressed()) - e.kbd_flags |= Event.KBD_ALT; - if (kevent.isSymPressed()) // no ctrl key in android, so use sym (?) - e.kbd_flags |= Event.KBD_CTRL; - if (kevent.isShiftPressed()) { - if (keyCode >= KeyEvent.KEYCODE_0 && - keyCode <= KeyEvent.KEYCODE_9) { - // Shift+number -> convert to F* key - int offset = keyCode == KeyEvent.KEYCODE_0 ? - 10 : keyCode - KeyEvent.KEYCODE_1; // turn 0 into 10 - e.kbd_keycode = Event.KEYCODE_F1 + offset; - e.kbd_ascii = Event.ASCII_F1 + offset; - } else - e.kbd_flags |= Event.KBD_SHIFT; - } + if (_events != null) { + _events.sendQuitEvent(); - if (kevent.getAction() == KeyEvent.ACTION_MULTIPLE) { - for (int i = 0; i <= kevent.getRepeatCount(); i++) { - e.type = Event.EVENT_KEYDOWN; - scummvm.pushEvent(e); - e.type = Event.EVENT_KEYUP; - scummvm.pushEvent(e); + try { + // 1s timeout + _scummvm_thread.join(1000); + } catch (InterruptedException e) { + Log.i(ScummVM.LOG_TAG, "Error while joining ScummVM thread", e); } - } else - scummvm.pushEvent(e); - - return true; - } - private int getEventType(int action) { - switch (action) { - case MotionEvent.ACTION_DOWN: - _last_click_was_right = _do_right_click; - return _last_click_was_right ? - Event.EVENT_RBUTTONDOWN : Event.EVENT_LBUTTONDOWN; - case MotionEvent.ACTION_UP: - return _last_click_was_right ? - Event.EVENT_RBUTTONUP : Event.EVENT_LBUTTONUP; - case MotionEvent.ACTION_MOVE: - return Event.EVENT_MOUSEMOVE; - default: - return Event.EVENT_INVALID; + _scummvm = null; } } @Override - public boolean onTrackballEvent(MotionEvent event) { - int type = getEventType(event.getAction()); - if (type == Event.EVENT_INVALID) - return false; - - Event e = new Event(type); - e.mouse_x = - (int)(event.getX() * event.getXPrecision()) * TRACKBALL_SCALE; - e.mouse_y = - (int)(event.getY() * event.getYPrecision()) * TRACKBALL_SCALE; - e.mouse_relative = true; - scummvm.pushEvent(e); - - return true; - } + public boolean onTrackballEvent(MotionEvent e) { + if (_events != null) + return _events.onTrackballEvent(e); - @Override - public boolean onTouchEvent(MotionEvent event) { - int type = getEventType(event.getAction()); - if (type == Event.EVENT_INVALID) - return false; - - Event e = new Event(type); - e.mouse_x = (int)event.getX(); - e.mouse_y = (int)event.getY(); - e.mouse_relative = false; - scummvm.pushEvent(e); - - return true; + return false; } private void showKeyboard(boolean show) { SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + if (show) imm.showSoftInput(main_surface, InputMethodManager.SHOW_IMPLICIT); else @@ -463,3 +222,4 @@ public class ScummVMActivity extends Activity { InputMethodManager.HIDE_IMPLICIT_ONLY); } } + diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java index 37a9d09e1a..f9eec72eac 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMApplication.java @@ -8,22 +8,24 @@ public class ScummVMApplication extends Application { public final static String ACTION_PLUGIN_QUERY = "org.inodes.gus.scummvm.action.PLUGIN_QUERY"; public final static String EXTRA_UNPACK_LIBS = "org.inodes.gus.scummvm.extra.UNPACK_LIBS"; - private static File cache_dir; + private static File _cache_dir; @Override public void onCreate() { super.onCreate(); + // This is still on /data :( - cache_dir = getCacheDir(); + _cache_dir = getCacheDir(); // This is mounted noexec :( //cache_dir = new File(Environment.getExternalStorageDirectory(), - // "/.ScummVM.tmp"); + // "/.ScummVM.tmp"); // This is owned by download manager and requires special // permissions to access :( //cache_dir = Environment.getDownloadCacheDirectory(); } public static File getLastCacheDir() { - return cache_dir; + return _cache_dir; } } + diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java new file mode 100644 index 0000000000..2d5c100a1c --- /dev/null +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMEvents.java @@ -0,0 +1,232 @@ +package org.inodes.gus.scummvm; + +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.content.Context; +import android.view.KeyEvent; +import android.view.KeyCharacterMap; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.GestureDetector; +import android.view.inputmethod.InputMethodManager; + +public class ScummVMEvents implements + android.view.View.OnKeyListener, + android.view.View.OnTouchListener, + android.view.GestureDetector.OnGestureListener, + android.view.GestureDetector.OnDoubleTapListener { + + public static final int JE_SYS_KEY = 0; + public static final int JE_KEY = 1; + public static final int JE_DPAD = 2; + public static final int JE_DOWN = 3; + public static final int JE_SCROLL = 4; + public static final int JE_TAP = 5; + public static final int JE_DOUBLE_TAP = 6; + public static final int JE_MULTI = 7; + public static final int JE_BALL = 8; + public static final int JE_QUIT = 0x1000; + + final protected Context _context; + final protected ScummVM _scummvm; + final protected GestureDetector _gd; + final protected int _longPress; + + public ScummVMEvents(Context context, ScummVM scummvm) { + _context = context; + _scummvm = scummvm; + + _gd = new GestureDetector(context, this); + _gd.setOnDoubleTapListener(this); + _gd.setIsLongpressEnabled(false); + + _longPress = ViewConfiguration.getLongPressTimeout(); + } + + final public void sendQuitEvent() { + _scummvm.pushEvent(JE_QUIT, 0, 0, 0, 0, 0); + } + + public boolean onTrackballEvent(MotionEvent e) { + _scummvm.pushEvent(JE_BALL, e.getAction(), + (int)(e.getX() * e.getXPrecision() * 100), + (int)(e.getY() * e.getYPrecision() * 100), + 0, 0); + return true; + } + + final static int MSG_MENU_LONG_PRESS = 1; + + final private Handler keyHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_MENU_LONG_PRESS) { + InputMethodManager imm = (InputMethodManager) + _context.getSystemService(_context.INPUT_METHOD_SERVICE); + + if (imm != null) + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + }; + + // OnKeyListener + final public boolean onKey(View v, int keyCode, KeyEvent e) { + final int action = e.getAction(); + + if (e.isSystem()) { + // filter what we handle + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: + case KeyEvent.KEYCODE_MENU: + case KeyEvent.KEYCODE_CAMERA: + case KeyEvent.KEYCODE_SEARCH: + break; + + default: + return false; + } + + // no repeats for system keys + if (e.getRepeatCount() > 0) + return false; + + // Have to reimplement hold-down-menu-brings-up-softkeybd + // ourselves, since we are otherwise hijacking the menu key :( + // See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel() + // for the usual Android implementation of this feature. + if (keyCode == KeyEvent.KEYCODE_MENU) { + final boolean fired = + !keyHandler.hasMessages(MSG_MENU_LONG_PRESS); + + keyHandler.removeMessages(MSG_MENU_LONG_PRESS); + + if (action == KeyEvent.ACTION_DOWN) { + keyHandler.sendMessageDelayed(keyHandler.obtainMessage( + MSG_MENU_LONG_PRESS), _longPress); + return true; + } + + if (fired) + return true; + + // only send up events of the menu button to the native side + if (action != KeyEvent.ACTION_UP) + return true; + } + + _scummvm.pushEvent(JE_SYS_KEY, action, keyCode, 0, 0, 0); + + return true; + } + + // sequence of characters + if (action == KeyEvent.ACTION_MULTIPLE && + keyCode == KeyEvent.KEYCODE_UNKNOWN) { + final KeyCharacterMap m = KeyCharacterMap.load(e.getDeviceId()); + final KeyEvent[] es = m.getEvents(e.getCharacters().toCharArray()); + + if (es == null) + return true; + + for (KeyEvent s : es) { + _scummvm.pushEvent(JE_KEY, s.getAction(), s.getKeyCode(), + s.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK, + s.getMetaState(), s.getRepeatCount()); + } + + return true; + } + + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_CENTER: + _scummvm.pushEvent(JE_DPAD, action, keyCode, + (int)(e.getEventTime() - e.getDownTime()), + e.getRepeatCount(), 0); + return true; + } + + _scummvm.pushEvent(JE_KEY, action, keyCode, + e.getUnicodeChar() & KeyCharacterMap.COMBINING_ACCENT_MASK, + e.getMetaState(), e.getRepeatCount()); + + return true; + } + + // OnTouchListener + final public boolean onTouch(View v, MotionEvent e) { + final int action = e.getAction(); + + // constants from APIv5: + // (action & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT + final int pointer = (action & 0xff00) >> 8; + + if (pointer > 0) { + _scummvm.pushEvent(JE_MULTI, pointer, action & 0xff, // ACTION_MASK + (int)e.getX(), (int)e.getY(), 0); + return true; + } + + return _gd.onTouchEvent(e); + } + + // OnGestureListener + final public boolean onDown(MotionEvent e) { + _scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0); + return true; + } + + final public boolean onFling(MotionEvent e1, MotionEvent e2, + float velocityX, float velocityY) { + //Log.d(ScummVM.LOG_TAG, String.format("onFling: %s -> %s (%.3f %.3f)", + // e1.toString(), e2.toString(), + // velocityX, velocityY)); + + return true; + } + + final public void onLongPress(MotionEvent e) { + // disabled, interferes with drag&drop + } + + final public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + _scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(), + (int)e2.getX(), (int)e2.getY(), 0); + + return true; + } + + final public void onShowPress(MotionEvent e) { + } + + final public boolean onSingleTapUp(MotionEvent e) { + _scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(), + (int)(e.getEventTime() - e.getDownTime()), 0, 0); + + return true; + } + + // OnDoubleTapListener + final public boolean onDoubleTap(MotionEvent e) { + return true; + } + + final public boolean onDoubleTapEvent(MotionEvent e) { + _scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(), + e.getAction(), 0, 0); + + return true; + } + + final public boolean onSingleTapConfirmed(MotionEvent e) { + return true; + } +} + diff --git a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java index 8811b1f3ae..c4b2ad7f5d 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java +++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java @@ -370,3 +370,4 @@ public class Unpacker extends Activity { } } } + diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp new file mode 100644 index 0000000000..c830676c07 --- /dev/null +++ b/backends/platform/android/texture.cpp @@ -0,0 +1,494 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(__ANDROID__) + +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +// Disable printf override in common/forbidden.h to avoid +// clashes with log.h from the Android SDK. +// That header file uses +// __attribute__ ((format(printf, 3, 4))) +// which gets messed up by our override mechanism; this could +// be avoided by either changing the Android SDK to use the equally +// legal and valid +// __attribute__ ((format(printf, 3, 4))) +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the Android port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + +#include "base/main.h" +#include "graphics/surface.h" + +#include "common/rect.h" +#include "common/array.h" +#include "common/util.h" +#include "common/tokenizer.h" + +#include "backends/platform/android/texture.h" +#include "backends/platform/android/android.h" + +// Supported GL extensions +static bool npot_supported = false; +#ifdef GL_OES_draw_texture +static bool draw_tex_supported = false; +#endif + +static inline GLfixed xdiv(int numerator, int denominator) { + assert(numerator < (1 << 16)); + return (numerator << 16) / denominator; +} + +template <class T> +static T nextHigher2(T k) { + if (k == 0) + return 1; + --k; + + for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1) + k = k | k >> i; + + return k + 1; +} + +void GLESBaseTexture::initGLExtensions() { + const char *ext_string = + reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)); + + LOGI("Extensions: %s", ext_string); + + Common::StringTokenizer tokenizer(ext_string, " "); + while (!tokenizer.empty()) { + Common::String token = tokenizer.nextToken(); + + if (token == "GL_ARB_texture_non_power_of_two") + npot_supported = true; + +#ifdef GL_OES_draw_texture + if (token == "GL_OES_draw_texture") + draw_tex_supported = true; +#endif + } +} + +GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType, + Graphics::PixelFormat pixelFormat) : + _glFormat(glFormat), + _glType(glType), + _glFilter(GL_NEAREST), + _texture_name(0), + _surface(), + _texture_width(0), + _texture_height(0), + _draw_rect(), + _all_dirty(false), + _dirty_rect(), + _pixelFormat(pixelFormat), + _palettePixelFormat() +{ + GLCALL(glGenTextures(1, &_texture_name)); +} + +GLESBaseTexture::~GLESBaseTexture() { + release(); +} + +void GLESBaseTexture::release() { + if (_texture_name) { + LOGD("Destroying texture %u", _texture_name); + + GLCALL(glDeleteTextures(1, &_texture_name)); + _texture_name = 0; + } +} + +void GLESBaseTexture::reinit() { + GLCALL(glGenTextures(1, &_texture_name)); + + initSize(); + + setDirty(); +} + +void GLESBaseTexture::initSize() { + // Allocate room for the texture now, but pixel data gets uploaded + // later (perhaps with multiple TexSubImage2D operations). + GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glFormat, + _texture_width, _texture_height, + 0, _glFormat, _glType, 0)); +} + +void GLESBaseTexture::setLinearFilter(bool value) { + if (value) + _glFilter = GL_LINEAR; + else + _glFilter = GL_NEAREST; + + GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); + + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); +} + +void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) { + _surface.w = w; + _surface.h = h; + _surface.format = _pixelFormat; + + if (w == _texture_width && h == _texture_height) + return; + + if (npot_supported) { + _texture_width = _surface.w; + _texture_height = _surface.h; + } else { + _texture_width = nextHigher2(_surface.w); + _texture_height = nextHigher2(_surface.h); + } + + initSize(); +} + +void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { + GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); + +#ifdef GL_OES_draw_texture + // Great extension, but only works under specific conditions. + // Still a work-in-progress - disabled for now. + if (false && draw_tex_supported && !hasPalette()) { + //GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); + const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h }; + + GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop)); + + // Android GLES bug? + GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff)); + + GLCALL(glDrawTexiOES(x, y, 0, w, h)); + } else +#endif + { + const GLfixed tex_width = xdiv(_surface.w, _texture_width); + const GLfixed tex_height = xdiv(_surface.h, _texture_height); + const GLfixed texcoords[] = { + 0, 0, + tex_width, 0, + 0, tex_height, + tex_width, tex_height, + }; + + GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords)); + + const GLshort vertices[] = { + x, y, + x + w, y, + x, y + h, + x + w, y + h, + }; + + GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices)); + + assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords)); + GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2)); + } + + clearDirty(); +} + +const Graphics::PixelFormat &GLESBaseTexture::getPixelFormat() const { + return _pixelFormat; +} + +GLESTexture::GLESTexture(GLenum glFormat, GLenum glType, + Graphics::PixelFormat pixelFormat) : + GLESBaseTexture(glFormat, glType, pixelFormat), + _pixels(0), + _buf(0) { +} + +GLESTexture::~GLESTexture() { + delete[] _buf; + delete[] _pixels; +} + +void GLESTexture::allocBuffer(GLuint w, GLuint h) { + GLuint oldw = _surface.w; + GLuint oldh = _surface.h; + + GLESBaseTexture::allocBuffer(w, h); + + _surface.pitch = w * _pixelFormat.bytesPerPixel; + + if (_surface.w == oldw && _surface.h == oldh) { + fillBuffer(0); + return; + } + + delete[] _buf; + delete[] _pixels; + + _pixels = new byte[w * h * _surface.format.bytesPerPixel]; + assert(_pixels); + + _surface.pixels = _pixels; + + fillBuffer(0); + + _buf = new byte[w * h * _surface.format.bytesPerPixel]; + assert(_buf); +} + +void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, + const void *buf, int pitch_buf) { + setDirtyRect(Common::Rect(x, y, x + w, y + h)); + + const byte *src = (const byte *)buf; + byte *dst = _pixels + y * _surface.pitch + x * _surface.format.bytesPerPixel; + + do { + memcpy(dst, src, w * _surface.format.bytesPerPixel); + dst += _surface.pitch; + src += pitch_buf; + } while (--h); +} + +void GLESTexture::fillBuffer(uint32 color) { + assert(_surface.pixels); + + if (_pixelFormat.bytesPerPixel == 1 || + ((color & 0xff) == ((color >> 8) & 0xff))) + memset(_pixels, color & 0xff, _surface.pitch * _surface.h); + else + Common::set_to(_pixels, _pixels + _surface.pitch * _surface.h, + (uint16)color); + + setDirty(); +} + +void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { + if (_all_dirty) { + _dirty_rect.top = 0; + _dirty_rect.left = 0; + _dirty_rect.bottom = _surface.h; + _dirty_rect.right = _surface.w; + + _all_dirty = false; + } + + if (!_dirty_rect.isEmpty()) { + byte *_tex; + + int16 dwidth = _dirty_rect.width(); + int16 dheight = _dirty_rect.height(); + + if (dwidth == _surface.w) { + _tex = _pixels + _dirty_rect.top * _surface.pitch; + } else { + _tex = _buf; + + byte *src = _pixels + _dirty_rect.top * _surface.pitch + + _dirty_rect.left * _surface.format.bytesPerPixel; + byte *dst = _buf; + + uint16 l = dwidth * _surface.format.bytesPerPixel; + + for (uint16 i = 0; i < dheight; ++i) { + memcpy(dst, src, l); + src += _surface.pitch; + dst += l; + } + } + + GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); + + GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, + _dirty_rect.left, _dirty_rect.top, + dwidth, dheight, _glFormat, _glType, _tex)); + } + + GLESBaseTexture::drawTexture(x, y, w, h); +} + +GLES4444Texture::GLES4444Texture() : + GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) { +} + +GLES4444Texture::~GLES4444Texture() { +} + +GLES5551Texture::GLES5551Texture() : + GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) { +} + +GLES5551Texture::~GLES5551Texture() { +} + +GLES565Texture::GLES565Texture() : + GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) { +} + +GLES565Texture::~GLES565Texture() { +} + +GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType, + Graphics::PixelFormat pixelFormat) : + GLESBaseTexture(glFormat, glType, pixelFormat), + _palette(0), + _pixels(0), + _buf(0) +{ + _palettePixelFormat = pixelFormat; + _fake_format = Graphics::PixelFormat::createFormatCLUT8(); + + _palette = new uint16[256]; + assert(_palette); + + memset(_palette, 0, 256 * 2); +} + +GLESFakePaletteTexture::~GLESFakePaletteTexture() { + delete[] _buf; + delete[] _pixels; + delete[] _palette; +} + +void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) { + GLuint oldw = _surface.w; + GLuint oldh = _surface.h; + + GLESBaseTexture::allocBuffer(w, h); + + _surface.format = Graphics::PixelFormat::createFormatCLUT8(); + _surface.pitch = w; + + if (_surface.w == oldw && _surface.h == oldh) { + fillBuffer(0); + return; + } + + delete[] _buf; + delete[] _pixels; + + _pixels = new byte[w * h]; + assert(_pixels); + + // fixup surface, for the outside this is a CLUT8 surface + _surface.pixels = _pixels; + + fillBuffer(0); + + _buf = new uint16[w * h]; + assert(_buf); +} + +void GLESFakePaletteTexture::fillBuffer(uint32 color) { + assert(_surface.pixels); + memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h); + setDirty(); +} + +void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y, GLuint w, + GLuint h, const void *buf, + int pitch_buf) { + setDirtyRect(Common::Rect(x, y, x + w, y + h)); + + const byte *src = (const byte *)buf; + byte *dst = _pixels + y * _surface.pitch + x; + + do { + memcpy(dst, src, w); + dst += _surface.pitch; + src += pitch_buf; + } while (--h); +} + +void GLESFakePaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, + GLshort h) { + if (_all_dirty) { + _dirty_rect.top = 0; + _dirty_rect.left = 0; + _dirty_rect.bottom = _surface.h; + _dirty_rect.right = _surface.w; + + _all_dirty = false; + } + + if (!_dirty_rect.isEmpty()) { + int16 dwidth = _dirty_rect.width(); + int16 dheight = _dirty_rect.height(); + + byte *src = _pixels + _dirty_rect.top * _surface.pitch + + _dirty_rect.left; + uint16 *dst = _buf; + uint pitch_delta = _surface.pitch - dwidth; + + for (uint16 j = 0; j < dheight; ++j) { + for (uint16 i = 0; i < dwidth; ++i) + *dst++ = _palette[*src++]; + src += pitch_delta; + } + + GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); + + GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, + _dirty_rect.left, _dirty_rect.top, + dwidth, dheight, _glFormat, _glType, _buf)); + } + + GLESBaseTexture::drawTexture(x, y, w, h); +} + +const Graphics::PixelFormat &GLESFakePaletteTexture::getPixelFormat() const { + return _fake_format; +} + +GLESFakePalette565Texture::GLESFakePalette565Texture() : + GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + GLES565Texture::pixelFormat()) { +} + +GLESFakePalette565Texture::~GLESFakePalette565Texture() { +} + +GLESFakePalette5551Texture::GLESFakePalette5551Texture() : + GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, + GLES5551Texture::pixelFormat()) { +} + +GLESFakePalette5551Texture::~GLESFakePalette5551Texture() { +} + +#endif + diff --git a/backends/platform/android/texture.h b/backends/platform/android/texture.h new file mode 100644 index 0000000000..6344326259 --- /dev/null +++ b/backends/platform/android/texture.h @@ -0,0 +1,277 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef _ANDROID_TEXTURE_H_ +#define _ANDROID_TEXTURE_H_ + +#if defined(__ANDROID__) + +#include <GLES/gl.h> + +#include "graphics/surface.h" +#include "graphics/pixelformat.h" + +#include "common/rect.h" +#include "common/array.h" + +class GLESBaseTexture { +public: + static void initGLExtensions(); + +protected: + GLESBaseTexture(GLenum glFormat, GLenum glType, + Graphics::PixelFormat pixelFormat); + +public: + virtual ~GLESBaseTexture(); + + void release(); + void reinit(); + void initSize(); + + void setLinearFilter(bool value); + + virtual void allocBuffer(GLuint w, GLuint h); + + virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, + const void *buf, int pitch_buf) = 0; + virtual void fillBuffer(uint32 color) = 0; + + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + + inline void setDrawRect(const Common::Rect &rect) { + _draw_rect = rect; + } + + inline void setDrawRect(int16 w, int16 h) { + _draw_rect = Common::Rect(w, h); + } + + inline void setDrawRect(int16 x1, int16 y1, int16 x2, int16 y2) { + _draw_rect = Common::Rect(x1, y1, x2, y2); + } + + inline const Common::Rect &getDrawRect() const { + return _draw_rect; + } + + inline void drawTextureRect() { + drawTexture(_draw_rect.left, _draw_rect.top, + _draw_rect.width(), _draw_rect.height()); + } + + inline void drawTextureOrigin() { + drawTexture(0, 0, _surface.w, _surface.h); + } + + inline GLuint width() const { + return _surface.w; + } + + inline GLuint height() const { + return _surface.h; + } + + inline uint16 pitch() const { + return _surface.pitch; + } + + inline bool isEmpty() const { + return _surface.w == 0 || _surface.h == 0; + } + + inline const Graphics::Surface *surface_const() const { + return &_surface; + } + + inline Graphics::Surface *surface() { + setDirty(); + return &_surface; + } + + virtual const byte *palette_const() const { + return 0; + }; + + virtual byte *palette() { + return 0; + }; + + inline bool hasPalette() const { + return _palettePixelFormat.bytesPerPixel > 0; + } + + inline bool dirty() const { + return _all_dirty || !_dirty_rect.isEmpty(); + } + + virtual const Graphics::PixelFormat &getPixelFormat() const; + + inline const Graphics::PixelFormat &getPalettePixelFormat() const { + return _palettePixelFormat; + } + +protected: + inline void setDirty() { + _all_dirty = true; + } + + inline void clearDirty() { + _all_dirty = false; + _dirty_rect.top = 0; + _dirty_rect.left = 0; + _dirty_rect.bottom = 0; + _dirty_rect.right = 0; + } + + inline void setDirtyRect(const Common::Rect& r) { + if (!_all_dirty) { + if (_dirty_rect.isEmpty()) + _dirty_rect = r; + else + _dirty_rect.extend(r); + } + } + + GLenum _glFormat; + GLenum _glType; + GLint _glFilter; + + GLuint _texture_name; + Graphics::Surface _surface; + GLuint _texture_width; + GLuint _texture_height; + + Common::Rect _draw_rect; + + bool _all_dirty; + Common::Rect _dirty_rect; + + Graphics::PixelFormat _pixelFormat; + Graphics::PixelFormat _palettePixelFormat; +}; + +class GLESTexture : public GLESBaseTexture { +protected: + GLESTexture(GLenum glFormat, GLenum glType, + Graphics::PixelFormat pixelFormat); + +public: + virtual ~GLESTexture(); + + virtual void allocBuffer(GLuint w, GLuint h); + + virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, + const void *buf, int pitch_buf); + virtual void fillBuffer(uint32 color); + + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + +protected: + byte *_pixels; + byte *_buf; +}; + +// RGBA4444 texture +class GLES4444Texture : public GLESTexture { +public: + GLES4444Texture(); + virtual ~GLES4444Texture(); + + static Graphics::PixelFormat pixelFormat() { + return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0); + } +}; + +// RGBA5551 texture +class GLES5551Texture : public GLESTexture { +public: + GLES5551Texture(); + virtual ~GLES5551Texture(); + + static inline Graphics::PixelFormat pixelFormat() { + return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0); + } +}; + +// RGB565 texture +class GLES565Texture : public GLESTexture { +public: + GLES565Texture(); + virtual ~GLES565Texture(); + + static inline Graphics::PixelFormat pixelFormat() { + return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); + } +}; + +class GLESFakePaletteTexture : public GLESBaseTexture { +protected: + GLESFakePaletteTexture(GLenum glFormat, GLenum glType, + Graphics::PixelFormat pixelFormat); + +public: + virtual ~GLESFakePaletteTexture(); + + virtual void allocBuffer(GLuint w, GLuint h); + virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, + const void *buf, int pitch_buf); + virtual void fillBuffer(uint32 color); + + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + + virtual const byte *palette_const() const { + return (byte *)_palette; + }; + + virtual byte *palette() { + setDirty(); + return (byte *)_palette; + }; + + virtual const Graphics::PixelFormat &getPixelFormat() const; + +protected: + Graphics::PixelFormat _fake_format; + uint16 *_palette; + byte *_pixels; + uint16 *_buf; +}; + +class GLESFakePalette565Texture : public GLESFakePaletteTexture { +public: + GLESFakePalette565Texture(); + virtual ~GLESFakePalette565Texture(); +}; + +class GLESFakePalette5551Texture : public GLESFakePaletteTexture { +public: + GLESFakePalette5551Texture(); + virtual ~GLESFakePalette5551Texture(); +}; + +#endif +#endif + diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp deleted file mode 100644 index f8427c2ac8..0000000000 --- a/backends/platform/android/video.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#if defined(__ANDROID__) - -#include "base/main.h" -#include "graphics/surface.h" - -#include "common/rect.h" -#include "common/array.h" -#include "common/util.h" -#include "common/tokenizer.h" - -#include "backends/platform/android/android.h" -#include "backends/platform/android/video.h" - -// Unfortunately, Android devices are too varied to make broad assumptions :/ -#define TEXSUBIMAGE_IS_EXPENSIVE 0 - -// Supported GL extensions -static bool npot_supported = false; -#ifdef GL_OES_draw_texture -static bool draw_tex_supported = false; -#endif - -static inline GLfixed xdiv(int numerator, int denominator) { - assert(numerator < (1 << 16)); - return (numerator << 16) / denominator; -} - -template <class T> -static T nextHigher2(T k) { - if (k == 0) - return 1; - --k; - - for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1) - k = k | k >> i; - - return k + 1; -} - -void GLESTexture::initGLExtensions() { - const char *ext_string = - reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)); - - LOGI("Extensions: %s", ext_string); - - Common::StringTokenizer tokenizer(ext_string, " "); - while (!tokenizer.empty()) { - Common::String token = tokenizer.nextToken(); - - if (token == "GL_ARB_texture_non_power_of_two") - npot_supported = true; - -#ifdef GL_OES_draw_texture - if (token == "GL_OES_draw_texture") - draw_tex_supported = true; -#endif - } -} - -GLESTexture::GLESTexture() : - _texture_width(0), - _texture_height(0), - _all_dirty(true) -{ - GLCALL(glGenTextures(1, &_texture_name)); - - // This all gets reset later in allocBuffer: - _surface.w = 0; - _surface.h = 0; - _surface.pitch = _texture_width; - _surface.pixels = 0; - _surface.bytesPerPixel = 0; -} - -GLESTexture::~GLESTexture() { - debug("Destroying texture %u", _texture_name); - GLCALL(glDeleteTextures(1, &_texture_name)); -} - -void GLESTexture::reinitGL() { - GLCALL(glDeleteTextures(1, &_texture_name)); - GLCALL(glGenTextures(1, &_texture_name)); - - // bypass allocBuffer() shortcut to reinit the texture properly - _texture_width = 0; - _texture_height = 0; - - allocBuffer(_surface.w, _surface.h); - setDirty(); -} - -void GLESTexture::allocBuffer(GLuint w, GLuint h) { - int bpp = bytesPerPixel(); - _surface.w = w; - _surface.h = h; - _surface.bytesPerPixel = bpp; - - // Already allocated a sufficiently large buffer? - if (w <= _texture_width && h <= _texture_height) - return; - - if (npot_supported) { - _texture_width = _surface.w; - _texture_height = _surface.h; - } else { - _texture_width = nextHigher2(_surface.w); - _texture_height = nextHigher2(_surface.h); - } - - _surface.pitch = _texture_width * bpp; - - // Allocate room for the texture now, but pixel data gets uploaded - // later (perhaps with multiple TexSubImage2D operations). - GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); - GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, glFormat(), - _texture_width, _texture_height, - 0, glFormat(), glType(), 0)); -} - -void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, - const void *buf, int pitch) { - ENTER("%u, %u, %u, %u, %p, %d", x, y, w, h, buf, pitch); - - GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); - GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); - - setDirtyRect(Common::Rect(x, y, x+w, y+h)); - - if (static_cast<int>(w) * bytesPerPixel() == pitch) { - GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, - glFormat(), glType(), buf)); - } else { - // GLES removed the ability to specify pitch, so we - // have to do this ourselves. - if (h == 0) - return; - -#if TEXSUBIMAGE_IS_EXPENSIVE - byte tmpbuf[w * h * bytesPerPixel()]; - const byte *src = static_cast<const byte *>(buf); - byte *dst = tmpbuf; - GLuint count = h; - - do { - memcpy(dst, src, w * bytesPerPixel()); - dst += w * bytesPerPixel(); - src += pitch; - } while (--count); - - GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, - glFormat(), glType(), tmpbuf)); -#else - // This version avoids the intermediate copy at the expense of - // repeat glTexSubImage2D calls. On some devices this is worse. - const byte *src = static_cast<const byte *>(buf); - do { - GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, - w, 1, glFormat(), glType(), src)); - ++y; - src += pitch; - } while (--h); -#endif - } -} - -void GLESTexture::fillBuffer(byte x) { - int rowbytes = _surface.w * bytesPerPixel(); - byte tmpbuf[_surface.h * rowbytes]; - memset(tmpbuf, x, _surface.h * rowbytes); - updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes); -} - -void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { - GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); - -#ifdef GL_OES_draw_texture - // Great extension, but only works under specific conditions. - // Still a work-in-progress - disabled for now. - if (false && draw_tex_supported && paletteSize() == 0) { - //GLCALL(glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); - const GLint crop[4] = { 0, _surface.h, _surface.w, -_surface.h }; - - GLCALL(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop)); - - // Android GLES bug? - GLCALL(glColor4ub(0xff, 0xff, 0xff, 0xff)); - - GLCALL(glDrawTexiOES(x, y, 0, w, h)); - } else -#endif - { - const GLfixed tex_width = xdiv(_surface.w, _texture_width); - const GLfixed tex_height = xdiv(_surface.h, _texture_height); - const GLfixed texcoords[] = { - 0, 0, - tex_width, 0, - 0, tex_height, - tex_width, tex_height, - }; - - GLCALL(glTexCoordPointer(2, GL_FIXED, 0, texcoords)); - - const GLshort vertices[] = { - x, y, - x + w, y, - x, y + h, - x + w, y + h, - }; - - GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices)); - - assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords)); - GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2)); - } - - _all_dirty = false; - _dirty_rect = Common::Rect(); -} - -GLESPaletteTexture::GLESPaletteTexture() : - GLESTexture(), - _texture(0) -{ -} - -GLESPaletteTexture::~GLESPaletteTexture() { - delete[] _texture; -} - -void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) { - int bpp = bytesPerPixel(); - _surface.w = w; - _surface.h = h; - _surface.bytesPerPixel = bpp; - - // Already allocated a sufficiently large buffer? - if (w <= _texture_width && h <= _texture_height) - return; - - if (npot_supported) { - _texture_width = _surface.w; - _texture_height = _surface.h; - } else { - _texture_width = nextHigher2(_surface.w); - _texture_height = nextHigher2(_surface.h); - } - _surface.pitch = _texture_width * bpp; - - // Texture gets uploaded later (from drawTexture()) - - byte *new_buffer = new byte[paletteSize() + - _texture_width * _texture_height * bytesPerPixel()]; - if (_texture) { - // preserve palette - memcpy(new_buffer, _texture, paletteSize()); - delete[] _texture; - } - - _texture = new_buffer; - _surface.pixels = _texture + paletteSize(); -} - -void GLESPaletteTexture::fillBuffer(byte x) { - assert(_surface.pixels); - memset(_surface.pixels, x, _surface.pitch * _surface.h); - setDirty(); -} - -void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y, - GLuint w, GLuint h, - const void *buf, int pitch) { - _all_dirty = true; - - const byte * src = static_cast<const byte *>(buf); - byte *dst = static_cast<byte *>(_surface.getBasePtr(x, y)); - - do { - memcpy(dst, src, w * bytesPerPixel()); - dst += _surface.pitch; - src += pitch; - } while (--h); -} - -void GLESPaletteTexture::uploadTexture() const { - const size_t texture_size = - paletteSize() + _texture_width * _texture_height * bytesPerPixel(); - - GLCALL(glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(), - _texture_width, _texture_height, - 0, texture_size, _texture)); -} - -void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { - if (_all_dirty) { - GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - uploadTexture(); - _all_dirty = false; - } - - GLESTexture::drawTexture(x, y, w, h); -} - -#endif - diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h deleted file mode 100644 index da42ea876d..0000000000 --- a/backends/platform/android/video.h +++ /dev/null @@ -1,209 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#if defined(__ANDROID__) - -#include <GLES/gl.h> - -#include "graphics/surface.h" - -#include "common/rect.h" -#include "common/array.h" - -class GLESTexture { -public: - static void initGLExtensions(); - - GLESTexture(); - virtual ~GLESTexture(); - - virtual void reinitGL(); - virtual void allocBuffer(GLuint width, GLuint height); - - virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, - const void *buf, int pitch); - virtual void fillBuffer(byte x); - - virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); - - inline GLuint width() const { - return _surface.w; - } - - inline GLuint height() const { - return _surface.h; - } - - inline GLuint texture_name() const { - return _texture_name; - } - - inline const Graphics::Surface *surface_const() const { - return &_surface; - } - - inline Graphics::Surface *surface() { - setDirty(); - return &_surface; - } - - inline bool dirty() const { - return _all_dirty || !_dirty_rect.isEmpty(); - } - - inline void drawTexture() { - drawTexture(0, 0, _surface.w, _surface.h); - } - -protected: - virtual byte bytesPerPixel() const = 0; - virtual GLenum glFormat() const = 0; - virtual GLenum glType() const = 0; - - virtual size_t paletteSize() const { - return 0; - } - - inline void setDirty() { - _all_dirty = true; - _dirty_rect = Common::Rect(); - } - - inline void setDirtyRect(const Common::Rect& r) { - if (!_all_dirty) { - if (_dirty_rect.isEmpty()) - _dirty_rect = r; - else - _dirty_rect.extend(r); - } - } - - GLuint _texture_name; - Graphics::Surface _surface; - GLuint _texture_width; - GLuint _texture_height; - bool _all_dirty; - - // Covers dirty area - Common::Rect _dirty_rect; -}; - -// RGBA4444 texture -class GLES4444Texture : public GLESTexture { -protected: - virtual byte bytesPerPixel() const { - return 2; - } - - virtual GLenum glFormat() const { - return GL_RGBA; - } - - virtual GLenum glType() const { - return GL_UNSIGNED_SHORT_4_4_4_4; - } -}; - -// RGB565 texture -class GLES565Texture : public GLESTexture { -protected: - virtual byte bytesPerPixel() const { - return 2; - } - - virtual GLenum glFormat() const { - return GL_RGB; - } - - virtual GLenum glType() const { - return GL_UNSIGNED_SHORT_5_6_5; - } -}; - -// RGB888 256-entry paletted texture -class GLESPaletteTexture : public GLESTexture { -public: - GLESPaletteTexture(); - virtual ~GLESPaletteTexture(); - - virtual void allocBuffer(GLuint width, GLuint height); - virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, - const void *buf, int pitch); - virtual void fillBuffer(byte x); - - virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); - - inline void drawTexture() { - drawTexture(0, 0, _surface.w, _surface.h); - } - - inline const byte *palette_const() const { - return _texture; - }; - - inline byte *palette() { - setDirty(); - return _texture; - }; - -protected: - virtual byte bytesPerPixel() const { - return 1; - } - - virtual GLenum glFormat() const { - return GL_RGB; - } - - virtual GLenum glType() const { - return GL_PALETTE8_RGB8_OES; - } - - virtual size_t paletteSize() const { - return 256 * 3; - } - - void uploadTexture() const; - - byte *_texture; -}; - -// RGBA8888 256-entry paletted texture -class GLESPaletteATexture : public GLESPaletteTexture { -protected: - virtual GLenum glFormat() const { - return GL_RGBA; - } - - virtual GLenum glType() const { - return GL_PALETTE8_RGBA8_OES; - } - - virtual size_t paletteSize() const { - return 256 * 4; - } -}; - -#endif diff --git a/backends/platform/dc/Makefile b/backends/platform/dc/Makefile index 637f474b4b..11d9421a0a 100644 --- a/backends/platform/dc/Makefile +++ b/backends/platform/dc/Makefile @@ -65,7 +65,7 @@ ENABLE_TOUCHE = $(ENABLED) ENABLE_TUCKER = $(ENABLED) OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \ - label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o + label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o plugins.o MODULE_DIRS += ./ diff --git a/backends/platform/dc/dc-fs.cpp b/backends/platform/dc/dc-fs.cpp index e21a12fa33..a024b5d70d 100644 --- a/backends/platform/dc/dc-fs.cpp +++ b/backends/platform/dc/dc-fs.cpp @@ -22,6 +22,8 @@ * $Id$ */ +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + #include "dc.h" #include "backends/fs/abstract-fs.h" #include "backends/fs/stdiostream.h" diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index 76c4b8cfd2..060eff2b48 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -26,11 +26,15 @@ #include "backends/base-backend.h" #include <graphics/surface.h> #include <graphics/colormasks.h> +#include <graphics/palette.h> #include <ronin/soundcommon.h> #include "backends/timer/default/default-timer.h" #include "backends/audiocd/default/default-audiocd.h" #include "backends/fs/fs-factory.h" #include "audio/mixer_intern.h" +#ifdef DYNAMIC_MODULES +#include "backends/plugins/dynamic-plugin.h" +#endif #define NUM_BUFFERS 4 #define SOUND_BUFFER_SHIFT 3 @@ -69,7 +73,11 @@ class DCCDManager : public DefaultAudioCDManager { void updateCD(); }; -class OSystem_Dreamcast : private DCHardware, public BaseBackend, public PaletteManager, public FilesystemFactory { +class OSystem_Dreamcast : private DCHardware, public BaseBackend, public PaletteManager, public FilesystemFactory +#ifdef DYNAMIC_MODULES + , public FilePluginProvider +#endif + { public: OSystem_Dreamcast(); @@ -250,6 +258,14 @@ public: void logMessage(LogMessageType::Type type, const char *message); Common::String getSystemLanguage() const; + +#ifdef DYNAMIC_MODULES + class DCPlugin; + + protected: + Plugin* createPlugin(const Common::FSNode &node) const; + bool isPluginFilename(const Common::FSNode &node) const; +#endif }; diff --git a/backends/platform/dc/dcmain.cpp b/backends/platform/dc/dcmain.cpp index bbd4f994f7..a3a1200178 100644 --- a/backends/platform/dc/dcmain.cpp +++ b/backends/platform/dc/dcmain.cpp @@ -23,6 +23,11 @@ * */ +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <common/scummsys.h> #include <engines/engine.h> #include <base/main.h> @@ -33,7 +38,6 @@ #include <common/config-manager.h> #include <common/memstream.h> -#include "backends/plugins/dc/dc-provider.h" #include "audio/mixer_intern.h" @@ -336,7 +340,7 @@ int main() g_system = &osys_dc; #ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new DCPluginProvider()); + PluginManager::instance().addPluginProvider(&osys_dc); #endif scummvm_main(argc, argv); diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp index b297022775..78fa2182dc 100644 --- a/backends/platform/dc/display.cpp +++ b/backends/platform/dc/display.cpp @@ -720,7 +720,7 @@ Graphics::Surface *OSystem_Dreamcast::lockScreen() _framebuffer.w = _screen_w; _framebuffer.h = _screen_h; _framebuffer.pitch = SCREEN_W*2; - _framebuffer.bytesPerPixel = (_screenFormat == 0? 1 : 2); + _framebuffer.format = screenFormats[_screenFormat]; return &_framebuffer; } diff --git a/backends/platform/dc/dreamcast.mk b/backends/platform/dc/dreamcast.mk index 8651a2936c..666e03eece 100644 --- a/backends/platform/dc/dreamcast.mk +++ b/backends/platform/dc/dreamcast.mk @@ -35,3 +35,7 @@ ip.txt : $(srcdir)/backends/platform/dc/ip.txt.in ver="V$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH)"; fi; \ sed -e 's/[@]VERSION[@]/'"$$ver"/ -e 's/[@]DATE[@]/$(shell date '+%Y%m%d')/' < $< > $@ + +dcdist : dist + mkdir -p dcdist/scummvm + cp scummvm.elf SCUMMVM.BIN IP.BIN *.PLG dcdist/scummvm/ diff --git a/backends/platform/dc/module.mk b/backends/platform/dc/module.mk index c52ca1a474..9ab287c080 100644 --- a/backends/platform/dc/module.mk +++ b/backends/platform/dc/module.mk @@ -1,7 +1,7 @@ MODULE := backends/platform/dc MODULE_OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \ - label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o + label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o plugins.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/plugins/dc/dc-provider.cpp b/backends/platform/dc/plugins.cpp index 86ef68828c..44b8960513 100644 --- a/backends/plugins/dc/dc-provider.cpp +++ b/backends/platform/dc/plugins.cpp @@ -25,16 +25,50 @@ #include "common/scummsys.h" -#if defined(DYNAMIC_MODULES) && defined(__DC__) +#if defined(DYNAMIC_MODULES) -#include "backends/plugins/dc/dc-provider.h" #include "backends/plugins/dynamic-plugin.h" #include "common/fs.h" #include "dcloader.h" +extern void draw_solid_quad(float x1, float y1, float x2, float y2, + int c0, int c1, int c2, int c3); + +static void drawPluginProgress(const Common::String &filename) +{ + ta_sync(); + void *mark = ta_txmark(); + const char *fn = filename.c_str(); + Label lab1, lab2, lab3; + char buf[32]; + unsigned memleft = 0x8cf00000-((unsigned)sbrk(0)); + float ffree = memleft*(1.0/(16<<20)); + int fcol = (memleft < (1<<20)? 0xffff0000: + (memleft < (4<<20)? 0xffffff00: 0xff00ff00)); + snprintf(buf, sizeof(buf), "%dK free memory", memleft>>10); + if (fn[0] == '/') fn++; + lab1.create_texture("Loading plugins, please wait..."); + lab2.create_texture(fn); + lab3.create_texture(buf); + ta_begin_frame(); + draw_solid_quad(80.0, 270.0, 560.0, 300.0, + 0xff808080, 0xff808080, 0xff808080, 0xff808080); + draw_solid_quad(85.0, 275.0, 555.0, 295.0, + 0xff202020, 0xff202020, 0xff202020, 0xff202020); + draw_solid_quad(85.0, 275.0, 85.0+470.0*ffree, 295.0, + fcol, fcol, fcol, fcol); + ta_commit_end(); + lab1.draw(100.0, 150.0, 0xffffffff); + lab2.draw(100.0, 190.0, 0xffaaffaa); + lab3.draw(100.0, 230.0, 0xffffffff); + ta_commit_frame(); + ta_sync(); + ta_txrelease(mark); +} + -class DCPlugin : public DynamicPlugin { +class OSystem_Dreamcast::DCPlugin : public DynamicPlugin { protected: void *_dlHandle; @@ -59,6 +93,7 @@ public: bool loadPlugin() { assert(!_dlHandle); + drawPluginProgress(_filename); _dlHandle = dlopen(_filename.c_str(), RTLD_LAZY); if (!_dlHandle) { @@ -85,11 +120,11 @@ public: }; -Plugin* DCPluginProvider::createPlugin(const Common::FSNode &node) const { +Plugin* OSystem_Dreamcast::createPlugin(const Common::FSNode &node) const { return new DCPlugin(node.getPath()); } -bool DCPluginProvider::isPluginFilename(const Common::FSNode &node) const { +bool OSystem_Dreamcast::isPluginFilename(const Common::FSNode &node) const { // Check the plugin suffix Common::String filename = node.getName(); if (!filename.hasSuffix(".PLG")) @@ -98,4 +133,4 @@ bool DCPluginProvider::isPluginFilename(const Common::FSNode &node) const { return true; } -#endif // defined(DYNAMIC_MODULES) && defined(__DC__) +#endif // defined(DYNAMIC_MODULES) diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 8fd12d66bf..77f34394a1 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_chdir + #include <common/scummsys.h> #include <engines/engine.h> #include <engines/metaengine.h> diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp index 6c8289684f..63e345efbe 100644 --- a/backends/platform/dc/vmsave.cpp +++ b/backends/platform/dc/vmsave.cpp @@ -23,6 +23,11 @@ * */ +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +#define FORBIDDEN_SYMBOL_EXCEPTION_fprintf + #include <common/scummsys.h> #include "engines/engine.h" #include "dc.h" diff --git a/backends/platform/dingux/main.cpp b/backends/platform/dingux/main.cpp index c5dccc5f50..cf25e1cb42 100644 --- a/backends/platform/dingux/main.cpp +++ b/backends/platform/dingux/main.cpp @@ -30,8 +30,6 @@ #if defined(DINGUX) -#include <unistd.h> - int main(int argc, char* argv[]) { g_system = new OSystem_SDL_Dingux(); diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c index 7f0757ef53..698590418c 100644 --- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c +++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c @@ -18,6 +18,9 @@ //--------------------------------------------------------------- // Includes +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + #include "gba_nds_fat.h" #include "disc_io.h" #include <string.h> diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index 3ad92b4355..462990cb32 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -20,6 +20,9 @@ */ +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + #include "common/scummsys.h" #include "common/system.h" @@ -243,7 +246,7 @@ void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) { } bool OSystem_DS::grabRawScreen(Graphics::Surface *surf) { - surf->create(DS::getGameWidth(), DS::getGameHeight(), 1); + surf->create(DS::getGameWidth(), DS::getGameHeight(), Graphics::PixelFormat::createFormatCLUT8()); // Ensure we copy using 16 bit quantities due to limitation of VRAM addressing @@ -259,13 +262,13 @@ bool OSystem_DS::grabRawScreen(Graphics::Surface *surf) { return true; } -void OSystem_DS::grabPalette(unsigned char *colours, uint start, uint num) { +void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) { // consolePrintf("Grabpalette"); for (unsigned int r = start; r < start + num; r++) { - *colours++ = (BG_PALETTE[r] & 0x001F) << 3; - *colours++ = (BG_PALETTE[r] & 0x03E0) >> 5 << 3; - *colours++ = (BG_PALETTE[r] & 0x7C00) >> 10 << 3; + *colors++ = (BG_PALETTE[r] & 0x001F) << 3; + *colors++ = (BG_PALETTE[r] & 0x03E0) >> 5 << 3; + *colors++ = (BG_PALETTE[r] & 0x7C00) >> 10 << 3; } } @@ -756,7 +759,7 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() { _framebuffer.w = DS::getGameWidth(); _framebuffer.h = DS::getGameHeight(); _framebuffer.pitch = DS::getGameWidth(); - _framebuffer.bytesPerPixel = 1; + _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); } else { @@ -781,7 +784,7 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() { _framebuffer.w = width; _framebuffer.h = height; _framebuffer.pitch = width; - _framebuffer.bytesPerPixel = 1; + _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); } @@ -849,16 +852,16 @@ Common::WriteStream *OSystem_DS::createConfigWriteStream() { return file.createWriteStream(); } -u16 OSystem_DS::applyGamma(u16 colour) { +u16 OSystem_DS::applyGamma(u16 color) { // Attempt to do gamma correction (or something like it) to palette entries // to improve the contrast of the image on the original DS screen. - // Split the colour into it's component channels - int r = colour & 0x001F; - int g = (colour & 0x03E0) >> 5; - int b = (colour & 0x7C00) >> 10; + // Split the color into it's component channels + int r = color & 0x001F; + int g = (color & 0x03E0) >> 5; + int b = (color & 0x7C00) >> 10; - // Caluclate the scaling factor for this colour based on it's brightness + // Caluclate the scaling factor for this color based on it's brightness int scale = ((23 - ((r + g + b) >> 2)) * _gammaValue) >> 3; // Scale the three components by the scaling factor, with clamping @@ -871,7 +874,7 @@ u16 OSystem_DS::applyGamma(u16 colour) { b = b + ((b * scale) >> 4); if (b > 31) b = 31; - // Stick them back together into a 555 colour value + // Stick them back together into a 555 color value return 0x8000 | r | (g << 5) | (b << 10); } diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 7feed7541f..b745b4dc6e 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -36,6 +36,7 @@ #include "audio/mixer_intern.h" #include "graphics/surface.h" #include "graphics/colormasks.h" +#include "graphics/palette.h" class OSystem_DS : public BaseBackend, public PaletteManager { protected: @@ -183,7 +184,7 @@ public: Common::WriteStream *createConfigWriteStream(); Common::SeekableReadStream *createConfigReadStream(); - u16 applyGamma(u16 colour); + u16 applyGamma(u16 color); void setGammaValue(int gamma) { _gammaValue = gamma; } void engineDone(); diff --git a/backends/platform/ds/ds.mk b/backends/platform/ds/ds.mk index a9ed3e0096..654475e1f3 100644 --- a/backends/platform/ds/ds.mk +++ b/backends/platform/ds/ds.mk @@ -170,10 +170,10 @@ dsclean: # HACK/FIXME: C compiler, for cartreset.c -- we should switch this to use CXX # as soon as possible. -CC := $(DEVKITARM)/bin/arm-eabi-gcc +CC := $(DEVKITPRO)/devkitARM/bin/arm-eabi-gcc # HACK/TODO: Pointer to objcopy. This should really be set by configure -OBJCOPY := $(DEVKITARM)/bin/arm-eabi-objcopy +OBJCOPY := $(DEVKITPRO)/devkitARM/bin/arm-eabi-objcopy # # Set various flags diff --git a/backends/platform/ds/makefile b/backends/platform/ds/makefile index 58d6fd4c02..e24a36ef81 100644 --- a/backends/platform/ds/makefile +++ b/backends/platform/ds/makefile @@ -3,7 +3,7 @@ -export PATH := $(DEVKITARM)/bin:$(PATH) +export PATH := $(DEVKITPRO)/devkitARM/bin:$(PATH) export portdir = $(CURDIR)/arm9 export srcdir = $(CURDIR)/../../.. diff --git a/backends/platform/gp2x/build/README-GP2X b/backends/platform/gp2x/build/README-GP2X deleted file mode 100644 index 3c6591d369..0000000000 --- a/backends/platform/gp2x/build/README-GP2X +++ /dev/null @@ -1,54 +0,0 @@ -ScummVM - GP2X SPECIFIC README ------------------------------------------------------------------------- - -Contents: - - * About the backend/port <#About_the_backendport> - * Supported audio options <#Supported_audio_options> - * Credits <#Credits> - ------------------------------------------------------------------------- - -Please refer to the: - -GP2X/GP2XWiz ScummVM Forum: <http://forums.scummvm.org/viewforum.php?f=14> -WiKi: <http://wiki.scummvm.org/index.php/GP2X> - -for the most current information on the port and any updates to this -documentation. - -The wiki includes detailed instructions on how to use the port and -control information. - ------------------------------------------------------------------------- -About the backend/port - -This is the readme for the official GP2X ScummVM backend (also known as -the GP2X port). - -This is an SVN test release of ScummVM for the GP2X, it would be -appreciated if this SVN test distribution was not mirrored and that -people be directed to http://scummvm.distant-earth.com/ instead for -updated SVN builds. - -Full supported official releases of the GP2X ScummVM backend are made in -line with main official releases and are avalalble from the ScummVM -downloads page <http://www.scummvm.org/downloads.php>. - ------------------------------------------------------------------------- -Supported audio options - -Raw audio. -MP3 audio. -OGG Vorbis audio. - -FLAC audio is currently unsupported. - -For best results use uncompressed audio in games. - ------------------------------------------------------------------------- -Credits - -Core ScummVM code (c) The ScummVM Team -Portions of the GP2X backend (c) John Willis -Detailed (c) information can be found within the source code diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh deleted file mode 100755 index d17f8bd831..0000000000 --- a/backends/platform/gp2x/build/bundle.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -echo Quick script to make building a distribution of the GP2X port more consistent. - -cd ../../../.. - -echo Building ScummVM for GP2X Wiz. - -make gp2x-bundle - diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h index 4d2a9c33cc..2a06cab788 100644 --- a/backends/platform/gp2x/gp2x-common.h +++ b/backends/platform/gp2x/gp2x-common.h @@ -26,7 +26,11 @@ #ifndef PLATFORM_SDL_GP2X_H #define PLATFORM_SDL_GP2X_H +#include "backends/base-backend.h" +#include "backends/platform/sdl/sdl.h" #include "backends/platform/sdl/posix/posix.h" +#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" +#include "backends/events/gp2xsdl/gp2xsdl-events.h" #ifndef PATH_MAX #define PATH_MAX 255 @@ -34,12 +38,15 @@ class OSystem_GP2X : public OSystem_POSIX { public: - virtual void initBackend(); - virtual void quit(); - virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); + OSystem_GP2X() {} + + void initBackend(); + void quit(); + void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); + void initSDL(); protected: - virtual void initSDL(); + }; #endif diff --git a/backends/platform/gp2x/gp2x-main.cpp b/backends/platform/gp2x/gp2x-main.cpp index a194accd77..f1ee5ed5f3 100644 --- a/backends/platform/gp2x/gp2x-main.cpp +++ b/backends/platform/gp2x/gp2x-main.cpp @@ -18,15 +18,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #include "backends/platform/gp2x/gp2x-common.h" -#include "backends/plugins/posix/posix-provider.h" +#include "backends/plugins/sdl/sdl-provider.h" #include "base/main.h" +#if defined(GP2X) int main(int argc, char *argv[]) { // Create our OSystem instance @@ -37,7 +35,7 @@ int main(int argc, char *argv[]) { ((OSystem_GP2X *)g_system)->init(); #ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); #endif // Invoke the actual ScummVM main entry point: @@ -48,3 +46,5 @@ int main(int argc, char *argv[]) { return res; } + +#endif diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 8ae54d679c..4cdb4cd0d5 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ /* @@ -31,12 +28,11 @@ // Disable symbol overrides so that we can use system headers. #define FORBIDDEN_SYMBOL_ALLOW_ALL +#include "backends/platform/sdl/sdl-sys.h" #include "backends/platform/gp2x/gp2x-common.h" #include "backends/platform/gp2x/gp2x-hw.h" #include "backends/platform/gp2x/gp2x-mem.h" -#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" -#include "backends/events/gp2xsdl/gp2xsdl-events.h" #include "backends/saves/default/default-saves.h" #include "common/config-manager.h" @@ -143,7 +139,7 @@ void OSystem_GP2X::initBackend() { if (_graphicsManager == 0) _graphicsManager = new GP2XSdlGraphicsManager(_eventSource); - // Call parent implementation of this method + /* Pass to POSIX method to do the heavy lifting */ OSystem_POSIX::initBackend(); } diff --git a/backends/platform/gph/caanoo/build.sh b/backends/platform/gph/build/caanoo-build.sh index 8000d2595d..8000d2595d 100755..100644 --- a/backends/platform/gph/caanoo/build.sh +++ b/backends/platform/gph/build/caanoo-build.sh diff --git a/backends/platform/gph/caanoo/bundle-debug.sh b/backends/platform/gph/build/caanoo-bundle-debug.sh index 2d5cefe80e..2d5cefe80e 100755..100644 --- a/backends/platform/gph/caanoo/bundle-debug.sh +++ b/backends/platform/gph/build/caanoo-bundle-debug.sh diff --git a/backends/platform/gph/caanoo/bundle.sh b/backends/platform/gph/build/caanoo-bundle.sh index 76fd31cec6..76fd31cec6 100755..100644 --- a/backends/platform/gph/caanoo/bundle.sh +++ b/backends/platform/gph/build/caanoo-bundle.sh diff --git a/backends/platform/gph/caanoo/config-alleng.sh b/backends/platform/gph/build/caanoo-config-alleng.sh index 97fed942fa..97fed942fa 100755..100644 --- a/backends/platform/gph/caanoo/config-alleng.sh +++ b/backends/platform/gph/build/caanoo-config-alleng.sh diff --git a/backends/platform/gph/caanoo/config.sh b/backends/platform/gph/build/caanoo-config.sh index 11d597481a..11d597481a 100755..100644 --- a/backends/platform/gph/caanoo/config.sh +++ b/backends/platform/gph/build/caanoo-config.sh diff --git a/backends/platform/gph/build/clean.sh b/backends/platform/gph/build/clean.sh index 5ec1b9e62c..6d58b7a975 100755 --- a/backends/platform/gph/build/clean.sh +++ b/backends/platform/gph/build/clean.sh @@ -4,5 +4,5 @@ echo Quick script to make building all the time less painful. cd ../../../.. -echo Cleaning ScummVM for the GP2X Wiz. +echo Cleaning ScummVM for the GPH devices. make clean diff --git a/backends/platform/gp2x/build/build.sh b/backends/platform/gph/build/gp2x-build.sh index 1ea77f4937..1ea77f4937 100755..100644 --- a/backends/platform/gp2x/build/build.sh +++ b/backends/platform/gph/build/gp2x-build.sh diff --git a/backends/platform/gph/build/gp2x-bundle.sh b/backends/platform/gph/build/gp2x-bundle.sh new file mode 100644 index 0000000000..c4fe63ed9e --- /dev/null +++ b/backends/platform/gph/build/gp2x-bundle.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +echo Quick script to make building a distribution of the GP2X port more consistent. + +# Set the paths up here to support the build. + +export PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin:$PATH +export PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin:$PATH +export CXX=arm-open2x-linux-g++ +export CC=arm-open2x-linux-gcc +export CXXFLAGS=-march=armv4t +export LDFLAGS=-static +export ASFLAGS=-mfloat-abi=soft + +cd ../../../.. + +echo Building ScummVM for GP2X Wiz. + +make gp2x-bundle diff --git a/backends/platform/gp2x/build/config-alleng.sh b/backends/platform/gph/build/gp2x-config-alleng.sh index 4a3526d50c..4a3526d50c 100755..100644 --- a/backends/platform/gp2x/build/config-alleng.sh +++ b/backends/platform/gph/build/gp2x-config-alleng.sh diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gph/build/gp2x-config.sh index e0a1bf1209..9092b0b1ea 100755..100644 --- a/backends/platform/gp2x/build/config.sh +++ b/backends/platform/gph/build/gp2x-config.sh @@ -17,7 +17,7 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd +./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd --enable-plugins --default-dynamic # --disable-release --enable-debug # --enable-plugins --default-dynamic diff --git a/backends/platform/gph/build/build.sh b/backends/platform/gph/build/gp2xwiz-build.sh index 876c3e378a..876c3e378a 100755..100644 --- a/backends/platform/gph/build/build.sh +++ b/backends/platform/gph/build/gp2xwiz-build.sh diff --git a/backends/platform/gph/build/bundle-debug.sh b/backends/platform/gph/build/gp2xwiz-bundle-debug.sh index cd5145b31d..cd5145b31d 100755..100644 --- a/backends/platform/gph/build/bundle-debug.sh +++ b/backends/platform/gph/build/gp2xwiz-bundle-debug.sh diff --git a/backends/platform/gph/build/bundle.sh b/backends/platform/gph/build/gp2xwiz-bundle.sh index 579e2dc77b..579e2dc77b 100755..100644 --- a/backends/platform/gph/build/bundle.sh +++ b/backends/platform/gph/build/gp2xwiz-bundle.sh diff --git a/backends/platform/gph/build/config-alleng.sh b/backends/platform/gph/build/gp2xwiz-config-alleng.sh index 9ec8a09cd2..9ec8a09cd2 100755..100644 --- a/backends/platform/gph/build/config-alleng.sh +++ b/backends/platform/gph/build/gp2xwiz-config-alleng.sh diff --git a/backends/platform/gph/build/config.sh b/backends/platform/gph/build/gp2xwiz-config.sh index ac7c34ad12..ac7c34ad12 100755..100644 --- a/backends/platform/gph/build/config.sh +++ b/backends/platform/gph/build/gp2xwiz-config.sh diff --git a/backends/platform/gph/build/scummvm.png b/backends/platform/gph/build/scummvm.png Binary files differdeleted file mode 100644 index 128e59efc4..0000000000 --- a/backends/platform/gph/build/scummvm.png +++ /dev/null diff --git a/backends/platform/gph/caanoo-bundle.mk b/backends/platform/gph/caanoo-bundle.mk index b7b3c9e188..8aabca9028 100755 --- a/backends/platform/gph/caanoo-bundle.mk +++ b/backends/platform/gph/caanoo-bundle.mk @@ -14,11 +14,11 @@ caanoo-bundle: $(EXECUTABLE) echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR" - $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm.gpe $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/caanoo/scummvm.gpe $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/ @@ -45,11 +45,11 @@ caanoo-bundle-debug: $(EXECUTABLE) echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR" - $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/ diff --git a/backends/platform/gph/caanoo/clean.sh b/backends/platform/gph/caanoo/clean.sh deleted file mode 100755 index 5ec1b9e62c..0000000000 --- a/backends/platform/gph/caanoo/clean.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -echo Quick script to make building all the time less painful. - -cd ../../../.. - -echo Cleaning ScummVM for the GP2X Wiz. -make clean diff --git a/backends/platform/gph/build/scummvm-gdb.gpe b/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe index 63ce193ca8..63ce193ca8 100755..100644 --- a/backends/platform/gph/build/scummvm-gdb.gpe +++ b/backends/platform/gph/devices/caanoo/scummvm-gdb.gpe diff --git a/backends/platform/gph/caanoo/scummvm.gpe b/backends/platform/gph/devices/caanoo/scummvm.gpe index 37d0f65d18..37d0f65d18 100755..100644 --- a/backends/platform/gph/caanoo/scummvm.gpe +++ b/backends/platform/gph/devices/caanoo/scummvm.gpe diff --git a/backends/platform/gph/build/README-GPH b/backends/platform/gph/devices/common/README-GPH index 64b9fcb76b..ea196f6649 100644 --- a/backends/platform/gph/build/README-GPH +++ b/backends/platform/gph/devices/common/README-GPH @@ -1,4 +1,4 @@ -ScummVM - GPH SPECIFIC README +ScummVM - GPH DEVICE SPECIFIC README ------------------------------------------------------------------------ Contents: @@ -29,7 +29,7 @@ control information. About the backend/port This is the readme for the official GPH ScummVM backend (also known as -the GP2X port/GP2XWiz port and Caanoo port). +the GP2X port/GP2XWiz port or Caanoo port). This is an SVN test release of ScummVM for GPH devices, it would be appreciated if this SVN test distribution was not mirrored and that diff --git a/backends/platform/gph/build/scummvm.ini b/backends/platform/gph/devices/common/scummvm.ini index c9cce92379..c9cce92379 100644 --- a/backends/platform/gph/build/scummvm.ini +++ b/backends/platform/gph/devices/common/scummvm.ini diff --git a/backends/platform/gp2x/build/scummvm.png b/backends/platform/gph/devices/common/scummvm.png Binary files differindex 128e59efc4..128e59efc4 100644 --- a/backends/platform/gp2x/build/scummvm.png +++ b/backends/platform/gph/devices/common/scummvm.png diff --git a/backends/platform/gph/build/scummvmb.png b/backends/platform/gph/devices/common/scummvmb.png Binary files differindex 24a27bc0e1..24a27bc0e1 100644 --- a/backends/platform/gph/build/scummvmb.png +++ b/backends/platform/gph/devices/common/scummvmb.png diff --git a/backends/platform/gp2x/mmuhack/Makefile b/backends/platform/gph/devices/gp2x/mmuhack/Makefile index a35d5c2a98..a35d5c2a98 100644 --- a/backends/platform/gp2x/mmuhack/Makefile +++ b/backends/platform/gph/devices/gp2x/mmuhack/Makefile diff --git a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.h b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h index 520841ace7..520841ace7 100644 --- a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.h +++ b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.h diff --git a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.s b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s index 17628c156a..17628c156a 100644 --- a/backends/platform/gp2x/mmuhack/flush_uppermem_cache.s +++ b/backends/platform/gph/devices/gp2x/mmuhack/flush_uppermem_cache.s diff --git a/backends/platform/gp2x/mmuhack/mmuhack.c b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c index 7e27262e5f..7e27262e5f 100644 --- a/backends/platform/gp2x/mmuhack/mmuhack.c +++ b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.c diff --git a/backends/platform/gp2x/build/mmuhack.o b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o Binary files differindex 475f4a54ae..475f4a54ae 100644 --- a/backends/platform/gp2x/build/mmuhack.o +++ b/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o diff --git a/backends/platform/gp2x/mmuhack/readme.txt b/backends/platform/gph/devices/gp2x/mmuhack/readme.txt index bea49d7d6d..bea49d7d6d 100644 --- a/backends/platform/gp2x/mmuhack/readme.txt +++ b/backends/platform/gph/devices/gp2x/mmuhack/readme.txt diff --git a/backends/platform/gp2x/build/scummvm.gpe b/backends/platform/gph/devices/gp2x/scummvm.gpe index c6b051831c..e8983aa2ce 100755..100644 --- a/backends/platform/gp2x/build/scummvm.gpe +++ b/backends/platform/gph/devices/gp2x/scummvm.gpe @@ -3,6 +3,10 @@ # Remount SD with forced Sync, does this really work? mount -o sync,remount /dev/mmcsd/disc0/part1 /mnt/sd/ +# Export the location of any libs ScummVM depends on +# (to avoid installing to the NAND and overwriting the broken ones there). +export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH + # Run ScummVM, important this bit. ./scummvm.gph diff --git a/backends/platform/gph/caanoo/scummvm-gdb.gpe b/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe index 63ce193ca8..63ce193ca8 100755..100644 --- a/backends/platform/gph/caanoo/scummvm-gdb.gpe +++ b/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe diff --git a/backends/platform/gph/build/scummvm.gpe b/backends/platform/gph/devices/gp2xwiz/scummvm.gpe index 59ff562aeb..59ff562aeb 100755..100644 --- a/backends/platform/gph/build/scummvm.gpe +++ b/backends/platform/gph/devices/gp2xwiz/scummvm.gpe diff --git a/backends/platform/gp2x/gp2x-bundle.mk b/backends/platform/gph/gp2x-bundle.mk index 67d22d1889..810ff8b8f0 100755..100644 --- a/backends/platform/gp2x/gp2x-bundle.mk +++ b/backends/platform/gph/gp2x-bundle.mk @@ -1,18 +1,21 @@ # Special target to create bundles for the GP2X. bundle_name = release/scummvm-gp2x +f=$(shell which $(STRIP)) +libloc = $(shell dirname $(f)) gp2x-bundle: $(EXECUTABLE) $(MKDIR) "$(bundle_name)" $(MKDIR) "$(bundle_name)/saves" $(MKDIR) "$(bundle_name)/engine-data" + $(MKDIR) "$(bundle_name)/lib" echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR" - $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/ - $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/ - $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/ - $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/scummvm.gpe $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/ @@ -27,6 +30,8 @@ ifdef DYNAMIC_MODULES $(STRIP) $(bundle_name)/plugins/* endif + $(CP) $(libloc)/../arm-open2x-linux/lib/libdl.so $(bundle_name)/lib/libdl.so + tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 . rm -R ./$(bundle_name) @@ -37,10 +42,10 @@ gp2x-bundle-debug: $(EXECUTABLE) echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR" - $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/ - $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/ - $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/ - $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/scummvm.gpe $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/gp2x/mmuhack/mmuhack.o $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/ @@ -54,6 +59,8 @@ ifdef DYNAMIC_MODULES $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins" endif + $(CP) $(libloc)/../arm-open2x-linux/lib/libdl.so $(bundle_name)/lib/libdl.so + tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 . rm -R ./$(bundle_name) diff --git a/backends/platform/gph/gp2xwiz-bundle.mk b/backends/platform/gph/gp2xwiz-bundle.mk index df4cae7f4f..65e2952fde 100755 --- a/backends/platform/gph/gp2xwiz-bundle.mk +++ b/backends/platform/gph/gp2xwiz-bundle.mk @@ -1,6 +1,5 @@ # Special target to create bundles for the GP2X Wiz. -#bundle_name = release/scummvm-wiz-`date '+%Y-%m-%d'` bundle_name = release/scummvm-gp2xwiz f=$(shell which $(STRIP)) libloc = $(shell dirname $(f)) @@ -14,11 +13,11 @@ gp2xwiz-bundle: $(EXECUTABLE) echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR" - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.gpe $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/gp2xwiz/scummvm.gpe $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/ @@ -48,11 +47,11 @@ gp2xwiz-bundle-debug: $(EXECUTABLE) echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR" - $(CP) $(srcdir)/backends/platform/gph/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/devices/gp2xwiz/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/devices/common/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/ diff --git a/backends/platform/gph/gph-backend.cpp b/backends/platform/gph/gph-backend.cpp new file mode 100644 index 0000000000..375ee37378 --- /dev/null +++ b/backends/platform/gph/gph-backend.cpp @@ -0,0 +1,219 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/platform/sdl/sdl-sys.h" + +// #include "backends/platform/gph/gph-options.h" +#include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h" +#include "backends/platform/gph/gph-hw.h" +#include "backends/platform/gph/gph-sdl.h" +#include "backends/plugins/posix/posix-provider.h" +#include "backends/saves/default/default-saves.h" +#include "backends/timer/default/default-timer.h" + +#include "base/main.h" + +#include "common/archive.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/events.h" +#include "common/file.h" +#include "common/textconsole.h" +#include "common/util.h" + +#include "audio/mixer_intern.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> +#include <sys/stat.h> +#include <time.h> // for getTimeAndDate() + +/* Dump console info to files. */ +#define DUMP_STDOUT + +void OSystem_GPH::initBackend() { + + // Create the events manager + if (_eventSource == 0) + _eventSource = new GPHEventSource(); + + // Create the graphics manager + if (_graphicsManager == 0) { + _graphicsManager = new GPHGraphicsManager(_eventSource); + } + + // Create the mixer manager + if (_mixer == 0) { + _mixerManager = new DoubleBufferSDLMixerManager(); + + // Setup and start mixer + _mixerManager->init(); + } + + /* Setup default save path to be workingdir/saves */ + + char savePath[PATH_MAX+1]; + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Could not obtain current working directory"); + } else { + printf("Current working directory: %s\n", workDirName); + } + + strcpy(savePath, workDirName); + strcat(savePath, "/saves"); + printf("Current save directory: %s\n", savePath); + struct stat sb; + if (stat(savePath, &sb) == -1) + if (errno == ENOENT) // Create the dir if it does not exist + if (mkdir(savePath, 0755) != 0) + warning("mkdir for '%s' failed!", savePath); + + _savefileManager = new DefaultSaveFileManager(savePath); + + #ifdef DUMP_STDOUT + // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we + // output all our STDOUT and STDERR to files for debug purposes. + char STDOUT_FILE[PATH_MAX+1]; + char STDERR_FILE[PATH_MAX+1]; + + strcpy(STDOUT_FILE, workDirName); + strcpy(STDERR_FILE, workDirName); + strcat(STDOUT_FILE, "/scummvm.stdout.txt"); + strcat(STDERR_FILE, "/scummvm.stderr.txt"); + + // Flush the output in case anything is queued + fclose(stdout); + fclose(stderr); + + // Redirect standard input and standard output + FILE *newfp = freopen(STDOUT_FILE, "w", stdout); + if (newfp == NULL) { + #if !defined(stdout) + stdout = fopen(STDOUT_FILE, "w"); + #else + newfp = fopen(STDOUT_FILE, "w"); + if (newfp) { + *stdout = *newfp; + } + #endif + } + + newfp = freopen(STDERR_FILE, "w", stderr); + if (newfp == NULL) { + #if !defined(stderr) + stderr = fopen(STDERR_FILE, "w"); + #else + newfp = fopen(STDERR_FILE, "w"); + if (newfp) { + *stderr = *newfp; + } + #endif + } + + setbuf(stderr, NULL); + printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); + #endif /* DUMP_STDOUT */ + + /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */ + WIZ_HW::deviceInit(); + + /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */ + WIZ_HW::mixerMoveVolume(0); + + /* Up default volume values as we use a seperate system level volume anyway. */ + ConfMan.registerDefault("music_volume", 192); + ConfMan.registerDefault("sfx_volume", 192); + ConfMan.registerDefault("speech_volume", 192); + + /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */ + ConfMan.registerDefault("autosave_period", 4 * 60); + + /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */ + ConfMan.registerDefault("aspect_ratio", true); + + /* Make sure SDL knows that we have a joystick we want to use. */ + ConfMan.setInt("joystick_num", 0); + + /* Now setup any device specific user options (Left handed mode, that sort of thing). */ + // GPH::setOptions(); + + printf("%s\n", "Passing to OSystem::SDL initBackend."); + + /* Pass to POSIX method to do the heavy lifting */ + OSystem_POSIX::initBackend(); +} + +void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + + /* Setup default extra data paths for engine data files and plugins */ + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Error: Could not obtain current working directory"); + } + + Common::FSNode workdirNode(workDirName); + if (workdirNode.exists() && workdirNode.isDirectory()) { + s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority); + } + + char enginedataPath[PATH_MAX+1]; + + strcpy(enginedataPath, workDirName); + strcat(enginedataPath, "/engine-data"); + + Common::FSNode engineNode(enginedataPath); + if (engineNode.exists() && engineNode.isDirectory()) { + s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); + } + + char pluginsPath[PATH_MAX+1]; + + strcpy(pluginsPath, workDirName); + strcat(pluginsPath, "/plugins"); + + Common::FSNode pluginsNode(pluginsPath); + if (pluginsNode.exists() && pluginsNode.isDirectory()) { + s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority); + } +} + +void OSystem_GPH::quit() { + + WIZ_HW::deviceDeinit(); + + #ifdef DUMP_STDOUT + printf("%s\n", "Debug: STDOUT and STDERR text files closed."); + fclose(stdout); + fclose(stderr); + #endif /* DUMP_STDOUT */ + + OSystem_SDL::quit(); +} diff --git a/backends/platform/gph/gph-main.cpp b/backends/platform/gph/gph-main.cpp index e711135c15..f91ec8f478 100644 --- a/backends/platform/gph/gph-main.cpp +++ b/backends/platform/gph/gph-main.cpp @@ -18,199 +18,34 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ -#include "backends/platform/sdl/sdl-sys.h" - -// #include "backends/platform/gph/gph-options.h" #include "backends/platform/gph/gph-sdl.h" -#include "backends/platform/gph/gph-hw.h" -#include "backends/plugins/posix/posix-provider.h" +#include "backends/plugins/sdl/sdl-provider.h" #include "base/main.h" -#include "common/archive.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/events.h" -#include "common/util.h" - -#include "common/file.h" -#include "base/main.h" - -#include "backends/saves/default/default-saves.h" - -#include "backends/timer/default/default-timer.h" -#include "audio/mixer_intern.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include <sys/stat.h> -#include <time.h> // for getTimeAndDate() - -/* Dump console info to files. */ -#define DUMP_STDOUT +#if defined(GPH_DEVICE) int main(int argc, char *argv[]) { + + // Create our OSystem instance g_system = new OSystem_GPH(); assert(g_system); + + // Pre initialize the backend + ((OSystem_GPH *)g_system)->init(); + #ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); #endif // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - g_system->quit(); - - return res; -} - -void OSystem_GPH::initBackend() { - - /* Setup default save path to be workingdir/saves */ - - char savePath[PATH_MAX+1]; - char workDirName[PATH_MAX+1]; - - if (getcwd(workDirName, PATH_MAX) == NULL) { - error("Could not obtain current working directory"); - } else { - printf("Current working directory: %s\n", workDirName); - } - - strcpy(savePath, workDirName); - strcat(savePath, "/saves"); - printf("Current save directory: %s\n", savePath); - struct stat sb; - if (stat(savePath, &sb) == -1) - if (errno == ENOENT) // Create the dir if it does not exist - if (mkdir(savePath, 0755) != 0) - warning("mkdir for '%s' failed!", savePath); - - _savefile = new DefaultSaveFileManager(savePath); - - #ifdef DUMP_STDOUT - // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we - // output all our STDOUT and STDERR to files for debug purposes. - char STDOUT_FILE[PATH_MAX+1]; - char STDERR_FILE[PATH_MAX+1]; - - strcpy(STDOUT_FILE, workDirName); - strcpy(STDERR_FILE, workDirName); - strcat(STDOUT_FILE, "/scummvm.stdout.txt"); - strcat(STDERR_FILE, "/scummvm.stderr.txt"); - - // Flush the output in case anything is queued - fclose(stdout); - fclose(stderr); - - // Redirect standard input and standard output - FILE *newfp = freopen(STDOUT_FILE, "w", stdout); - if (newfp == NULL) { - #if !defined(stdout) - stdout = fopen(STDOUT_FILE, "w"); - #else - newfp = fopen(STDOUT_FILE, "w"); - if (newfp) { - *stdout = *newfp; - } - #endif - } - - newfp = freopen(STDERR_FILE, "w", stderr); - if (newfp == NULL) { - #if !defined(stderr) - stderr = fopen(STDERR_FILE, "w"); - #else - newfp = fopen(STDERR_FILE, "w"); - if (newfp) { - *stderr = *newfp; - } - #endif - } - setbuf(stderr, NULL); - printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); - #endif /* DUMP_STDOUT */ + // Free OSystem + delete (OSystem_GPH *)g_system; - /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */ - WIZ_HW::deviceInit(); - - /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */ - WIZ_HW::mixerMoveVolume(0); - - /* Up default volume values as we use a seperate system level volume anyway. */ - ConfMan.registerDefault("music_volume", 192); - ConfMan.registerDefault("sfx_volume", 192); - ConfMan.registerDefault("speech_volume", 192); - - /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */ - ConfMan.registerDefault("autosave_period", 4 * 60); - - /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */ - ConfMan.registerDefault("aspect_ratio", true); - - /* Make sure SDL knows that we have a joystick we want to use. */ - ConfMan.setInt("joystick_num", 0); - - /* Now setup any device specific user options (Left handed mode, that sort of thing). */ - // GPH::setOptions(); - - printf("%s\n", "Passing to OSystem::SDL initBackend."); - - /* Pass to SDL backend to do the heavy lifting */ - OSystem_SDL::initBackend(); -} - -void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { - - /* Setup default extra data paths for engine data files and plugins */ - char workDirName[PATH_MAX+1]; - - if (getcwd(workDirName, PATH_MAX) == NULL) { - error("Error: Could not obtain current working directory"); - } - - Common::FSNode workdirNode(workDirName); - if (workdirNode.exists() && workdirNode.isDirectory()) { - s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority); - } - - char enginedataPath[PATH_MAX+1]; - - strcpy(enginedataPath, workDirName); - strcat(enginedataPath, "/engine-data"); - - Common::FSNode engineNode(enginedataPath); - if (engineNode.exists() && engineNode.isDirectory()) { - s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); - } - - char pluginsPath[PATH_MAX+1]; - - strcpy(pluginsPath, workDirName); - strcat(pluginsPath, "/plugins"); - - Common::FSNode pluginsNode(pluginsPath); - if (pluginsNode.exists() && pluginsNode.isDirectory()) { - s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority); - } + return res; } -void OSystem_GPH::quit() { - - WIZ_HW::deviceDeinit(); - - #ifdef DUMP_STDOUT - printf("%s\n", "Debug: STDOUT and STDERR text files closed."); - fclose(stdout); - fclose(stderr); - #endif /* DUMP_STDOUT */ - - OSystem_SDL::quit(); -} +#endif diff --git a/backends/platform/gph/gph-sdl.h b/backends/platform/gph/gph-sdl.h index 136363f9a0..68a641eed7 100644 --- a/backends/platform/gph/gph-sdl.h +++ b/backends/platform/gph/gph-sdl.h @@ -18,64 +18,32 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ -#ifndef GPH_SDL_H -#define GPH_SDL_H +#ifndef GPH_H +#define GPH_H -#include "backends/platform/sdl/sdl.h" +#if defined(GPH_DEVICE) -// FIXME: For now keep hacks in this header to save polluting the SDL backend. -enum { - GFX_HALF = 12 -}; +#include "backends/base-backend.h" +#include "backends/platform/sdl/sdl.h" +#include "backends/platform/sdl/posix/posix.h" +#include "backends/graphics/gph/gph-graphics.h" +#include "backends/events/gph/gph-events.h" #define __GP2XWIZ__ -#define MIXER_DOUBLE_BUFFERING 1 #ifndef PATH_MAX #define PATH_MAX 255 #endif -class OSystem_GPH : public OSystem_SDL { +class OSystem_GPH : public OSystem_POSIX { public: - OSystem_GPH() {} - - /* Graphics */ - void initSize(uint w, uint h); - void setGraphicsModeIntern(); - bool setGraphicsMode(int mode); - void internUpdateScreen(); - const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(const char *name); - int getDefaultGraphicsMode() const; - bool loadGFXMode(); - void drawMouse(); - void undrawMouse(); - void showOverlay(); - void hideOverlay(); - - /* Event Stuff */ - void moveStick(); - void fillMouseEvent(Common::Event&, int, int); - void warpMouse(int, int); - bool remapKey(SDL_Event&, Common::Event&); - /* Platform Setup Stuff */ void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); void initBackend(); void quit(); - -protected: - bool _stickBtn[32]; - - bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); - bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); - bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); - bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); }; -#endif //GPH_SDL_H +#endif +#endif //GPH_H diff --git a/backends/platform/gph/module.mk b/backends/platform/gph/module.mk index f5567f581e..a9951494d1 100644 --- a/backends/platform/gph/module.mk +++ b/backends/platform/gph/module.mk @@ -1,10 +1,9 @@ MODULE := backends/platform/gph MODULE_OBJS := \ - gph-events.o \ - gph-graphics.o \ - gph-hw.o \ - gph-main.o + gph-main.o \ + gph-backend.o \ + gph-hw.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h index 5e88510980..79f596632f 100644 --- a/backends/platform/iphone/osys_main.h +++ b/backends/platform/iphone/osys_main.h @@ -30,6 +30,7 @@ #include "audio/mixer_intern.h" #include "backends/fs/posix/posix-fs-factory.h" #include "graphics/colormasks.h" +#include "graphics/palette.h" #include <AudioToolbox/AudioQueue.h> @@ -81,7 +82,7 @@ protected: bool _mouseVisible; byte *_mouseBuf; - byte _mouseKeyColour; + byte _mouseKeyColor; uint _mouseWidth, _mouseHeight; uint _mouseX, _mouseY; int _mouseHotspotX, _mouseHotspotY; diff --git a/backends/platform/iphone/osys_video.cpp b/backends/platform/iphone/osys_video.cpp index d67d38932a..a10efeff40 100644 --- a/backends/platform/iphone/osys_video.cpp +++ b/backends/platform/iphone/osys_video.cpp @@ -312,7 +312,7 @@ void OSystem_IPHONE::drawMouseCursorOnRectUpdate(const Common::Rect& updatedRect uint16 *dst = &_fullscreen[top * _screenWidth + left]; for (int y = displayHeight; y > srcY; y--) { for (int x = displayWidth; x > srcX; x--) { - if (*src != _mouseKeyColour) + if (*src != _mouseKeyColor) *dst = _palette[*src]; dst++; src++; @@ -334,7 +334,7 @@ Graphics::Surface *OSystem_IPHONE::lockScreen() { _framebuffer.w = _screenWidth; _framebuffer.h = _screenHeight; _framebuffer.pitch = _screenWidth; - _framebuffer.bytesPerPixel = 1; + _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); return &_framebuffer; } @@ -497,7 +497,7 @@ void OSystem_IPHONE::setMouseCursor(const byte *buf, uint w, uint h, int hotspot _mouseHotspotX = hotspotX; _mouseHotspotY = hotspotY; - _mouseKeyColour = (byte)keycolor; + _mouseKeyColor = (byte)keycolor; memcpy(_mouseBuf, buf, w * h); diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h index 2daa41a9f6..7a84de0449 100644 --- a/backends/platform/n64/osys_n64.h +++ b/backends/platform/n64/osys_n64.h @@ -37,6 +37,7 @@ #include "graphics/surface.h" #include "graphics/colormasks.h" +#include "graphics/palette.h" #include "graphics/pixelformat.h" #include "audio/mixer_intern.h" diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp index 54eab0fd52..232037899b 100644 --- a/backends/platform/n64/osys_n64_base.cpp +++ b/backends/platform/n64/osys_n64_base.cpp @@ -610,7 +610,7 @@ Graphics::Surface *OSystem_N64::lockScreen() { _framebuffer.w = _gameWidth; _framebuffer.h = _gameHeight; _framebuffer.pitch = _screenWidth; - _framebuffer.bytesPerPixel = 1; + _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); return &_framebuffer; } diff --git a/backends/platform/n64/osys_n64_events.cpp b/backends/platform/n64/osys_n64_events.cpp index 9a53051d3d..22b9addbfb 100644 --- a/backends/platform/n64/osys_n64_events.cpp +++ b/backends/platform/n64/osys_n64_events.cpp @@ -118,9 +118,9 @@ void OSystem_N64::readControllerAnalogInput(void) { // Gamepad if (abs(pad_analogX) > PAD_DEADZONE) - mx += tan(pad_analogX * (PI / 140)); + mx += tan(pad_analogX * (M_PI / 140)); if (abs(pad_analogY) > PAD_DEADZONE) - my -= tan(pad_analogY * (PI / 140)); + my -= tan(pad_analogY * (M_PI / 140)); // Mouse if (abs(pad_mouseX) > MOUSE_DEADZONE) diff --git a/backends/platform/openpandora/module.mk b/backends/platform/openpandora/module.mk index 1e5f6bcd69..8e60b87aa6 100755 --- a/backends/platform/openpandora/module.mk +++ b/backends/platform/openpandora/module.mk @@ -1,9 +1,8 @@ MODULE := backends/platform/openpandora MODULE_OBJS := \ - op-graphics.o \ - op-events.o \ op-options.o \ + op-backend.o \ op-main.o MODULE_DIRS += \ diff --git a/backends/platform/openpandora/op-backend.cpp b/backends/platform/openpandora/op-backend.cpp new file mode 100644 index 0000000000..4c29636e40 --- /dev/null +++ b/backends/platform/openpandora/op-backend.cpp @@ -0,0 +1,278 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/platform/openpandora/op-sdl.h" +#include "base/main.h" + +#include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h" +#include "backends/saves/default/default-saves.h" +#include "backends/timer/default/default-timer.h" + +#include "common/archive.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/events.h" +#include "common/file.h" +#include "common/util.h" + +#include "audio/mixer_intern.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> +#include <sys/stat.h> +#include <time.h> // for getTimeAndDate() + +/* Dump console info to files. */ +#define DUMP_STDOUT + +static SDL_Cursor *hiddenCursor; + +static Uint32 timer_handler(Uint32 interval, void *param) { + ((DefaultTimerManager *)param)->handler(); + return interval; +} + +void OSystem_OP::initBackend() { + + assert(!_inited); + +// int joystick_num = ConfMan.getInt("joystick_num"); +// uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; +// +// if (ConfMan.hasKey("disable_sdl_parachute")) +// sdlFlags |= SDL_INIT_NOPARACHUTE; +// +// if (joystick_num > -1) +// sdlFlags |= SDL_INIT_JOYSTICK; +// +// if (SDL_Init(sdlFlags) == -1) { +// error("Could not initialize SDL: %s", SDL_GetError()); +// } +// + + // Create the mixer manager + if (_mixer == 0) { + _mixerManager = new DoubleBufferSDLMixerManager(); + + // Setup and start mixer + _mixerManager->init(); + } + + /* Setup default save path to be workingdir/saves */ + + char savePath[PATH_MAX+1]; + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Could not obtain current working directory."); + } else { + printf("Current working directory: %s\n", workDirName); + } + + strcpy(savePath, workDirName); + strcat(savePath, "/../saves"); + printf("Current save directory: %s\n", savePath); + struct stat sb; + if (stat(savePath, &sb) == -1) + if (errno == ENOENT) // Create the dir if it does not exist + if (mkdir(savePath, 0755) != 0) + warning("mkdir for '%s' failed!", savePath); + +// _savefileManager = new DefaultSaveFileManager(savePath); + + #ifdef DUMP_STDOUT + // The OpenPandora has a serial console on the EXT connection but most users do not use this so we + // output all our STDOUT and STDERR to files for debug purposes. + char STDOUT_FILE[PATH_MAX+1]; + char STDERR_FILE[PATH_MAX+1]; + + strcpy(STDOUT_FILE, workDirName); + strcpy(STDERR_FILE, workDirName); + strcat(STDOUT_FILE, "/scummvm.stdout.txt"); + strcat(STDERR_FILE, "/scummvm.stderr.txt"); + + // Flush the output in case anything is queued + fclose(stdout); + fclose(stderr); + + // Redirect standard input and standard output + FILE *newfp = freopen(STDOUT_FILE, "w", stdout); + if (newfp == NULL) { + #if !defined(stdout) + stdout = fopen(STDOUT_FILE, "w"); + #else + newfp = fopen(STDOUT_FILE, "w"); + if (newfp) { + *stdout = *newfp; + } + #endif + } + + newfp = freopen(STDERR_FILE, "w", stderr); + if (newfp == NULL) { + #if !defined(stderr) + stderr = fopen(STDERR_FILE, "w"); + #else + newfp = fopen(STDERR_FILE, "w"); + if (newfp) { + *stderr = *newfp; + } + #endif + } + + setbuf(stderr, NULL); + printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); + #endif /* DUMP_STDOUT */ + + /* Trigger autosave every 4 minutes. */ + ConfMan.registerDefault("autosave_period", 4 * 60); + + ConfMan.registerDefault("fullscreen", true); + + /* Make sure that aspect ratio correction is enabled on the 1st run to stop + users asking me what the 'wasted space' at the bottom is ;-). */ + ConfMan.registerDefault("aspect_ratio", true); + + /* Make sure SDL knows that we have a joystick we want to use. */ + ConfMan.setInt("joystick_num", 0); + + // Create the events manager + if (_eventSource == 0) + _eventSource = new OPEventSource(); + + // Create the graphics manager + if (_graphicsManager == 0) + _graphicsManager = new OPGraphicsManager(_eventSource); + +// _graphicsMutex = createMutex(); + + // Invoke parent implementation of this method + OSystem_POSIX::initBackend(); + + _inited = true; +} + + + + // enable joystick +// if (joystick_num > -1 && SDL_NumJoysticks() > 0) { +// printf("Using joystick: %s\n", SDL_JoystickName(0)); +// _joystick = SDL_JoystickOpen(joystick_num); +// } +// +// setupMixer(); + + // Note: We could implement a custom SDLTimerManager by using + // SDL_AddTimer. That might yield better timer resolution, but it would + // also change the semantics of a timer: Right now, ScummVM timers + // *never* run in parallel, due to the way they are implemented. If we + // switched to SDL_AddTimer, each timer might run in a separate thread. + // However, not all our code is prepared for that, so we can't just + // switch. Still, it's a potential future change to keep in mind. +// _timer = new DefaultTimerManager(); +// _timerID = SDL_AddTimer(10, &timer_handler, _timer); + +void OSystem_OP::initSDL() { + // Check if SDL has not been initialized + if (!_initedSDL) { + + uint32 sdlFlags = SDL_INIT_EVENTTHREAD; + if (ConfMan.hasKey("disable_sdl_parachute")) + sdlFlags |= SDL_INIT_NOPARACHUTE; + + // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers) + if (SDL_Init(sdlFlags) == -1) + error("Could not initialize SDL: %s", SDL_GetError()); + + uint8_t hiddenCursorData = 0; + + hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0); + + /* On the OpenPandora we need to work around an SDL assumption that + returns relative mouse coordinates when you get to the screen + edges using the touchscreen. The workaround is to set a blank + SDL cursor and not disable it (Hackish I know). + + The root issues likes in the Windows Manager GRAB code in SDL. + That is why the issue is not seen on framebuffer devices like the + GP2X (there is no X window manager ;)). + */ + SDL_ShowCursor(SDL_ENABLE); + SDL_SetCursor(hiddenCursor); + SDL_EnableUNICODE(1); + +// memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); +// memset(&_videoMode, 0, sizeof(_videoMode)); +// memset(&_transactionDetails, 0, sizeof(_transactionDetails)); + +// _videoMode.mode = GFX_DOUBLESIZE; +// _videoMode.scaleFactor = 2; +// _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); +// _scalerProc = Normal2x; +// _scalerType = 0; + +// _videoMode.fullscreen = true; + + _initedSDL = true; + } +} + +void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + + /* Setup default extra data paths for engine data files and plugins */ + + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Error: Could not obtain current working directory."); + } + + char enginedataPath[PATH_MAX+1]; + + strcpy(enginedataPath, workDirName); + strcat(enginedataPath, "/../data"); + printf("Default engine data directory: %s\n", enginedataPath); + + Common::FSNode engineNode(enginedataPath); + if (engineNode.exists() && engineNode.isDirectory()) { + s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); + } +} + +void OSystem_OP::quit() { + + SDL_FreeCursor(hiddenCursor); + + #ifdef DUMP_STDOUT + printf("%s\n", "Debug: STDOUT and STDERR text files closed."); + fclose(stdout); + fclose(stderr); + #endif /* DUMP_STDOUT */ + + OSystem_POSIX::quit(); +} diff --git a/backends/platform/openpandora/op-main.cpp b/backends/platform/openpandora/op-main.cpp index 6e64baddc7..ab777fec8f 100644 --- a/backends/platform/openpandora/op-main.cpp +++ b/backends/platform/openpandora/op-main.cpp @@ -18,250 +18,36 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ -// Disable symbol overrides so that we can use system headers. -#define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/platform/sdl/sdl-sys.h" - #include "backends/platform/openpandora/op-sdl.h" #include "backends/plugins/posix/posix-provider.h" #include "base/main.h" -#include "common/archive.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/events.h" -#include "common/util.h" - -#include "common/file.h" -#include "base/main.h" - -#include "backends/saves/default/default-saves.h" - -#include "backends/timer/default/default-timer.h" -#include "audio/mixer_intern.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include <sys/stat.h> -#include <time.h> // for getTimeAndDate() - -/* Dump console info to files. */ -#define DUMP_STDOUT - -static SDL_Cursor *hiddenCursor; +#if defined(OPENPANDORA) int main(int argc, char *argv[]) { + + // Create our OSystem instance g_system = new OSystem_OP(); assert(g_system); + // Pre initialize the backend + //((OSystem_OP *)g_system)->init(); + #ifdef DYNAMIC_MODULES PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); #endif // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - g_system->quit(); - - return res; -} - -static Uint32 timer_handler(Uint32 interval, void *param) { - ((DefaultTimerManager *)param)->handler(); - return interval; -} - -void OSystem_OP::initBackend() { - - assert(!_inited); - - uint8_t hiddenCursorData = 0; - - int joystick_num = ConfMan.getInt("joystick_num"); - uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; - - if (ConfMan.hasKey("disable_sdl_parachute")) - sdlFlags |= SDL_INIT_NOPARACHUTE; - - if (joystick_num > -1) - sdlFlags |= SDL_INIT_JOYSTICK; - - if (SDL_Init(sdlFlags) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); - } - - hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0); - - /* Setup default save path to be workingdir/saves */ - - char savePath[PATH_MAX+1]; - char workDirName[PATH_MAX+1]; - - if (getcwd(workDirName, PATH_MAX) == NULL) { - error("Could not obtain current working directory."); - } else { - printf("Current working directory: %s\n", workDirName); - } - - strcpy(savePath, workDirName); - strcat(savePath, "/../saves"); - printf("Current save directory: %s\n", savePath); - struct stat sb; - if (stat(savePath, &sb) == -1) - if (errno == ENOENT) // Create the dir if it does not exist - if (mkdir(savePath, 0755) != 0) - warning("mkdir for '%s' failed!", savePath); - - _savefile = new DefaultSaveFileManager(savePath); - - #ifdef DUMP_STDOUT - // The OpenPandora has a serial console on the EXT connection but most users do not use this so we - // output all our STDOUT and STDERR to files for debug purposes. - char STDOUT_FILE[PATH_MAX+1]; - char STDERR_FILE[PATH_MAX+1]; - - strcpy(STDOUT_FILE, workDirName); - strcpy(STDERR_FILE, workDirName); - strcat(STDOUT_FILE, "/scummvm.stdout.txt"); - strcat(STDERR_FILE, "/scummvm.stderr.txt"); - - // Flush the output in case anything is queued - fclose(stdout); - fclose(stderr); - // Redirect standard input and standard output - FILE *newfp = freopen(STDOUT_FILE, "w", stdout); - if (newfp == NULL) { - #if !defined(stdout) - stdout = fopen(STDOUT_FILE, "w"); - #else - newfp = fopen(STDOUT_FILE, "w"); - if (newfp) { - *stdout = *newfp; - } - #endif - } + // Free OSystem + delete (OSystem_OP *)g_system; - newfp = freopen(STDERR_FILE, "w", stderr); - if (newfp == NULL) { - #if !defined(stderr) - stderr = fopen(STDERR_FILE, "w"); - #else - newfp = fopen(STDERR_FILE, "w"); - if (newfp) { - *stderr = *newfp; - } - #endif - } - - setbuf(stderr, NULL); - printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); - #endif /* DUMP_STDOUT */ - - /* Trigger autosave every 4 minutes. */ - ConfMan.registerDefault("autosave_period", 4 * 60); - - ConfMan.registerDefault("fullscreen", true); - - /* Make sure that aspect ratio correction is enabled on the 1st run to stop - users asking me what the 'wasted space' at the bottom is ;-). */ - ConfMan.registerDefault("aspect_ratio", true); - - /* Make sure SDL knows that we have a joystick we want to use. */ - ConfMan.setInt("joystick_num", 0); - - _graphicsMutex = createMutex(); - - /* On the OpenPandora we need to work around an SDL assumption that - returns relative mouse coordinates when you get to the screen - edges using the touchscreen. The workaround is to set a blank - SDL cursor and not disable it (Hackish I know). - - The root issues likes in the Windows Manager GRAB code in SDL. - That is why the issue is not seen on framebuffer devices like the - GP2X (there is no X window manager ;)). - */ - SDL_ShowCursor(SDL_ENABLE); - SDL_SetCursor(hiddenCursor); - - // Enable unicode support if possible - SDL_EnableUNICODE(1); - - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); - memset(&_videoMode, 0, sizeof(_videoMode)); - memset(&_transactionDetails, 0, sizeof(_transactionDetails)); - - _videoMode.mode = GFX_DOUBLESIZE; - _videoMode.scaleFactor = 2; - _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); - _scalerProc = Normal2x; - _scalerType = 0; - - _videoMode.fullscreen = true; - - // enable joystick - if (joystick_num > -1 && SDL_NumJoysticks() > 0) { - printf("Using joystick: %s\n", SDL_JoystickName(0)); - _joystick = SDL_JoystickOpen(joystick_num); - } - - setupMixer(); - - // Note: We could implement a custom SDLTimerManager by using - // SDL_AddTimer. That might yield better timer resolution, but it would - // also change the semantics of a timer: Right now, ScummVM timers - // *never* run in parallel, due to the way they are implemented. If we - // switched to SDL_AddTimer, each timer might run in a separate thread. - // However, not all our code is prepared for that, so we can't just - // switch. Still, it's a potential future change to keep in mind. - _timer = new DefaultTimerManager(); - _timerID = SDL_AddTimer(10, &timer_handler, _timer); - - // Invoke parent implementation of this method - OSystem::initBackend(); - - _inited = true; -} - -void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { - - /* Setup default extra data paths for engine data files and plugins */ - - char workDirName[PATH_MAX+1]; - - if (getcwd(workDirName, PATH_MAX) == NULL) { - error("Error: Could not obtain current working directory."); - } - - char enginedataPath[PATH_MAX+1]; - - strcpy(enginedataPath, workDirName); - strcat(enginedataPath, "/../data"); - printf("Default engine data directory: %s\n", enginedataPath); - - Common::FSNode engineNode(enginedataPath); - if (engineNode.exists() && engineNode.isDirectory()) { - s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); - } + return res; } -void OSystem_OP::quit() { - - SDL_FreeCursor(hiddenCursor); - - #ifdef DUMP_STDOUT - printf("%s\n", "Debug: STDOUT and STDERR text files closed."); - fclose(stdout); - fclose(stderr); - #endif /* DUMP_STDOUT */ - - OSystem_SDL::quit(); -} +#endif diff --git a/backends/platform/openpandora/op-sdl.h b/backends/platform/openpandora/op-sdl.h index 8561b42498..9d92472b17 100644 --- a/backends/platform/openpandora/op-sdl.h +++ b/backends/platform/openpandora/op-sdl.h @@ -18,42 +18,37 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #ifndef OP_SDL_H #define OP_SDL_H +#if defined(OPENPANDORA) + +#include "backends/base-backend.h" #include "backends/platform/sdl/sdl.h" +#include "backends/platform/sdl/posix/posix.h" +#include "backends/events/openpandora/op-events.h" +#include "backends/graphics/openpandora/op-graphics.h" #define __OPENPANDORA__ -#define MIXER_DOUBLE_BUFFERING 1 #ifndef PATH_MAX #define PATH_MAX 255 #endif -class OSystem_OP : public OSystem_SDL { +class OSystem_OP : public OSystem_POSIX { public: OSystem_OP() {} - /* Events */ - bool handleKeyDown(SDL_Event &ev, Common::Event &event); - bool handleKeyUp(SDL_Event &ev, Common::Event &event); - bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); - bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); - - /* Graphics */ - bool loadGFXMode(); - /* Platform Setup Stuff */ void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); void initBackend(); + void initSDL(); void quit(); protected: }; #endif +#endif //OP_SDL_H diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp index f869779573..c228a12b26 100644 --- a/backends/platform/ps2/Gs2dScreen.cpp +++ b/backends/platform/ps2/Gs2dScreen.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include "Gs2dScreen.h" #include <kernel.h> #include <malloc.h> @@ -398,7 +400,7 @@ Graphics::Surface *Gs2dScreen::lockScreen() { _framebuffer.w = _width; _framebuffer.h = _height; _framebuffer.pitch = _width; // -not- _pitch; ! It's EE mem, not Tex - _framebuffer.bytesPerPixel = 1; + _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); return &_framebuffer; } @@ -441,7 +443,7 @@ void Gs2dScreen::grabPalette(uint8 *pal, uint8 start, uint16 num) { void Gs2dScreen::grabScreen(Graphics::Surface *surf) { assert(surf); WaitSema(g_DmacSema); - surf->create(_width, _height, 1); + surf->create(_width, _height, Graphics::PixelFormat::createFormatCLUT8()); memcpy(surf->pixels, _screenBuf, _width * _height); SignalSema(g_DmacSema); } @@ -680,7 +682,7 @@ void Gs2dScreen::animThread(void) { { SCALE(1), SCALE(1) }, { SCALE(1), SCALE(14) }, { SCALE(128), SCALE(1) }, { SCALE(128), SCALE(14) } }; - float angleStep = ((2 * PI) / _tvHeight); + float angleStep = ((2 * M_PI) / _tvHeight); while (!_systemQuit) { do { @@ -739,7 +741,7 @@ void Gs2dScreen::animThread(void) { float z[4]; GsVertex nodes[4]; - float angle = PI / 2 + angleStep * drawY; + float angle = M_PI / 2 + angleStep * drawY; float rotSin = sinf(angle); float rotCos = cosf(angle); for (int coord = 0; coord < 4; coord++) { diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h index 358e717cbe..6e842b3f55 100644 --- a/backends/platform/ps2/Gs2dScreen.h +++ b/backends/platform/ps2/Gs2dScreen.h @@ -46,7 +46,7 @@ enum GsInterlace { namespace Graphics { - struct Surface; +struct Surface; } class Gs2dScreen { diff --git a/backends/platform/ps2/irxboot.cpp b/backends/platform/ps2/irxboot.cpp index 5ab7823e63..cc23df6575 100644 --- a/backends/platform/ps2/irxboot.cpp +++ b/backends/platform/ps2/irxboot.cpp @@ -73,7 +73,7 @@ PS2Device detectBootPath(const char *elfPath, char *bootPath) { PS2Device device = _getDev(elfPath); - printf("elf path: %s, device %d\n", elfPath, device); + sioprintf("elf path: %s, device %d\n", elfPath, device); strcpy(bootPath, elfPath); diff --git a/backends/platform/ps2/ps2input.cpp b/backends/platform/ps2/ps2input.cpp index 964a773f7e..6da21172ad 100644 --- a/backends/platform/ps2/ps2input.cpp +++ b/backends/platform/ps2/ps2input.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <kernel.h> #include <malloc.h> #include <assert.h> diff --git a/backends/platform/ps2/ps2input.h b/backends/platform/ps2/ps2input.h index 266f408809..eca5950113 100644 --- a/backends/platform/ps2/ps2input.h +++ b/backends/platform/ps2/ps2input.h @@ -32,6 +32,10 @@ class OSystem_PS2; class Ps2Pad; +namespace Common { +struct Event; +} + class Ps2Input { public: Ps2Input(OSystem_PS2 *system, bool mouseLoaded, bool kbdLoaded); diff --git a/backends/platform/ps2/ps2mutex.cpp b/backends/platform/ps2/ps2mutex.cpp index fe76202f32..974cf00f56 100644 --- a/backends/platform/ps2/ps2mutex.cpp +++ b/backends/platform/ps2/ps2mutex.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include "backends/platform/ps2/systemps2.h" void OSystem_PS2::initMutexes(void) { diff --git a/backends/platform/ps2/ps2pad.cpp b/backends/platform/ps2/ps2pad.cpp index 3d285eedd5..090a5f2a35 100644 --- a/backends/platform/ps2/ps2pad.cpp +++ b/backends/platform/ps2/ps2pad.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <kernel.h> #include <malloc.h> #include <assert.h> diff --git a/backends/platform/ps2/ps2time.cpp b/backends/platform/ps2/ps2time.cpp index 4da8420478..4c682cb9f2 100644 --- a/backends/platform/ps2/ps2time.cpp +++ b/backends/platform/ps2/ps2time.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + #include "backends/platform/ps2/systemps2.h" #include "backends/platform/ps2/ps2debug.h" #include "eecodyvdfs.h" diff --git a/backends/platform/ps2/savefilemgr.cpp b/backends/platform/ps2/savefilemgr.cpp index a4b3ddb971..459920c34a 100644 --- a/backends/platform/ps2/savefilemgr.cpp +++ b/backends/platform/ps2/savefilemgr.cpp @@ -23,6 +23,10 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + #include "common/config-manager.h" #include "common/zlib.h" diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 77de74eb5b..aed2378faf 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -568,6 +568,11 @@ void OSystem_PS2::updateScreen(void) { _screen->updateScreen(); } +void OSystem_PS2::displayMessageOnOSD(const char *msg) { + /* TODO : check */ + printf("displayMessageOnOSD: %s\n", msg); +} + uint32 OSystem_PS2::getMillis(void) { return msecCount; } @@ -727,7 +732,7 @@ void OSystem_PS2::msgPrintf(int millis, const char *format, ...) { int maxWidth = 0; Graphics::Surface surf; - surf.create(300, 200, 1); + surf.create(300, 200, Graphics::PixelFormat::createFormatCLUT8()); char *lnSta = resStr; while (*lnSta && (posY < 180)) { diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index 37575f399f..26e3105cd9 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -28,6 +28,7 @@ #include "common/system.h" #include "backends/base-backend.h" +#include "graphics/palette.h" class DefaultTimerManager; class DefaultSaveFileManager; @@ -47,11 +48,11 @@ struct Ps2Mutex { }; namespace Common { - class TimerManager; +class TimerManager; }; namespace Audio { - class MixerImpl; +class MixerImpl; }; class OSystem_PS2 : public BaseBackend, public PaletteManager { @@ -78,9 +79,7 @@ public: virtual Graphics::Surface *lockScreen(); virtual void unlockScreen(); virtual void updateScreen(); - /* TODO : check */ - virtual void displayMessageOnOSD(const char *msg) { printf("displayMessageOnOSD: %s\n", msg); }; - /* */ + virtual void displayMessageOnOSD(const char *msg); virtual void showOverlay(); virtual void hideOverlay(); diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP index b520022033..dcfa30898c 100644 --- a/backends/platform/psp/README.PSP +++ b/backends/platform/psp/README.PSP @@ -1,4 +1,4 @@ -ScummVM-PSP 1.3.0git README +ScummVM-PSP 1.4.0git README ============================================================================== Installation diff --git a/backends/platform/psp/cursor.cpp b/backends/platform/psp/cursor.cpp index cf879e095a..420b0398c3 100644 --- a/backends/platform/psp/cursor.cpp +++ b/backends/platform/psp/cursor.cpp @@ -327,8 +327,20 @@ inline void Cursor::setRendererModePalettized(bool palettized) { _renderer.setAlphaReverse(false); _renderer.setColorTest(false); } else { // 16 bits, no palette + // Color test is an easy way for the hardware to make our keycolor + // transparent. + _renderer.setColorTest(true); + + // Alpha blending is not strictly required, but makes the cursor look + // much better _renderer.setAlphaBlending(true); - _renderer.setAlphaReverse(true); // We can't change all alpha values, so just reverse - _renderer.setColorTest(true); // Color test to make our key color transparent + + // Pixel formats without alpha (5650) are considered to have their alpha set. + // Since pixel formats with alpha don't have their alpha bits set, we reverse + // the alpha format for them so that 0 alpha is 1. + if (_buffer.getPixelFormat() != PSPPixelFormat::Type_5650) + _renderer.setAlphaReverse(true); + else + _renderer.setAlphaReverse(false); } } diff --git a/backends/platform/psp/default_display_client.cpp b/backends/platform/psp/default_display_client.cpp index bb42406c3e..34b1a70711 100644 --- a/backends/platform/psp/default_display_client.cpp +++ b/backends/platform/psp/default_display_client.cpp @@ -199,7 +199,7 @@ Graphics::Surface *Screen::lockAndGetForEditing() { _frameBuffer.w = _buffer.getSourceWidth(); _frameBuffer.h = _buffer.getSourceHeight(); _frameBuffer.pitch = _buffer.getBytesPerPixel() * _buffer.getWidth(); - _frameBuffer.bytesPerPixel = _buffer.getBytesPerPixel(); + _frameBuffer.format = _pixelFormat; // We'll set to dirty once we unlock the screen return &_frameBuffer; diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp index 76b4a28e4a..d43e876a17 100644 --- a/backends/platform/psp/display_client.cpp +++ b/backends/platform/psp/display_client.cpp @@ -23,6 +23,20 @@ * */ +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <pspgu.h> #include <pspkerneltypes.h> #include <pspdisplay.h> diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp index 54476dabfd..fd686513af 100644 --- a/backends/platform/psp/mp3.cpp +++ b/backends/platform/psp/mp3.cpp @@ -23,12 +23,26 @@ * */ +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf #include "common/debug.h" #include "common/stream.h" #include "common/util.h" #include "common/singleton.h" #include "common/mutex.h" +#include "common/textconsole.h" #include "audio/audiostream.h" diff --git a/backends/platform/psp/mp3.h b/backends/platform/psp/mp3.h index 1d2fe5ec2f..95491d5788 100644 --- a/backends/platform/psp/mp3.h +++ b/backends/platform/psp/mp3.h @@ -30,7 +30,7 @@ #include "common/scummsys.h" namespace Common { - class SeekableReadStream; +class SeekableReadStream; } namespace Audio { diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index bb7c1ff7d5..e2a8a88c57 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -23,6 +23,9 @@ * */ +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + #include <pspuser.h> #include <pspgu.h> #include <pspdisplay.h> diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 051449d4a0..1e4aea70d3 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -29,6 +29,7 @@ #include "common/scummsys.h" #include "graphics/surface.h" #include "graphics/colormasks.h" +#include "graphics/palette.h" #include "audio/mixer_intern.h" #include "backends/base-backend.h" #include "backends/fs/psp/psp-fs-factory.h" diff --git a/backends/platform/psp/portdefs.h b/backends/platform/psp/portdefs.h index bf7ed41e25..dae9b5d49e 100644 --- a/backends/platform/psp/portdefs.h +++ b/backends/platform/psp/portdefs.h @@ -26,6 +26,12 @@ #ifndef PORTDEFS_H #define PORTDEFS_H +// FIXME: This file is only used when building using the file +// backends/platform/psp/Makefile, but not when building using configure +// && make. So either -DNONSTANDARD_PORT needs to be added to the PSP +// configure rules, or it should be removed from the aforementioned +// Makefile. + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index d24c614e33..b85467f788 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -23,6 +23,20 @@ * */ +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #define USERSPACE_ONLY //don't use kernel mode features #ifndef USERSPACE_ONLY diff --git a/backends/platform/psp/trace.cpp b/backends/platform/psp/trace.cpp index 74c2f64300..92ee7b669e 100644 --- a/backends/platform/psp/trace.cpp +++ b/backends/platform/psp/trace.cpp @@ -23,6 +23,19 @@ * */ +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf #include <pspkernel.h> #include <pspdebug.h> diff --git a/backends/platform/samsungtv/main.cpp b/backends/platform/samsungtv/main.cpp index 3beb97165f..a1962dd904 100644 --- a/backends/platform/samsungtv/main.cpp +++ b/backends/platform/samsungtv/main.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + #include "backends/platform/samsungtv/samsungtv.h" #include "backends/plugins/sdl/sdl-provider.h" #include "base/main.h" diff --git a/backends/platform/sdl/posix/posix-main.cpp b/backends/platform/sdl/posix/posix-main.cpp index 10ed43f43f..9e778ab899 100644 --- a/backends/platform/sdl/posix/posix-main.cpp +++ b/backends/platform/sdl/posix/posix-main.cpp @@ -25,7 +25,7 @@ #include "common/scummsys.h" -#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(LINUXMOTO) && !defined(GP2XWIZ) && !defined(GP2X) && !defined(DINGUX) +#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) #include "backends/platform/sdl/posix/posix.h" #include "backends/plugins/sdl/sdl-provider.h" diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp index 71a88265a0..889bc5cd5e 100644 --- a/backends/platform/sdl/posix/posix.cpp +++ b/backends/platform/sdl/posix/posix.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + #include "common/scummsys.h" #ifdef UNIX @@ -34,6 +36,7 @@ #include <errno.h> #include <sys/stat.h> + OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName) : _baseConfigName(baseConfigName) { diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index dc91bd9fe7..e6ca423f61 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> @@ -32,6 +34,7 @@ #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" #include "common/EventRecorder.h" +#include "common/textconsole.h" #include "backends/saves/default/default-saves.h" #include "backends/audiocd/sdl/sdl-audiocd.h" @@ -125,10 +128,10 @@ void OSystem_SDL::init() { if (_timerManager == 0) _timerManager = new SdlTimerManager(); - #ifdef USE_OPENGL - // Setup a list with both SDL and OpenGL graphics modes - setupGraphicsModes(); - #endif +#ifdef USE_OPENGL + // Setup a list with both SDL and OpenGL graphics modes + setupGraphicsModes(); +#endif } void OSystem_SDL::initBackend() { @@ -148,11 +151,15 @@ void OSystem_SDL::initBackend() { Common::String gfxMode(ConfMan.get("gfx_mode")); bool use_opengl = false; const OSystem::GraphicsMode *mode = OpenGLSdlGraphicsManager::supportedGraphicsModes(); + int i = 0; while (mode->name) { - if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0) + if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0) { + _graphicsMode = i + _sdlModesCount; use_opengl = true; + } mode++; + ++i; } // If the gfx_mode is from OpenGL, create the OpenGL graphics manager @@ -210,6 +217,11 @@ void OSystem_SDL::initSDL() { if (ConfMan.hasKey("disable_sdl_parachute")) sdlFlags |= SDL_INIT_NOPARACHUTE; +#ifdef WEBOS + // WebOS needs this flag or otherwise the application won't start + sdlFlags |= SDL_INIT_VIDEO; +#endif + // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers) if (SDL_Init(sdlFlags) == -1) error("Could not initialize SDL: %s", SDL_GetError()); @@ -369,7 +381,11 @@ void OSystem_SDL::setupIcon() { unsigned int rgba[256]; unsigned int *icon; - sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes); + if (sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes) != 4) { + warning("Wrong format of scummvm_icon[0] (%s)", scummvm_icon[0]); + + return; + } if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) { warning("Could not load the built-in icon (%d %d %d %d)", w, h, ncols, nbytes); return; @@ -384,13 +400,17 @@ void OSystem_SDL::setupIcon() { unsigned char code; char color[32]; unsigned int col; - sscanf(scummvm_icon[1 + i], "%c c %s", &code, color); + if (sscanf(scummvm_icon[1 + i], "%c c %s", &code, color) != 2) { + warning("Wrong format of scummvm_icon[%d] (%s)", 1 + i, scummvm_icon[1 + i]); + } if (!strcmp(color, "None")) col = 0x00000000; else if (!strcmp(color, "black")) col = 0xFF000000; else if (color[0] == '#') { - sscanf(color + 1, "%06x", &col); + if (sscanf(color + 1, "%06x", &col) != 1) { + warning("Wrong format of color (%s)", color + 1); + } col |= 0xFF000000; } else { warning("Could not load the built-in icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]); @@ -464,6 +484,7 @@ int OSystem_SDL::getDefaultGraphicsMode() const { bool OSystem_SDL::setGraphicsMode(int mode) { const OSystem::GraphicsMode *srcMode; int i; + // Check if mode is from SDL or OpenGL if (mode < _sdlModesCount) { srcMode = SdlGraphicsManager::supportedGraphicsModes(); @@ -472,28 +493,34 @@ bool OSystem_SDL::setGraphicsMode(int mode) { srcMode = OpenGLSdlGraphicsManager::supportedGraphicsModes(); i = _sdlModesCount; } + // Loop through modes while (srcMode->name) { if (i == mode) { // If the new mode and the current mode are not from the same graphics // manager, delete and create the new mode graphics manager if (_graphicsMode >= _sdlModesCount && mode < _sdlModesCount) { + debug(1, "switching to plain SDL graphics"); delete _graphicsManager; _graphicsManager = new SdlGraphicsManager(_eventSource); ((SdlGraphicsManager *)_graphicsManager)->initEventObserver(); _graphicsManager->beginGFXTransaction(); } else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) { + debug(1, "switching to OpenGL graphics"); delete _graphicsManager; _graphicsManager = new OpenGLSdlGraphicsManager(); ((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver(); _graphicsManager->beginGFXTransaction(); } + _graphicsMode = mode; return _graphicsManager->setGraphicsMode(srcMode->id); } + i++; srcMode++; } + return false; } diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp index 9459263ae2..fffc3a2a75 100644 --- a/backends/platform/sdl/win32/win32.cpp +++ b/backends/platform/sdl/win32/win32.cpp @@ -27,6 +27,8 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "common/scummsys.h" +#include "common/error.h" +#include "common/textconsole.h" #ifdef WIN32 diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl index 921f384c65..dbced3126a 100644 --- a/backends/platform/symbian/AdaptAllMMPs.pl +++ b/backends/platform/symbian/AdaptAllMMPs.pl @@ -36,6 +36,7 @@ chdir("../../../"); "mmp/scummvm_hugo.mmp", "mmp/scummvm_toon.mmp", "mmp/scummvm_lastexpress.mmp", + "mmp/scummvm_tsage.mmp", # Target Platform Project Files "S60/ScummVM_S60.mmp", "S60v3/ScummVM_S60v3.mmp", @@ -111,7 +112,8 @@ ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, ParseModule("_base", "common", \@section_empty); ParseModule("_base", "gui", \@section_empty, \@excludes_gui); ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics); -ParseModule("_base", "sound", \@section_empty, \@excludes_snd); +ParseModule("_base", "audio", \@section_empty, \@excludes_snd); +ParseModule("_base", "video", \@section_empty); chdir("engines/"); ParseModule("_scumm", "scumm", \@sections_scumm, \@excludes_scumm ); @@ -142,6 +144,7 @@ ParseModule("_mohawk" ,"mohawk", \@section_empty); ParseModule("_hugo" ,"hugo", \@section_empty); ParseModule("_toon" ,"toon", \@section_empty); ParseModule("_lastexpress","lastexpress", \@section_empty); +ParseModule("_tsage","tsage", \@section_empty); print " ======================================================================================= Done. Enjoy :P diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl index 5c127afaa0..cb1c508fa1 100644 --- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl +++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl @@ -4,7 +4,7 @@ @WorkingEngines = qw( scumm agos sky queen gob groovie saga drascula kyra lure agi touche parallaction cine - cruise made m4 tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo toon lastexpress + cruise made m4 tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo toon lastexpress tsage ); @WorkingEngines_1st = qw( @@ -14,9 +14,10 @@ ); @WorkingEngines_2nd = qw( - agos sky gob - kyra lure agi tinsel - sword1 sword2 draci sci teenagent hugo toon + agos sky gob kyra lure + agi tinsel sword1 sword2 + draci sci teenagent hugo toon + tsage ); @TestingEngines = qw( diff --git a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in index c7623d09a8..4e0a66793c 100644 --- a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in @@ -63,8 +63,8 @@ START BITMAP ScummVM.mbm TARGETPATH \Resource\Apps SOURCEPATH ..\res // Source Color-depth Source-bitmap-list -// c denotes whether the bitmap is a colour bitmap and the digits represent the -// colour-depth of the bitmap and the bitmap mask respectively +// c denotes whether the bitmap is a color bitmap and the digits represent the +// color-depth of the bitmap and the bitmap mask respectively SOURCE c24 ScummSmall.bmp SOURCE 8 ScummSmallMask.bmp SOURCE c24 ScummLarge.bmp @@ -91,7 +91,7 @@ STATICLIBRARY esdl.lib // *** Include paths USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\engines -USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\sound +USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version @@ -119,6 +119,7 @@ SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp SOURCE backends\audiocd\sdl\sdl-audiocd.cpp SOURCE backends\audiocd\default\default-audiocd.cpp +SOURCE backends\fs\symbian\symbian-fs.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in index 6f14e858b0..1929723fb6 100644 --- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in @@ -63,8 +63,8 @@ START BITMAP ScummVM.mbm TARGETPATH \Resource\Apps SOURCEPATH ..\res // Source Color-depth Source-bitmap-list -// c denotes whether the bitmap is a colour bitmap and the digits represent the -// colour-depth of the bitmap and the bitmap mask respectively +// c denotes whether the bitmap is a color bitmap and the digits represent the +// color-depth of the bitmap and the bitmap mask respectively SOURCE c24 ScummSmall.bmp SOURCE 8 ScummSmallMask.bmp SOURCE c24 ScummLarge.bmp @@ -91,7 +91,7 @@ STATICLIBRARY esdl.lib // *** Include paths USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\engines -USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\sound +USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl ..\..\..\..\audio SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version @@ -119,6 +119,7 @@ SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp SOURCE backends\audiocd\sdl\sdl-audiocd.cpp SOURCE backends\audiocd\default\default-audiocd.cpp +SOURCE backends\fs\symbian\symbian-fs.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp diff --git a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in index 3fab5cc2b7..f5bdaac237 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in @@ -64,8 +64,8 @@ START BITMAP ScummVM.mbm TARGETPATH \Resource\Apps SOURCEPATH ..\res // Source Color-depth Source-bitmap-list -// c denotes whether the bitmap is a colour bitmap and the digits represent the -// colour-depth of the bitmap and the bitmap mask respectively +// c denotes whether the bitmap is a color bitmap and the digits represent the +// color-depth of the bitmap and the bitmap mask respectively SOURCE c24 ScummSmall.bmp SOURCE 8 ScummSmallMask.bmp SOURCE c24 ScummLarge.bmp @@ -117,6 +117,7 @@ SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp SOURCE backends\audiocd\sdl\sdl-audiocd.cpp SOURCE backends\audiocd\default\default-audiocd.cpp +SOURCE backends\fs\symbian\symbian-fs.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in index 31dfc36399..2354161e47 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in @@ -64,8 +64,8 @@ START BITMAP ScummVM.mbm TARGETPATH \Resource\Apps SOURCEPATH ..\res // Source Color-depth Source-bitmap-list -// c denotes whether the bitmap is a colour bitmap and the digits represent the -// colour-depth of the bitmap and the bitmap mask respectively +// c denotes whether the bitmap is a color bitmap and the digits represent the +// color-depth of the bitmap and the bitmap mask respectively SOURCE c24 ScummSmall.bmp SOURCE 8 ScummSmallMask.bmp SOURCE c24 ScummLarge.bmp @@ -117,6 +117,7 @@ SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp SOURCE backends\audiocd\sdl\sdl-audiocd.cpp SOURCE backends\audiocd\default\default-audiocd.cpp +SOURCE backends\fs\symbian\symbian-fs.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp diff --git a/backends/platform/symbian/mmp/scummvm_agi.mmp.in b/backends/platform/symbian/mmp/scummvm_agi.mmp.in index 044326405d..e2d98b9ae4 100644 --- a/backends/platform/symbian/mmp/scummvm_agi.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_agi.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\agi // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_agos.mmp.in b/backends/platform/symbian/mmp/scummvm_agos.mmp.in index e2d1e5eff4..077111d783 100644 --- a/backends/platform/symbian/mmp/scummvm_agos.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_agos.mmp.in @@ -65,6 +65,6 @@ SOURCEPATH ..\..\..\..\engines\agos // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in index d25cef4ffe..2b74bca42b 100644 --- a/backends/platform/symbian/mmp/scummvm_base.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in @@ -51,7 +51,7 @@ ALWAYS_BUILD_AS_ARM // *** Include paths -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl SYSTEMINCLUDE \epoc32\include\ESDL @@ -95,12 +95,12 @@ SOURCEPATH ..\..\..\..\gui //SOURCE KeysDialog.cpp //SOURCE Actions.cpp -SOURCEPATH ..\..\..\..\sound -//START_AUTO_OBJECTS_SOUND_// +SOURCEPATH ..\..\..\..\audio +//START_AUTO_OBJECTS_AUDIO_// // empty base file, will be updated by Perl build scripts -//STOP_AUTO_OBJECTS_SOUND_// +//STOP_AUTO_OBJECTS_AUDIO_// SOURCE softsynth\fmtowns_pc98\towns_pc98_fmsynth.cpp // Included since its excluded by filter #if defined (WINS) @@ -110,6 +110,12 @@ SOURCE rate_arm.cpp // ARM version: add ASM .cpp wrapper SOURCE rate_arm_asm.s // ARM version: add ASM routines #endif +SOURCEPATH ..\..\..\..\video +//START_AUTO_OBJECTS_VIDEO_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_VIDEO_// // add a few files manually, since they are not parsed from modules.mk files SOURCEPATH ..\..\..\.. diff --git a/backends/platform/symbian/mmp/scummvm_cine.mmp.in b/backends/platform/symbian/mmp/scummvm_cine.mmp.in index d114ec554b..2c8118ef13 100644 --- a/backends/platform/symbian/mmp/scummvm_cine.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_cine.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\cine // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in index e4c836a68b..b43a867da3 100644 --- a/backends/platform/symbian/mmp/scummvm_cruise.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_cruise.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\cruise // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_draci.mmp.in b/backends/platform/symbian/mmp/scummvm_draci.mmp.in index b10eb0b5a8..9f24927f27 100644 --- a/backends/platform/symbian/mmp/scummvm_draci.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_draci.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\draci // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in index 529eeb9e0b..d8cc6da6ae 100644 --- a/backends/platform/symbian/mmp/scummvm_drascula.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_drascula.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\drascula // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_gob.mmp.in b/backends/platform/symbian/mmp/scummvm_gob.mmp.in index fa2ce0dedf..ce94f85283 100644 --- a/backends/platform/symbian/mmp/scummvm_gob.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_gob.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\gob // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in index 7a03cc1745..7229edf4aa 100644 --- a/backends/platform/symbian/mmp/scummvm_groovie.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_groovie.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\groovie // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in index 301d23cab4..b3f9edd1e6 100644 --- a/backends/platform/symbian/mmp/scummvm_hugo.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_hugo.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\hugo // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in index 5fa5fdac6a..654632c229 100644 --- a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in @@ -65,5 +65,5 @@ SOURCEPATH ..\..\..\..\engines\kyra // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in index a297137f02..418730c064 100644 --- a/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_lastexpress.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\lastexpress // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_lure.mmp.in b/backends/platform/symbian/mmp/scummvm_lure.mmp.in index c4a3900a05..e1a63b602b 100644 --- a/backends/platform/symbian/mmp/scummvm_lure.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_lure.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\lure // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_m4.mmp.in b/backends/platform/symbian/mmp/scummvm_m4.mmp.in index f4430f2e58..c2e1ce4e8b 100644 --- a/backends/platform/symbian/mmp/scummvm_m4.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_m4.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\m4 // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_made.mmp.in b/backends/platform/symbian/mmp/scummvm_made.mmp.in index bf50157224..91b9ca756d 100644 --- a/backends/platform/symbian/mmp/scummvm_made.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_made.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\made // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in index 78e931b06f..0edba5eb4d 100644 --- a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\mohawk // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in index e96ab907cd..744a756f4e 100644 --- a/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_parallaction.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\parallaction // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_queen.mmp.in b/backends/platform/symbian/mmp/scummvm_queen.mmp.in index 4f9d9319e0..bf88744701 100644 --- a/backends/platform/symbian/mmp/scummvm_queen.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_queen.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\queen // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_saga.mmp.in b/backends/platform/symbian/mmp/scummvm_saga.mmp.in index e5beefc0c5..a95ee1e7fd 100644 --- a/backends/platform/symbian/mmp/scummvm_saga.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_saga.mmp.in @@ -71,5 +71,5 @@ SOURCEPATH ..\..\..\..\engines\saga // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in index eb0d1b020f..ca9e712f3f 100644 --- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\sci // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in index 6b5d249422..0a3cd9bb7d 100644 --- a/backends/platform/symbian/mmp/scummvm_scumm.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_scumm.mmp.in @@ -82,7 +82,7 @@ SOURCE smush/codec47ARM.s // ARM version: add ASM routines // *** Include paths USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\scumm\smush ..\..\..\..\engines\scumm\insane -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc diff --git a/backends/platform/symbian/mmp/scummvm_sky.mmp.in b/backends/platform/symbian/mmp/scummvm_sky.mmp.in index d1d222b1fa..1bc2301745 100644 --- a/backends/platform/symbian/mmp/scummvm_sky.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sky.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sky // *** Include paths USERINCLUDE ..\..\..\..\engines ..\..\..\..\engines\sky\music -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in index 0aaf9d504b..6bf543070b 100644 --- a/backends/platform/symbian/mmp/scummvm_sword1.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sword1.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sword1 // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in index 4a7181709f..cee4143f94 100644 --- a/backends/platform/symbian/mmp/scummvm_sword2.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sword2.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\sword2 // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in index 7832fc4880..fa4ef79692 100644 --- a/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_teenagent.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\teenagent // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in index 6190ec8152..569b79ba3c 100644 --- a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in @@ -59,5 +59,5 @@ SOURCEPATH ..\..\..\..\engines\tinsel // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_toon.mmp.in b/backends/platform/symbian/mmp/scummvm_toon.mmp.in index f2301c4ae2..f309e6d0fa 100644 --- a/backends/platform/symbian/mmp/scummvm_toon.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_toon.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\toon // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_touche.mmp.in b/backends/platform/symbian/mmp/scummvm_touche.mmp.in index 9e4c3d0496..ab42afe304 100644 --- a/backends/platform/symbian/mmp/scummvm_touche.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_touche.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\touche // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_tsage.mmp.in b/backends/platform/symbian/mmp/scummvm_tsage.mmp.in new file mode 100644 index 0000000000..8265d9e772 --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_tsage.mmp.in @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL + * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System + * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer + * Copyright (C) 2005-2011 The ScummVM project + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_tsage.lib +TARGETTYPE lib +OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp +OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings +OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char +ALWAYS_BUILD_AS_ARM + +//START_AUTO_MACROS_SLAVE// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_MACROS_SLAVE// + +// *** SOURCE files + +SOURCEPATH ..\..\..\..\engines\tsage + +//START_AUTO_OBJECTS_TSAGE_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_TSAGE_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in index d193ac49a9..434072bc96 100644 --- a/backends/platform/symbian/mmp/scummvm_tucker.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_tucker.mmp.in @@ -59,6 +59,6 @@ SOURCEPATH ..\..\..\..\engines\tucker // *** Include paths USERINCLUDE ..\..\..\..\engines -USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\audio ..\src SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h index 1c5de2d43c..e8a620475e 100644 --- a/backends/platform/symbian/src/portdefs.h +++ b/backends/platform/symbian/src/portdefs.h @@ -35,6 +35,11 @@ #include <e32std.h> #include <math.h> +/* define pi */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif /* M_PI */ + #define DISABLE_COMMAND_LINE #if defined(USE_TREMOR) && !defined(USE_VORBIS) diff --git a/backends/platform/symbian/src/vsnprintf.h b/backends/platform/symbian/src/vsnprintf.h index 5a9c836ea3..6e75719d55 100644 --- a/backends/platform/symbian/src/vsnprintf.h +++ b/backends/platform/symbian/src/vsnprintf.h @@ -1,8 +1,11 @@ /* - * This is the vsnprintf for scummvm/symbian implementation from the original snprintf.c, - * all support functions has been removed and vsnprintf renamed to symbian_vsnprintf + * This is the vsnprintf for scummvm/symbian implementation from the original + * snprintf.c, all support functions has been removed and vsnprintf renamed to + * symbian_vsnprintf + * According to the homepage this function may be licensed under either the + * Frontier Artistic License or the GPL. + * * snprintf.c - a portable implementation of snprintf - * According to the homepage this function could be licensed as either Frontier Aritistic or GPL. * * AUTHOR * Mark Martinec <mark.martinec@ijs.si>, April 1999. @@ -244,13 +247,14 @@ int symbian_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ /* but the following code achieves better performance for cases * where format string is long and contains few conversions */ - const char *q = strchr(p+1,'%'); - size_t n = !q ? strlen(p) : (q-p); + const char *q = strchr(p + 1, '%'); + size_t n = !q ? strlen(p) : (q - p); if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, p, (n>avail?avail:n)); + size_t avail = str_m - str_l; + fast_memcpy(str + str_l, p, (n > avail ? avail : n)); } - p += n; str_l += n; + p += n; + str_l += n; } else { const char *starting_p; size_t min_field_width = 0, precision = 0; @@ -262,398 +266,453 @@ int symbian_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { char tmp[32];/* temporary buffer for simple numeric->string conversion */ const char *str_arg; /* string address in case of string argument */ - size_t str_arg_l; /* natural field width of arg without padding + size_t str_arg_l; /* natural field width of arg without padding and sign */ - unsigned char uchar_arg; - /* unsigned char argument value - only defined for c conversion. - N.B. standard explicitly states the char argument for - the c conversion is unsigned */ + unsigned char uchar_arg; + /* unsigned char argument value - only defined for c conversion. + N.B. standard explicitly states the char argument for + the c conversion is unsigned */ - size_t number_of_zeros_to_pad = 0; - /* number of zeros to be inserted for numeric conversions - as required by the precision or minimal field width */ + size_t number_of_zeros_to_pad = 0; + /* number of zeros to be inserted for numeric conversions + as required by the precision or minimal field width */ - size_t zero_padding_insertion_ind = 0; - /* index into tmp where zero padding is to be inserted */ + size_t zero_padding_insertion_ind = 0; + /* index into tmp where zero padding is to be inserted */ - char fmt_spec = '\0'; - /* current conversion specifier character */ + char fmt_spec = '\0'; + /* current conversion specifier character */ - str_arg = credits;/* just to make compiler happy (defined but not used)*/ - str_arg = NULL; - starting_p = p; p++; /* skip '%' */ - /* parse flags */ - while (*p == '0' || *p == '-' || *p == '+' || - *p == ' ' || *p == '#' || *p == '\'') { - switch (*p) { - case '0': zero_padding = 1; break; - case '-': justify_left = 1; break; - case '+': force_sign = 1; space_for_positive = 0; break; - case ' ': force_sign = 1; - /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ - break; - case '#': alternate_form = 1; break; - case '\'': break; - } - p++; - } - /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ + str_arg = credits;/* just to make compiler happy (defined but not used)*/ + str_arg = NULL; + starting_p = p; + p++; /* skip '%' */ + /* parse flags */ + while (*p == '0' || *p == '-' || *p == '+' || + *p == ' ' || *p == '#' || *p == '\'') { + switch (*p) { + case '0': + zero_padding = 1; + break; + case '-': + justify_left = 1; + break; + case '+': + force_sign = 1; + space_for_positive = 0; + break; + case ' ': + force_sign = 1; + /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ + break; + case '#': + alternate_form = 1; + break; + case '\'': + break; + } + p++; + } + /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ - /* parse field width */ - if (*p == '*') { - int j; - p++; j = va_arg(ap, int); - if (j >= 0) min_field_width = j; - else { min_field_width = -j; justify_left = 1; } - } else if (isdigit((int)(*p))) { - /* size_t could be wider than unsigned int; - make sure we treat argument like common implementations do */ - unsigned int uj = *p++ - '0'; - while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); - min_field_width = uj; - } - /* parse precision */ - if (*p == '.') { - p++; precision_specified = 1; - if (*p == '*') { - int j = va_arg(ap, int); - p++; - if (j >= 0) precision = j; - else { - precision_specified = 0; precision = 0; - /* NOTE: - * Solaris 2.6 man page claims that in this case the precision - * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page - * claim that this case should be treated as unspecified precision, - * which is what we do here. - */ - } - } else if (isdigit((int)(*p))) { - /* size_t could be wider than unsigned int; - make sure we treat argument like common implementations do */ - unsigned int uj = *p++ - '0'; - while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); - precision = uj; - } - } - /* parse 'h', 'l' and 'll' length modifiers */ - if (*p == 'h' || *p == 'l') { - length_modifier = *p; p++; - if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ + /* parse field width */ + if (*p == '*') { + int j; + p++; + j = va_arg(ap, int); + if (j >= 0) min_field_width = j; + else { min_field_width = -j; justify_left = 1; } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10 * uj + (unsigned int)(*p++ - '0'); + min_field_width = uj; + } + /* parse precision */ + if (*p == '.') { + p++; + precision_specified = 1; + if (*p == '*') { + int j = va_arg(ap, int); + p++; + if (j >= 0) precision = j; + else { + precision_specified = 0; + precision = 0; + /* NOTE: + * Solaris 2.6 man page claims that in this case the precision + * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page + * claim that this case should be treated as unspecified precision, + * which is what we do here. + */ + } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10 * uj + (unsigned int)(*p++ - '0'); + precision = uj; + } + } + /* parse 'h', 'l' and 'll' length modifiers */ + if (*p == 'h' || *p == 'l') { + length_modifier = *p; + p++; + if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ #ifdef SNPRINTF_LONGLONG_SUPPORT - length_modifier = '2'; /* double l encoded as '2' */ + length_modifier = '2'; /* double l encoded as '2' */ #else - length_modifier = 'l'; /* treat it as a single 'l' */ + length_modifier = 'l'; /* treat it as a single 'l' */ #endif - p++; - } - } - fmt_spec = *p; - /* common synonyms: */ - switch (fmt_spec) { - case 'i': fmt_spec = 'd'; break; - case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; - case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; - case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - default: break; - } - /* get parameter value, do initial processing */ - switch (fmt_spec) { - case '%': /* % behaves similar to 's' regarding flags and field widths */ - case 'c': /* c behaves similar to 's' regarding flags and field widths */ - case 's': - length_modifier = '\0'; /* wint_t and wchar_t not supported */ - /* the result of zero padding flag with non-numeric conversion specifier*/ - /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ - /* Digital Unix and Linux does not. */ - zero_padding = 0; /* turn zero padding off for string conversions */ - str_arg_l = 1; - switch (fmt_spec) { - case '%': - str_arg = p; break; - case 'c': { - int j = va_arg(ap, int); - uchar_arg = (unsigned char) j; /* standard demands unsigned char */ - str_arg = (const char *) &uchar_arg; - break; - } - case 's': - str_arg = va_arg(ap, const char *); - if (!str_arg) str_arg_l = 0; - /* make sure not to address string beyond the specified precision !!! */ - else if (!precision_specified) str_arg_l = strlen(str_arg); - /* truncate string if necessary as requested by precision */ - else if (precision == 0) str_arg_l = 0; - else { - /* memchr on HP does not like n > 2^31 !!! */ - const char *q = (const char*) memchr(str_arg, '\0', - precision <= 0x7fffffff ? precision : 0x7fffffff); - str_arg_l = !q ? precision : (q-str_arg); - } - break; - default: break; - } - break; - case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { - /* NOTE: the u, o, x, X and p conversion specifiers imply - the value is unsigned; d implies a signed value */ + p++; + } + } + fmt_spec = *p; + /* common synonyms: */ + switch (fmt_spec) { + case 'i': + fmt_spec = 'd'; + break; + case 'D': + fmt_spec = 'd'; + length_modifier = 'l'; + break; + case 'U': + fmt_spec = 'u'; + length_modifier = 'l'; + break; + case 'O': + fmt_spec = 'o'; + length_modifier = 'l'; + break; + default: + break; + } + /* get parameter value, do initial processing */ + switch (fmt_spec) { + case '%': /* % behaves similar to 's' regarding flags and field widths */ + case 'c': /* c behaves similar to 's' regarding flags and field widths */ + case 's': + length_modifier = '\0'; /* wint_t and wchar_t not supported */ + /* the result of zero padding flag with non-numeric conversion specifier*/ + /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ + /* Digital Unix and Linux does not. */ + zero_padding = 0; /* turn zero padding off for string conversions */ + str_arg_l = 1; + switch (fmt_spec) { + case '%': + str_arg = p; + break; + case 'c': { + int j = va_arg(ap, int); + uchar_arg = (unsigned char) j; /* standard demands unsigned char */ + str_arg = (const char *) & uchar_arg; + break; + } + case 's': + str_arg = va_arg(ap, const char *); + if (!str_arg) str_arg_l = 0; + /* make sure not to address string beyond the specified precision !!! */ + else if (!precision_specified) str_arg_l = strlen(str_arg); + /* truncate string if necessary as requested by precision */ + else if (precision == 0) str_arg_l = 0; + else { + /* memchr on HP does not like n > 2^31 !!! */ + const char *q = (const char*) memchr(str_arg, '\0', + precision <= 0x7fffffff ? precision : 0x7fffffff); + str_arg_l = !q ? precision : (q - str_arg); + } + break; + default: + break; + } + break; + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': + case 'p': { + /* NOTE: the u, o, x, X and p conversion specifiers imply + the value is unsigned; d implies a signed value */ - int arg_sign = 0; - /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), - +1 if greater than zero (or nonzero for unsigned arguments), - -1 if negative (unsigned argument is never negative) */ + int arg_sign = 0; + /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), + +1 if greater than zero (or nonzero for unsigned arguments), + -1 if negative (unsigned argument is never negative) */ - int int_arg = 0; unsigned int uint_arg = 0; - /* only defined for length modifier h, or for no length modifiers */ + int int_arg = 0; + unsigned int uint_arg = 0; + /* only defined for length modifier h, or for no length modifiers */ - long int long_arg = 0; unsigned long int ulong_arg = 0; - /* only defined for length modifier l */ + long int long_arg = 0; + unsigned long int ulong_arg = 0; + /* only defined for length modifier l */ - void *ptr_arg = NULL; - /* pointer argument value -only defined for p conversion */ + void *ptr_arg = NULL; + /* pointer argument value -only defined for p conversion */ #ifdef SNPRINTF_LONGLONG_SUPPORT - long long int long_long_arg = 0; - unsigned long long int ulong_long_arg = 0; - /* only defined for length modifier ll */ + long long int long_long_arg = 0; + unsigned long long int ulong_long_arg = 0; + /* only defined for length modifier ll */ #endif - if (fmt_spec == 'p') { - /* HPUX 10: An l, h, ll or L before any other conversion character - * (other than d, i, u, o, x, or X) is ignored. - * Digital Unix: - * not specified, but seems to behave as HPUX does. - * Solaris: If an h, l, or L appears before any other conversion - * specifier (other than d, i, u, o, x, or X), the behavior - * is undefined. (Actually %hp converts only 16-bits of address - * and %llp treats address as 64-bit data which is incompatible - * with (void *) argument on a 32-bit system). - */ - length_modifier = '\0'; - ptr_arg = va_arg(ap, void *); - if (ptr_arg != NULL) arg_sign = 1; - } else if (fmt_spec == 'd') { /* signed */ - switch (length_modifier) { - case '\0': - case 'h': - /* It is non-portable to specify a second argument of char or short - * to va_arg, because arguments seen by the called function - * are not char or short. C converts char and short arguments - * to int before passing them to a function. - */ - int_arg = va_arg(ap, int); - if (int_arg > 0) arg_sign = 1; - else if (int_arg < 0) arg_sign = -1; - break; - case 'l': - long_arg = va_arg(ap, long int); - if (long_arg > 0) arg_sign = 1; - else if (long_arg < 0) arg_sign = -1; - break; + if (fmt_spec == 'p') { + /* HPUX 10: An l, h, ll or L before any other conversion character + * (other than d, i, u, o, x, or X) is ignored. + * Digital Unix: + * not specified, but seems to behave as HPUX does. + * Solaris: If an h, l, or L appears before any other conversion + * specifier (other than d, i, u, o, x, or X), the behavior + * is undefined. (Actually %hp converts only 16-bits of address + * and %llp treats address as 64-bit data which is incompatible + * with (void *) argument on a 32-bit system). + */ + length_modifier = '\0'; + ptr_arg = va_arg(ap, void *); + if (ptr_arg != NULL) arg_sign = 1; + } else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': + /* It is non-portable to specify a second argument of char or short + * to va_arg, because arguments seen by the called function + * are not char or short. C converts char and short arguments + * to int before passing them to a function. + */ + int_arg = va_arg(ap, int); + if (int_arg > 0) arg_sign = 1; + else if (int_arg < 0) arg_sign = -1; + break; + case 'l': + long_arg = va_arg(ap, long int); + if (long_arg > 0) arg_sign = 1; + else if (long_arg < 0) arg_sign = -1; + break; #ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': - long_long_arg = va_arg(ap, long long int); - if (long_long_arg > 0) arg_sign = 1; - else if (long_long_arg < 0) arg_sign = -1; - break; + case '2': + long_long_arg = va_arg(ap, long long int); + if (long_long_arg > 0) arg_sign = 1; + else if (long_long_arg < 0) arg_sign = -1; + break; #endif - } - } else { /* unsigned */ - switch (length_modifier) { - case '\0': - case 'h': - uint_arg = va_arg(ap, unsigned int); - if (uint_arg) arg_sign = 1; - break; - case 'l': - ulong_arg = va_arg(ap, unsigned long int); - if (ulong_arg) arg_sign = 1; - break; + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': + uint_arg = va_arg(ap, unsigned int); + if (uint_arg) arg_sign = 1; + break; + case 'l': + ulong_arg = va_arg(ap, unsigned long int); + if (ulong_arg) arg_sign = 1; + break; #ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': - ulong_long_arg = va_arg(ap, unsigned long long int); - if (ulong_long_arg) arg_sign = 1; - break; + case '2': + ulong_long_arg = va_arg(ap, unsigned long long int); + if (ulong_long_arg) arg_sign = 1; + break; #endif - } - } - str_arg = tmp; str_arg_l = 0; - /* NOTE: - * For d, i, u, o, x, and X conversions, if precision is specified, - * the '0' flag should be ignored. This is so with Solaris 2.6, - * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - */ - if (precision_specified) zero_padding = 0; - if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; - /* leave negative numbers for sprintf to handle, - to avoid handling tricky cases like (short int)(-32768) */ - } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) - { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } - /* alternate form should have no effect for p conversion, but ... */ - } - zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) precision = 1; /* default precision is 1 */ - if (precision == 0 && arg_sign == 0 - ) { - /* converted to null string */ - /* When zero value is formatted with an explicit precision 0, - the resulting formatted string is empty (d, i, u, o, x, X, p). */ - } else { - char f[5]; int f_l = 0; - f[f_l++] = '%'; /* construct a simple format string for sprintf */ - if (!length_modifier) { } - else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } - else f[f_l++] = length_modifier; - f[f_l++] = fmt_spec; f[f_l++] = '\0'; - if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); - else if (fmt_spec == 'd') { /* signed */ - switch (length_modifier) { - case '\0': - case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; - case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; + } + } + str_arg = tmp; + str_arg_l = 0; + /* NOTE: + * For d, i, u, o, x, and X conversions, if precision is specified, + * the '0' flag should be ignored. This is so with Solaris 2.6, + * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. + */ + if (precision_specified) zero_padding = 0; + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + /* leave negative numbers for sprintf to handle, + to avoid handling tricky cases like (short int)(-32768) */ + } else if (alternate_form) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X')) + { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } + /* alternate form should have no effect for p conversion, but ... */ + } + zero_padding_insertion_ind = str_arg_l; + if (!precision_specified) precision = 1; /* default precision is 1 */ + if (precision == 0 && arg_sign == 0 + ) { + /* converted to null string */ + /* When zero value is formatted with an explicit precision 0, + the resulting formatted string is empty (d, i, u, o, x, X, p). */ + } else { + char f[5]; + int f_l = 0; + f[f_l++] = '%'; /* construct a simple format string for sprintf */ + if (!length_modifier) { } else if (length_modifier == '2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } else f[f_l++] = length_modifier; + f[f_l++] = fmt_spec; + f[f_l++] = '\0'; + if (fmt_spec == 'p') str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); + else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': + str_arg_l += sprintf(tmp + str_arg_l, f, int_arg); + break; + case 'l': + str_arg_l += sprintf(tmp + str_arg_l, f, long_arg); + break; #ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; + case '2': + str_arg_l += sprintf(tmp + str_arg_l, f, long_long_arg); + break; #endif - } - } else { /* unsigned */ - switch (length_modifier) { - case '\0': - case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; - case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': + str_arg_l += sprintf(tmp + str_arg_l, f, uint_arg); + break; + case 'l': + str_arg_l += sprintf(tmp + str_arg_l, f, ulong_arg); + break; #ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; + case '2': + str_arg_l += sprintf(tmp + str_arg_l, f, ulong_long_arg); + break; #endif - } - } - /* include the optional minus sign and possible "0x" - in the region before the zero padding insertion point */ - if (zero_padding_insertion_ind < str_arg_l && - tmp[zero_padding_insertion_ind] == '-') { - zero_padding_insertion_ind++; - } - if (zero_padding_insertion_ind+1 < str_arg_l && - tmp[zero_padding_insertion_ind] == '0' && - (tmp[zero_padding_insertion_ind+1] == 'x' || - tmp[zero_padding_insertion_ind+1] == 'X') ) { - zero_padding_insertion_ind += 2; - } - } - { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; - if (alternate_form && fmt_spec == 'o' - /* unless zero is already the first character */ - && !(zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '0') - ) { /* assure leading zero for alternate-form octal numbers */ - if (!precision_specified || precision < num_of_digits+1) { - /* precision is increased to force the first character to be zero, - except if a zero value is formatted with an explicit precision - of zero */ - precision = num_of_digits+1; precision_specified = 1; - } - } - /* zero padding to specified precision? */ - if (num_of_digits < precision) - number_of_zeros_to_pad = precision - num_of_digits; - } - /* zero padding to specified minimal field width? */ - if (!justify_left && zero_padding) { - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) number_of_zeros_to_pad += n; - } - break; - } - default: /* unrecognized conversion specifier, keep format string as-is*/ - zero_padding = 0; /* turn zero padding off for non-numeric convers. */ - justify_left = 1; min_field_width = 0; /* reset flags */ - /* discard the unrecognized conversion, just keep * - * the unrecognized conversion character */ - str_arg = p; str_arg_l = 0; - if (*p) str_arg_l++; /* include invalid conversion specifier unchanged + } + } + /* include the optional minus sign and possible "0x" + in the region before the zero padding insertion point */ + if (zero_padding_insertion_ind < str_arg_l && + tmp[zero_padding_insertion_ind] == '-') { + zero_padding_insertion_ind++; + } + if (zero_padding_insertion_ind + 1 < str_arg_l && + tmp[zero_padding_insertion_ind] == '0' && + (tmp[zero_padding_insertion_ind+1] == 'x' || + tmp[zero_padding_insertion_ind+1] == 'X')) { + zero_padding_insertion_ind += 2; + } + } + { + size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; + if (alternate_form && fmt_spec == 'o' + /* unless zero is already the first character */ + && !(zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '0') + ) { /* assure leading zero for alternate-form octal numbers */ + if (!precision_specified || precision < num_of_digits + 1) { + /* precision is increased to force the first character to be zero, + except if a zero value is formatted with an explicit precision + of zero */ + precision = num_of_digits + 1; + precision_specified = 1; + } + } + /* zero padding to specified precision? */ + if (num_of_digits < precision) + number_of_zeros_to_pad = precision - num_of_digits; + } + /* zero padding to specified minimal field width? */ + if (!justify_left && zero_padding) { + int n = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (n > 0) number_of_zeros_to_pad += n; + } + break; + } + default: /* unrecognized conversion specifier, keep format string as-is*/ + zero_padding = 0; /* turn zero padding off for non-numeric convers. */ + justify_left = 1; + min_field_width = 0; /* reset flags */ + /* discard the unrecognized conversion, just keep * + * the unrecognized conversion character */ + str_arg = p; + str_arg_l = 0; + if (*p) str_arg_l++; /* include invalid conversion specifier unchanged if not at end-of-string */ - break; - } - if (*p) p++; /* step over the just processed conversion specifier */ - /* insert padding to the left as requested by min_field_width; - this does not include the zero padding in case of numerical conversions*/ - if (!justify_left) { /* left padding with blank or zero */ - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); - } - str_l += n; - } - } - /* zero padding as requested by the precision or by the minimal field width - * for numeric conversions required? */ - if (number_of_zeros_to_pad <= 0) { - /* will not copy first part of numeric right now, * - * force it to be copied later in its entirety */ - zero_padding_insertion_ind = 0; - } else { - /* insert first part of numerics (sign or '0x') before zero padding */ - int n = zero_padding_insertion_ind; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); - } - str_l += n; - } - /* insert zero padding as requested by the precision or min field width */ - n = number_of_zeros_to_pad; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, '0', (n>avail?avail:n)); - } - str_l += n; - } - } - /* insert formatted string - * (or as-is conversion specifier for unknown conversions) */ - { int n = str_arg_l - zero_padding_insertion_ind; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, - (n>avail?avail:n)); - } - str_l += n; - } - } - /* insert right padding */ - if (justify_left) { /* right blank padding to the field width */ - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, ' ', (n>avail?avail:n)); - } - str_l += n; - } - } - } - } - if (str_m > 0) { /* make sure the string is null-terminated + break; + } + if (*p) p++; /* step over the just processed conversion specifier */ + /* insert padding to the left as requested by min_field_width; + this does not include the zero padding in case of numerical conversions*/ + if (!justify_left) { /* left padding with blank or zero */ + int n = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m - str_l; + fast_memset(str + str_l, (zero_padding ? '0' : ' '), (n > avail ? avail : n)); + } + str_l += n; + } + } + /* zero padding as requested by the precision or by the minimal field width + * for numeric conversions required? */ + if (number_of_zeros_to_pad <= 0) { + /* will not copy first part of numeric right now, * + * force it to be copied later in its entirety */ + zero_padding_insertion_ind = 0; + } else { + /* insert first part of numerics (sign or '0x') before zero padding */ + int n = zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m - str_l; + fast_memcpy(str + str_l, str_arg, (n > avail ? avail : n)); + } + str_l += n; + } + /* insert zero padding as requested by the precision or min field width */ + n = number_of_zeros_to_pad; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m - str_l; + fast_memset(str + str_l, '0', (n > avail ? avail : n)); + } + str_l += n; + } + } + /* insert formatted string + * (or as-is conversion specifier for unknown conversions) */ + { + int n = str_arg_l - zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m - str_l; + fast_memcpy(str + str_l, str_arg + zero_padding_insertion_ind, + (n > avail ? avail : n)); + } + str_l += n; + } + } + /* insert right padding */ + if (justify_left) { /* right blank padding to the field width */ + int n = min_field_width - (str_arg_l + number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m - str_l; + fast_memset(str + str_l, ' ', (n > avail ? avail : n)); + } + str_l += n; + } + } + } + } + if (str_m > 0) { /* make sure the string is null-terminated even at the expense of overwriting the last character (shouldn't happen, but just in case) */ - str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; - } - /* Return the number of characters formatted (excluding trailing null - * character), that is, the number of characters that would have been - * written to the buffer if it were large enough. - * - * The value of str_l should be returned, but str_l is of unsigned type - * size_t, and snprintf is int, possibly leading to an undetected - * integer overflow, resulting in a negative return value, which is illegal. - * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. - * Should errno be set to EOVERFLOW and EOF returned in this case??? - */ - return (int) str_l; + str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; + } + /* Return the number of characters formatted (excluding trailing null + * character), that is, the number of characters that would have been + * written to the buffer if it were large enough. + * + * The value of str_l should be returned, but str_l is of unsigned type + * size_t, and snprintf is int, possibly leading to an undetected + * integer overflow, resulting in a negative return value, which is illegal. + * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. + * Should errno be set to EOVERFLOW and EOF returned in this case??? + */ + return (int) str_l; } int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...) { diff --git a/backends/platform/webos/main.cpp b/backends/platform/webos/main.cpp new file mode 100644 index 0000000000..eefdd30496 --- /dev/null +++ b/backends/platform/webos/main.cpp @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + +#include "backends/platform/webos/webos.h" +#include "backends/plugins/sdl/sdl-provider.h" +#include "base/main.h" + +#if defined(WEBOS) + +#include <unistd.h> + +int main(int argc, char* argv[]) { + g_system = new OSystem_SDL_WebOS(); + assert(g_system); + + ((OSystem_SDL_WebOS *)g_system)->init(); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + + // Free OSystem + delete (OSystem_SDL_WebOS *)g_system; + + return res; +} + +#endif diff --git a/backends/platform/webos/module.mk b/backends/platform/webos/module.mk new file mode 100644 index 0000000000..fe4ec1e079 --- /dev/null +++ b/backends/platform/webos/module.mk @@ -0,0 +1,10 @@ +MODULE := backends/platform/webos + +MODULE_OBJS := \ + main.o \ + webos.o + +# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. +MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) +OBJS := $(MODULE_OBJS) $(OBJS) +MODULE_DIRS += $(sort $(dir $(MODULE_OBJS))) diff --git a/backends/platform/webos/webos.cpp b/backends/platform/webos/webos.cpp new file mode 100644 index 0000000000..7db17f4b9f --- /dev/null +++ b/backends/platform/webos/webos.cpp @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/platform/webos/webos.h" +#include "backends/events/webossdl/webossdl-events.h" +#include "backends/keymapper/keymapper.h" + +#if defined(WEBOS) + +using namespace Common; + +OSystem_SDL_WebOS::OSystem_SDL_WebOS() + : + OSystem_POSIX() { +} + +/** + * Initializes the backend. + */ +void OSystem_SDL_WebOS::initBackend() { + // Create the events manager + if (_eventSource == 0) + _eventSource = new WebOSSdlEventSource(); + + // Call parent implementation of this method + OSystem_SDL::initBackend(); +} + +/** + * Gets the original SDL hardware key set, adds WebOS specific keys and + * returns the new key set. + * + * @return The hardware key set with added webOS specific keys. + */ +HardwareKeySet *OSystem_SDL_WebOS::getHardwareKeySet() { +#ifdef ENABLE_KEYMAPPER + // Get the original SDL hardware key set + HardwareKeySet *keySet = OSystem_SDL::getHardwareKeySet(); + + // Add WebOS specific keys + keySet->addHardwareKey(new HardwareKey("FORWARD", + KeyState((KeyCode) 229, 229, 0), "Forward", kActionKeyType)); + + // Return the modified hardware key set + return keySet; +#else + return 0; +#endif +} + +#endif diff --git a/backends/plugins/dc/dc-provider.h b/backends/platform/webos/webos.h index 55413ade5a..1cdba703e0 100644 --- a/backends/plugins/dc/dc-provider.h +++ b/backends/platform/webos/webos.h @@ -23,20 +23,18 @@ * */ -#ifndef BACKENDS_PLUGINS_DC_H -#define BACKENDS_PLUGINS_DC_H +#ifndef PLATFORM_SDL_WEBOS_H +#define PLATFORM_SDL_WEBOS_H -#include "base/plugins.h" +#include "common/system.h" +#include "backends/platform/sdl/posix/posix.h" -#if defined(DYNAMIC_MODULES) && defined(__DC__) +class OSystem_SDL_WebOS : public OSystem_POSIX { +public: + OSystem_SDL_WebOS(); -class DCPluginProvider : public FilePluginProvider { -protected: - Plugin* createPlugin(const Common::FSNode &node) const; - - bool isPluginFilename(const Common::FSNode &node) const; + virtual void initBackend(); + virtual Common::HardwareKeySet *getHardwareKeySet(); }; -#endif // defined(DYNAMIC_MODULES) && defined(__DC__) - #endif diff --git a/backends/platform/webos/webos.mk b/backends/platform/webos/webos.mk new file mode 100644 index 0000000000..2b145b00c9 --- /dev/null +++ b/backends/platform/webos/webos.mk @@ -0,0 +1,91 @@ +# WebOS specific build targets +# ============================================================================ +# +# Build instructions: +# +# 1. Install the WebOS SDK and PDK and setup the environment variables +# WEBOS_SDK and WEBOS_PDK accordingly. +# +# 2. Cross-compile zlib, flac, mad and tremor and install it into the PDK. +# +# 3. Prepare the ScummVM source for a webOS build: +# $ ./configure --host=webos --enable-plugins --default-dynamic \ +# --enable-release +# +# 4. Create the package: +# $ make package +# +# The package is now in the "portdist" folder. +# +# See http://wiki.scummvm.org/index.php/Compiling_ScummVM/WebOS for +# more detailed build instructions. +# +# +# Palm App catalog instructions: +# +# VER_PACKAGE must be set to a number which is higher than the currently +# used package version in the app catalog. So when creating an updated +# package for ScummVM 1.3.9 and the current ScummVM package in the app +# catalog is version 1.3.0902 then you must specify VER_PACKAGE=3 to create +# the ScummVM package with version 1.3.0903. Yeah, I know that's ugly but +# WebOS package version numbers are restricted to three numeric components. +# +# As long as Palm doesn't support Team-maintained apps the uploaded packages +# MUST NOT be packaged with the default "org.scummvm" base id. Instead apps +# must be uploaded with a user-specific base id. A good practice is using +# the github user as base id: com.github.<username>. It is also necessary +# to use a user-specific app name when submitting the created package to the +# Palm app catalog. Use "ScummVM (<username>)" instead of "ScummVM" and +# "ScummVM Beta (<username>)" instead of "ScummVM Beta". +# +# The app id is automatically parsed from the installation prefix. So add a +# configure parameter like this to prepare a build of a package for the Palm +# App Catalog: +# +# --prefix=/media/cryptofs/apps/usr/palm/applications/com.github.kayahr.scummvm +# +# To build a package for the Palm Beta App Catalog add "-beta" to the prefix: +# +# --prefix=/media/cryptofs/apps/usr/palm/applications/com.github.kayahr.scummvm-beta +# ============================================================================ + +# Increment this number when the packaging of the app has been changed while +# ScummVM itself has the same version as before. The number can be reset to +# 1 when the ScummVM version is increased. +VER_PACKAGE = 5 + +PATH_DIST = $(srcdir)/dists/webos +PATH_MOJO = $(PATH_DIST)/mojo +APP_ID = $(shell basename $(prefix)) +APP_VERSION = $(shell printf "%d.%d.%02d%02d" $(VER_MAJOR) $(VER_MINOR) $(VER_PATCH) $(VER_PACKAGE)) +DESTDIR ?= portdist + +install: all + $(QUIET)$(INSTALL) -d "$(DESTDIR)$(prefix)" + $(QUIET)$(INSTALL) -m 0644 -t "$(DESTDIR)$(prefix)/" "$(PATH_MOJO)/"* + $(QUIET)$(INSTALL) -m 0755 "$(PATH_MOJO)/start" "$(DESTDIR)$(prefix)/" + $(QUIET)$(INSTALL) -d "$(DESTDIR)$(bindir)" + $(QUIET)$(INSTALL) -c -m 755 "./$(EXECUTABLE)" "$(DESTDIR)$(bindir)/$(EXECUTABLE)" + $(QUIET)$(STRIP) "$(DESTDIR)$(bindir)/$(EXECUTABLE)" + $(QUIET)$(INSTALL) -d "$(DESTDIR)$(docdir)" + $(QUIET)$(INSTALL) -c -m 644 $(DIST_FILES_DOCS) "$(DESTDIR)$(docdir)" + $(QUIET)$(INSTALL) -d "$(DESTDIR)$(datadir)" + $(QUIET)$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) "$(DESTDIR)$(datadir)/" +ifdef DYNAMIC_MODULES + $(QUIET)$(INSTALL) -d "$(DESTDIR)$(libdir)/" + $(QUIET)$(INSTALL) -c -m 644 $(PLUGINS) "$(DESTDIR)$(libdir)/" + $(QUIET)$(STRIP) "$(DESTDIR)$(libdir)/"* +endif + $(QUIET)sed -i s/'APP_VERSION'/'$(APP_VERSION)'/ "$(DESTDIR)$(prefix)/appinfo.json" + $(QUIET)sed -i s/'APP_ID'/'$(APP_ID)'/ "$(DESTDIR)$(prefix)/appinfo.json" +ifneq (,$(findstring -beta,$(APP_ID))) + $(QUIET)sed -i s/'APP_TITLE'/'ScummVM Beta'/ "$(DESTDIR)$(prefix)/appinfo.json" +else + $(QUIET)sed -i s/'APP_TITLE'/'ScummVM'/ "$(DESTDIR)$(prefix)/appinfo.json" +endif + +uninstall: + $(QUIET)$(RM_REC) "$(DESTDIR)$(prefix)" + +package: install + $(QUIET)$(WEBOS_SDK)/bin/palm-package --use-v1-format "$(DESTDIR)$(prefix)" -o "$(DESTDIR)" diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp index aa688534fc..3965f51b7f 100644 --- a/backends/platform/wii/main.cpp +++ b/backends/platform/wii/main.cpp @@ -19,6 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define FORBIDDEN_SYMBOL_EXCEPTION_chdir +#define FORBIDDEN_SYMBOL_EXCEPTION_getcwd +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <sys/stat.h> #include <sys/types.h> #include <errno.h> diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp index 2aefe48f0c..401b19b0e1 100644 --- a/backends/platform/wii/osystem.cpp +++ b/backends/platform/wii/osystem.cpp @@ -19,6 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +// Allow use of stuff in <time.h> +#define FORBIDDEN_SYMBOL_EXCEPTION_time_h + +#define FORBIDDEN_SYMBOL_EXCEPTION_printf +#define FORBIDDEN_SYMBOL_EXCEPTION_getcwd + #include <unistd.h> #include <ogc/conf.h> @@ -26,6 +32,7 @@ #include <ogc/lwp_watchdog.h> #include "common/config-manager.h" +#include "common/textconsole.h" #include "backends/fs/wii/wii-fs-factory.h" #include "osystem.h" diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h index 3c992b8bdc..0db5f92fff 100644 --- a/backends/platform/wii/osystem.h +++ b/backends/platform/wii/osystem.h @@ -24,7 +24,6 @@ #include <gctypes.h> #include <gccore.h> -#include <ogcsys.h> #include <gxflux/gfx.h> @@ -36,6 +35,7 @@ #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" #include "graphics/colormasks.h" +#include "graphics/palette.h" #include "graphics/surface.h" #include "audio/mixer_intern.h" diff --git a/backends/platform/wii/osystem_events.cpp b/backends/platform/wii/osystem_events.cpp index 5d0bca453f..8e51bbc673 100644 --- a/backends/platform/wii/osystem_events.cpp +++ b/backends/platform/wii/osystem_events.cpp @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <unistd.h> #include <malloc.h> diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index cb9a8c72e9..b44c1270f5 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <malloc.h> #include <gxflux/gfx_con.h> @@ -537,10 +539,10 @@ Graphics::Surface *OSystem_Wii::lockScreen() { _surface.h = _gameHeight; #ifdef USE_RGB_COLOR _surface.pitch = _gameWidth * _pfGame.bytesPerPixel; - _surface.bytesPerPixel = _pfGame.bytesPerPixel; + _surface.format = _pfGame; #else _surface.pitch = _gameWidth; - _surface.bytesPerPixel = 1; + _surface.format = Graphics::PixelFormat::createFormatCLUT8(); #endif return &_surface; diff --git a/backends/platform/wii/osystem_sfx.cpp b/backends/platform/wii/osystem_sfx.cpp index 33397f0a93..acab6df7e1 100644 --- a/backends/platform/wii/osystem_sfx.cpp +++ b/backends/platform/wii/osystem_sfx.cpp @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include <malloc.h> #include "osystem.h" diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp index 99d0be2bdc..3895c7d6fa 100644 --- a/backends/platform/wince/CEActionsPocket.cpp +++ b/backends/platform/wince/CEActionsPocket.cpp @@ -38,7 +38,7 @@ #ifdef _WIN32_WCE -#define KEY_ALL_SKIP 3457 +#define KEY_ALL_SKIP 3457 #endif const Common::String pocketActionNames[] = { @@ -85,14 +85,14 @@ int CEActionsPocket::version() { } CEActionsPocket::CEActionsPocket(const Common::String &gameid) : -GUI::Actions() { + GUI::Actions() { int i; _right_click_needed = false; _hide_toolbar_needed = false; _zoom_needed = false; - for (i=0; i<POCKET_ACTION_LAST; i++) { + for (i = 0; i < POCKET_ACTION_LAST; i++) { _action_mapping[i] = 0; _action_enabled[i] = false; } @@ -112,7 +112,7 @@ GUI::Actions() { void CEActionsPocket::initInstanceMain(OSystem *mainSystem) { // Nothing generic to do for Pocket PC - _CESystem = static_cast<OSystem_WINCE3*>(mainSystem); + _CESystem = static_cast<OSystem_WINCE3 *>(mainSystem); GUI_Actions::initInstanceMain(mainSystem); } @@ -126,7 +126,7 @@ void CEActionsPocket::initInstanceGame() { bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0); bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0); bool is_saga = (gameid == "saga"); - bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0); + bool is_kyra = (strncmp(gameid.c_str(), "kyra", 4) == 0); bool is_samnmax = (gameid == "samnmax"); bool is_cine = (gameid == "cine"); bool is_touche = (gameid == "touche"); @@ -134,7 +134,7 @@ void CEActionsPocket::initInstanceGame() { bool is_parallaction = (gameid == "parallaction"); bool is_lure = (gameid == "lure"); bool is_feeble = (gameid == "feeble"); - bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0); + bool is_drascula = (strncmp(gameid.c_str(), "drascula", 8) == 0); bool is_tucker = (gameid == "tucker"); bool is_groovie = (gameid == "groovie"); bool is_tinsel = (gameid == "tinsel"); @@ -145,7 +145,7 @@ void CEActionsPocket::initInstanceGame() { // See if a right click mapping could be needed if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_tinsel || - is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise) + is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise) _right_click_needed = true; // See if a "hide toolbar" mapping could be needed @@ -187,7 +187,7 @@ void CEActionsPocket::initInstanceGame() { if (!is_cine && !is_parallaction && !is_groovie && !is_cruise && !is_made) _action_enabled[POCKET_ACTION_SKIP] = true; if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_tinsel || - is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker) + is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker) _key_action[POCKET_ACTION_SKIP].setKey(VK_ESCAPE); else _key_action[POCKET_ACTION_SKIP].setKey(KEY_ALL_SKIP); @@ -239,10 +239,12 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) { if (!pushed) { switch (action) { case POCKET_ACTION_RIGHTCLICK: - _CESystem->add_right_click(false); + //_CESystem->add_right_click(false); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(false); return true; case POCKET_ACTION_LEFTCLICK: - _CESystem->add_left_click(false); + //_CESystem->add_left_click(false); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(false); return true; case POCKET_ACTION_PAUSE: case POCKET_ACTION_SAVE: @@ -272,43 +274,55 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) { EventsBuffer::simulateKey(&_key_action[action], true); return true; case POCKET_ACTION_KEYBOARD: - _CESystem->swap_panel(); + //_CESystem->swap_panel(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_panel(); return true; case POCKET_ACTION_HIDE: - _CESystem->swap_panel_visibility(); + //_CESystem->swap_panel_visibility(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_panel_visibility(); return true; case POCKET_ACTION_SOUND: _CESystem->swap_sound_master(); return true; case POCKET_ACTION_RIGHTCLICK: - _CESystem->add_right_click(true); + //_CESystem->add_right_click(true); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(true); return true; case POCKET_ACTION_CURSOR: - _CESystem->swap_mouse_visibility(); + //_CESystem->swap_mouse_visibility(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_mouse_visibility(); return true; case POCKET_ACTION_FREELOOK: - _CESystem->swap_freeLook(); + //_CESystem->swap_freeLook(); + ((WINCESdlEventSource *)((OSystem_SDL *)g_system)->getEventManager())->swap_freeLook(); return true; case POCKET_ACTION_ZOOM_UP: - _CESystem->swap_zoom_up(); + //_CESystem->swap_zoom_up(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_zoom_up(); return true; case POCKET_ACTION_ZOOM_DOWN: - _CESystem->swap_zoom_down(); + //_CESystem->swap_zoom_down(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_zoom_down(); return true; case POCKET_ACTION_LEFTCLICK: - _CESystem->add_left_click(true); + //_CESystem->add_left_click(true); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(true); return true; case POCKET_ACTION_UP: - _CESystem->move_cursor_up(); + //_CESystem->move_cursor_up(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_up(); return true; case POCKET_ACTION_DOWN: - _CESystem->move_cursor_down(); + //_CESystem->move_cursor_down(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_down(); return true; case POCKET_ACTION_LEFT: - _CESystem->move_cursor_left(); + //_CESystem->move_cursor_left(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_left(); return true; case POCKET_ACTION_RIGHT: - _CESystem->move_cursor_right(); + //_CESystem->move_cursor_right(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_right(); return true; case POCKET_ACTION_QUIT: if (!quitdialog) { diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp index 5c7feb4950..413c52af2b 100644 --- a/backends/platform/wince/CEActionsSmartphone.cpp +++ b/backends/platform/wince/CEActionsSmartphone.cpp @@ -36,7 +36,7 @@ #include "common/translation.h" -#define KEY_ALL_SKIP 3457 +#define KEY_ALL_SKIP 3457 const String smartphoneActionNames[] = { _s("Up"), @@ -79,10 +79,10 @@ int CEActionsSmartphone::version() { } CEActionsSmartphone::CEActionsSmartphone() -: GUI::Actions() { + : GUI::Actions() { int i; - for (i=0; i<SMARTPHONE_ACTION_LAST; i++) { + for (i = 0; i < SMARTPHONE_ACTION_LAST; i++) { _action_mapping[i] = ACTIONS_SMARTPHONE_DEFAULT[i]; _action_enabled[i] = false; } @@ -90,7 +90,7 @@ CEActionsSmartphone::CEActionsSmartphone() } void CEActionsSmartphone::initInstanceMain(OSystem *mainSystem) { - _CESystem = static_cast<OSystem_WINCE3*>(mainSystem); + _CESystem = static_cast<OSystem_WINCE3 *>(mainSystem); GUI_Actions::initInstanceMain(mainSystem); @@ -117,7 +117,7 @@ void CEActionsSmartphone::initInstanceGame() { bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0); bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0); bool is_saga = (gameid == "saga"); - bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0); + bool is_kyra = (strncmp(gameid.c_str(), "kyra", 4) == 0); bool is_samnmax = (gameid == "samnmax"); bool is_cine = (gameid == "cine"); bool is_touche = (gameid == "touche"); @@ -125,7 +125,7 @@ void CEActionsSmartphone::initInstanceGame() { bool is_parallaction = (gameid == "parallaction"); bool is_lure = (gameid == "lure"); bool is_feeble = (gameid == "feeble"); - bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0); + bool is_drascula = (strncmp(gameid.c_str(), "drascula", 8) == 0); bool is_tucker = (gameid == "tucker"); bool is_groovie = (gameid == "groovie"); bool is_tinsel = (gameid == "tinsel"); @@ -136,7 +136,7 @@ void CEActionsSmartphone::initInstanceGame() { // See if a right click mapping could be needed if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_tinsel || - is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise) + is_samnmax || is_cine || is_touche || is_parallaction || is_drascula || is_cruise) _right_click_needed = true; // Initialize keys for different actions @@ -168,8 +168,8 @@ void CEActionsSmartphone::initInstanceGame() { // Skip _action_enabled[SMARTPHONE_ACTION_SKIP] = true; if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_tinsel || - is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker || - is_groovie || is_cruise || is_made) + is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula || is_tucker || + is_groovie || is_cruise || is_made) _key_action[SMARTPHONE_ACTION_SKIP].setKey(VK_ESCAPE); else _key_action[SMARTPHONE_ACTION_SKIP].setKey(KEY_ALL_SKIP); @@ -204,81 +204,92 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) { if (!pushed) { switch (action) { - case SMARTPHONE_ACTION_RIGHTCLICK: - _CESystem->add_right_click(false); - return true; - case SMARTPHONE_ACTION_LEFTCLICK: - _CESystem->add_left_click(false); - return true; - case SMARTPHONE_ACTION_SAVE: - case SMARTPHONE_ACTION_SKIP: - case SMARTPHONE_ACTION_MULTI: - EventsBuffer::simulateKey(&_key_action[action], false); - return true; - } - return false; - } - - switch (action) { - case SMARTPHONE_ACTION_SAVE: - case SMARTPHONE_ACTION_SKIP: - case SMARTPHONE_ACTION_MULTI: - if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") { - // FIXME: This is a temporary solution. The engine should handle its own menus. - // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience - GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save")); - if (alert.runModal() == GUI::kMessageOK) - _key_action[action].setKey(SDLK_l); - else - _key_action[action].setKey(SDLK_s); - } - EventsBuffer::simulateKey(&_key_action[action], true); - return true; case SMARTPHONE_ACTION_RIGHTCLICK: - _CESystem->add_right_click(true); + //_CESystem->add_right_click(false); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(false); return true; case SMARTPHONE_ACTION_LEFTCLICK: - _CESystem->add_left_click(true); - return true; - case SMARTPHONE_ACTION_UP: - _CESystem->move_cursor_up(); - return true; - case SMARTPHONE_ACTION_DOWN: - _CESystem->move_cursor_down(); - return true; - case SMARTPHONE_ACTION_LEFT: - _CESystem->move_cursor_left(); - return true; - case SMARTPHONE_ACTION_RIGHT: - _CESystem->move_cursor_right(); - return true; - case SMARTPHONE_ACTION_ZONE: - _CESystem->switch_zone(); + //_CESystem->add_left_click(false); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(false); return true; - case SMARTPHONE_ACTION_BINDKEYS: - if (!keydialogrunning) { - keydialogrunning = true; - GUI::KeysDialog *keysDialog = new GUI::KeysDialog(); - keysDialog->runModal(); - delete keysDialog; - keydialogrunning = false; - } - return true; - case SMARTPHONE_ACTION_KEYBOARD: - _CESystem->swap_smartphone_keyboard(); - return true; - case SMARTPHONE_ACTION_ROTATE: - _CESystem->smartphone_rotate_display(); - return true; - case SMARTPHONE_ACTION_QUIT: - if (!quitdialog) { - quitdialog = true; - GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No")); - if (alert.runModal() == GUI::kMessageOK) - _mainSystem->quit(); - quitdialog = false; - } + case SMARTPHONE_ACTION_SAVE: + case SMARTPHONE_ACTION_SKIP: + case SMARTPHONE_ACTION_MULTI: + EventsBuffer::simulateKey(&_key_action[action], false); return true; + } + return false; + } + + switch (action) { + case SMARTPHONE_ACTION_SAVE: + case SMARTPHONE_ACTION_SKIP: + case SMARTPHONE_ACTION_MULTI: + if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") { + // FIXME: This is a temporary solution. The engine should handle its own menus. + // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience + GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save")); + if (alert.runModal() == GUI::kMessageOK) + _key_action[action].setKey(SDLK_l); + else + _key_action[action].setKey(SDLK_s); + } + EventsBuffer::simulateKey(&_key_action[action], true); + return true; + case SMARTPHONE_ACTION_RIGHTCLICK: + //_CESystem->add_right_click(true); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_right_click(true); + return true; + case SMARTPHONE_ACTION_LEFTCLICK: + //_CESystem->add_left_click(true); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->add_left_click(true); + return true; + case SMARTPHONE_ACTION_UP: + //_CESystem->move_cursor_up(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_up(); + return true; + case SMARTPHONE_ACTION_DOWN: + //_CESystem->move_cursor_down(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_down(); + return true; + case SMARTPHONE_ACTION_LEFT: + //_CESystem->move_cursor_left(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_left(); + return true; + case SMARTPHONE_ACTION_RIGHT: + //_CESystem->move_cursor_right(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->move_cursor_right(); + return true; + case SMARTPHONE_ACTION_ZONE: + //_CESystem->switch_zone(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->switch_zone(); + return true; + case SMARTPHONE_ACTION_BINDKEYS: + if (!keydialogrunning) { + keydialogrunning = true; + GUI::KeysDialog *keysDialog = new GUI::KeysDialog(); + keysDialog->runModal(); + delete keysDialog; + keydialogrunning = false; + } + return true; + case SMARTPHONE_ACTION_KEYBOARD: + //_CESystem->swap_smartphone_keyboard(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->swap_smartphone_keyboard(); + return true; + case SMARTPHONE_ACTION_ROTATE: + //_CESystem->smartphone_rotate_display(); + ((WINCESdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->smartphone_rotate_display(); + return true; + case SMARTPHONE_ACTION_QUIT: + if (!quitdialog) { + quitdialog = true; + GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No")); + if (alert.runModal() == GUI::kMessageOK) + _mainSystem->quit(); + quitdialog = false; + } + return true; } return false; diff --git a/backends/platform/wince/CEDevice.cpp b/backends/platform/wince/CEDevice.cpp index d94ce6cde7..ffe2523b47 100644 --- a/backends/platform/wince/CEDevice.cpp +++ b/backends/platform/wince/CEDevice.cpp @@ -29,22 +29,22 @@ #include "backends/platform/wince/wince-sdl.h" -static void (WINAPI* _SHIdleTimerReset)(void) = NULL; -static HANDLE (WINAPI* _SetPowerRequirement)(PVOID,int,ULONG,PVOID,ULONG) = NULL; -static DWORD (WINAPI* _ReleasePowerRequirement)(HANDLE) = NULL; +static void (WINAPI *_SHIdleTimerReset)(void) = NULL; +static HANDLE(WINAPI *_SetPowerRequirement)(PVOID, int, ULONG, PVOID, ULONG) = NULL; +static DWORD (WINAPI *_ReleasePowerRequirement)(HANDLE) = NULL; static HANDLE _hPowerManagement = NULL; static DWORD _lastTime = 0; static DWORD REG_bat = 0, REG_ac = 0, REG_disp = 0, bat_timeout = 0; static bool REG_tampered = false; #ifdef __GNUC__ extern "C" void WINAPI SystemIdleTimerReset(void); -#define SPI_SETBATTERYIDLETIMEOUT 251 -#define SPI_GETBATTERYIDLETIMEOUT 252 +#define SPI_SETBATTERYIDLETIMEOUT 251 +#define SPI_GETBATTERYIDLETIMEOUT 252 #endif #define TIMER_TRIGGER 9000 -DWORD CEDevice::reg_access(TCHAR *key, TCHAR *val, DWORD data) { +DWORD CEDevice::reg_access(const TCHAR *key, const TCHAR *val, DWORD data) { HKEY regkey; DWORD tmpval, cbdata; @@ -70,7 +70,7 @@ DWORD CEDevice::reg_access(TCHAR *key, TCHAR *val, DWORD data) { void CEDevice::backlight_xchg() { HANDLE h; - REG_bat = reg_access(TEXT("ControlPanel\\BackLight"), TEXT("BatteryTimeout"), REG_bat); + REG_bat = reg_access(TEXT("ControlPanel\\BackLight"), (const TCHAR *)TEXT("BatteryTimeout"), REG_bat); REG_ac = reg_access(TEXT("ControlPanel\\BackLight"), TEXT("ACTimeout"), REG_ac); REG_disp = reg_access(TEXT("ControlPanel\\Power"), TEXT("Display"), REG_disp); @@ -85,20 +85,19 @@ void CEDevice::init() { // 2003+ power management code borrowed from MoDaCo & Betaplayer. Thanks ! HINSTANCE dll = LoadLibrary(TEXT("aygshell.dll")); if (dll) { - *(FARPROC*)&_SHIdleTimerReset = GetProcAddress(dll, MAKEINTRESOURCE(2006)); + _SHIdleTimerReset = (void (*)())GetProcAddress(dll, MAKEINTRESOURCE(2006)); } dll = LoadLibrary(TEXT("coredll.dll")); if (dll) { - *(FARPROC*)&_SetPowerRequirement = GetProcAddress(dll, TEXT("SetPowerRequirement")); - *(FARPROC*)&_ReleasePowerRequirement = GetProcAddress(dll, TEXT("ReleasePowerRequirement")); - + _SetPowerRequirement = (HANDLE (*)(PVOID, int, ULONG, PVOID, ULONG))GetProcAddress(dll, TEXT("SetPowerRequirement")); + _ReleasePowerRequirement = (DWORD (*)(HANDLE))GetProcAddress(dll, TEXT("ReleasePowerRequirement")); } if (_SetPowerRequirement) _hPowerManagement = _SetPowerRequirement((PVOID) TEXT("BKL1:"), 0, 1, (PVOID) NULL, 0); _lastTime = GetTickCount(); // older devices - REG_bat = REG_ac = REG_disp = 2 * 60 * 60 * 1000; // 2hrs should do it + REG_bat = REG_ac = REG_disp = 2 * 60 * 60 * 1000; // 2hrs should do it backlight_xchg(); REG_tampered = true; SystemParametersInfo(SPI_GETBATTERYIDLETIMEOUT, 0, (void *) &bat_timeout, 0); @@ -127,6 +126,10 @@ bool CEDevice::hasSquareQVGAResolution() { return (OSystem_WINCE3::getScreenWidth() == 240 && OSystem_WINCE3::getScreenHeight() == 240); } +bool CEDevice::hasWideResolution() { + return (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640); +} + bool CEDevice::hasPocketPCResolution() { if (OSystem_WINCE3::isOzone() && hasWideResolution()) return true; @@ -139,10 +142,6 @@ bool CEDevice::hasDesktopResolution() { return (OSystem_WINCE3::getScreenWidth() > 320); } -bool CEDevice::hasWideResolution() { - return (OSystem_WINCE3::getScreenWidth() >= 640 || OSystem_WINCE3::getScreenHeight() >= 640); -} - bool CEDevice::hasSmartphoneResolution() { return (OSystem_WINCE3::getScreenWidth() < 240); } diff --git a/backends/platform/wince/CEDevice.h b/backends/platform/wince/CEDevice.h index b2b20d05ce..24dffca0b3 100644 --- a/backends/platform/wince/CEDevice.h +++ b/backends/platform/wince/CEDevice.h @@ -43,7 +43,7 @@ public: static bool isSmartphone(); private: - static DWORD reg_access(TCHAR *key, TCHAR *val, DWORD data); + static DWORD reg_access(const TCHAR *key, const TCHAR *val, DWORD data); static void backlight_xchg(); }; diff --git a/backends/platform/wince/CEException.cpp b/backends/platform/wince/CEException.cpp index 421db4960c..08a327136f 100644 --- a/backends/platform/wince/CEException.cpp +++ b/backends/platform/wince/CEException.cpp @@ -36,7 +36,7 @@ void CEException::writeBreak(HANDLE file) { int i; memset(tempo, 0, sizeof(tempo)); - for (i=0; i<40; i++) + for (i = 0; i < 40; i++) tempo[i] = '-'; writeString(file, tempo); } @@ -51,23 +51,23 @@ void CEException::dumpContext(HANDLE file, HANDLE hProcess, CONTEXT *context) { writeBreak(file); writeString(file, "Context dump"); sprintf(tempo, "R0=%.8x R1=%.8x R2=%.8x R3=%.8x R4=%.8x", context->R0, context->R1, - context->R2, context->R3, context->R4); + context->R2, context->R3, context->R4); writeString(file, tempo); sprintf(tempo, "R5=%.8x R6=%.8x R7=%.8x R8=%.8x R9=%.8x", context->R5, context->R6, - context->R7, context->R8, context->R9); + context->R7, context->R8, context->R9); writeString(file, tempo); sprintf(tempo, "R10=%.8x R11=%.8x R12=%.8x", context->R10, context->R11, - context->R12); + context->R12); writeString(file, tempo); sprintf(tempo, "Sp=%.8x Lr=%.8x Pc=%.8x Psr=%.8x", context->Sp, context->Lr, - context->Pc, context->Psr); + context->Pc, context->Psr); writeString(file, tempo); writeBreak(file); sprintf(tempo, "Memory dump at %.8x", context->Pc - (sizeof(memoryDump) / 2)); writeString(file, tempo); if (ReadProcessMemory(hProcess, (LPCVOID)(context->Pc - (sizeof(memoryDump) / 2)), memoryDump, sizeof(memoryDump), &size)) { - for (i=0; i<size; i+=8) { + for (i = 0; i < size; i += 8) { int j; char digit[4]; int max; @@ -75,7 +75,7 @@ void CEException::dumpContext(HANDLE file, HANDLE hProcess, CONTEXT *context) { if (max > 8) max = 8; tempo[0] = '\0'; - for (j=0; j<max; j++) { + for (j = 0; j < max; j++) { sprintf(digit, "%.2x ", memoryDump[i + j]); strcat(tempo, digit); } @@ -121,10 +121,10 @@ void CEException::dumpException(HANDLE file, EXCEPTION_RECORD *exceptionRecord) break; } sprintf(tempo, "Exception %s Flags %.8x Address %.8x", exceptionName, exceptionRecord->ExceptionFlags, - exceptionRecord->ExceptionAddress); + exceptionRecord->ExceptionAddress); writeString(file, tempo); if (exceptionRecord->NumberParameters) { - for (i=0; i<exceptionRecord->NumberParameters; i++) { + for (i = 0; i < exceptionRecord->NumberParameters; i++) { sprintf(tempo, "Parameter %d %.8x", i, exceptionRecord->ExceptionInformation[i]); writeString(file, tempo); } @@ -144,8 +144,8 @@ bool CEException::writeException(TCHAR *path, EXCEPTION_POINTERS *exceptionPoint GetSystemTime(&systemTime); wsprintf(dumpFileName, TEXT("%s_%.2d_%.2d_%.4d_%.2d_%.2d_%.2d.txt"), - path, systemTime.wDay, systemTime.wMonth, systemTime.wYear, - systemTime.wHour, systemTime.wMinute, systemTime.wSecond); + path, systemTime.wDay, systemTime.wMonth, systemTime.wYear, + systemTime.wHour, systemTime.wMinute, systemTime.wSecond); dumpFile = CreateFile(dumpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (dumpFile == INVALID_HANDLE_VALUE) return false; diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp index de1bb2f1f6..8824af732f 100644 --- a/backends/platform/wince/CELauncherDialog.cpp +++ b/backends/platform/wince/CELauncherDialog.cpp @@ -48,14 +48,14 @@ using namespace Common; class CEAboutDialog : public Dialog { public: CEAboutDialog() - : Dialog(10, 60, 300, 77) { + : Dialog(10, 60, 300, 77) { char tempo[100]; // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what // needs fixing, or remove it! const int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0); const int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0); - new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME + new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME Common::String videoDriver(_("Using SDL driver ")); SDL_VideoDriverName(tempo, sizeof(tempo)); @@ -106,14 +106,13 @@ void CELauncherDialog::addGame() { MessageDialog alert(_("Do you want to perform an automatic scan ?"), _("Yes"), _("No")); if (alert.runModal() == kMessageOK && _browser->runModal() > 0) { // Clear existing domains - ConfigManager::DomainMap &domains = (ConfigManager::DomainMap&)ConfMan.getGameDomains(); + ConfigManager::DomainMap &domains = (ConfigManager::DomainMap &)ConfMan.getGameDomains(); domains.clear(); ConfMan.flushToDisk(); automaticScanDirectory(_browser->getResult()); ConfMan.flushToDisk(); updateListing(); draw(); - } - else + } else GUILauncherDialog::addGame(); } diff --git a/backends/platform/wince/CEgui/GUIElement.cpp b/backends/platform/wince/CEgui/GUIElement.cpp index dd463c22a1..e7ffc8d473 100644 --- a/backends/platform/wince/CEgui/GUIElement.cpp +++ b/backends/platform/wince/CEgui/GUIElement.cpp @@ -32,7 +32,7 @@ namespace CEGUI { GUIElement::GUIElement(int x, int y, int width, int height) : -_background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) { + _background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) { } bool GUIElement::setBackground(WORD backgroundReference) { @@ -45,9 +45,7 @@ bool GUIElement::setBackground(WORD backgroundReference) { if (!_height && !_width) { _height = _background->height(); _width = _background->width(); - } - else - if (_background->height() != _height || _background->width() != _width) { + } else if (_background->height() != _height || _background->width() != _width) { delete _background; _background = NULL; return false; @@ -74,8 +72,7 @@ bool GUIElement::draw(SDL_Surface *surface) { _drawn = true; return true; - } - else + } else return false; } diff --git a/backends/platform/wince/CEgui/ItemAction.cpp b/backends/platform/wince/CEgui/ItemAction.cpp index 55805744e6..efbc43ce00 100644 --- a/backends/platform/wince/CEgui/ItemAction.cpp +++ b/backends/platform/wince/CEgui/ItemAction.cpp @@ -28,7 +28,7 @@ namespace CEGUI { ItemAction::ItemAction(WORD reference, GUI::ActionType action) : -PanelItem(reference) { + PanelItem(reference) { _action = action; if (!GUI::Actions::Instance()->isEnabled(_action)) _visible = false; diff --git a/backends/platform/wince/CEgui/ItemSwitch.cpp b/backends/platform/wince/CEgui/ItemSwitch.cpp index d4648f7556..8eb62bf365 100644 --- a/backends/platform/wince/CEgui/ItemSwitch.cpp +++ b/backends/platform/wince/CEgui/ItemSwitch.cpp @@ -40,7 +40,7 @@ void ItemSwitch::init(WORD referenceTrue, WORD referenceFalse) { } ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item) : -PanelItem(referenceTrue) { + PanelItem(referenceTrue) { init(referenceTrue, referenceFalse); _item = item; _itemmax = -1; @@ -49,8 +49,8 @@ PanelItem(referenceTrue) { } ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max) : -PanelItem(referenceTrue) { - init(referenceTrue, referenceFalse); + PanelItem(referenceTrue) { + init(referenceTrue, referenceFalse); _itemmultiple = item; _itemmax = max; if (!*item) diff --git a/backends/platform/wince/CEgui/Panel.cpp b/backends/platform/wince/CEgui/Panel.cpp index dfdd6526be..576da23029 100644 --- a/backends/platform/wince/CEgui/Panel.cpp +++ b/backends/platform/wince/CEgui/Panel.cpp @@ -34,7 +34,7 @@ Panel::Panel(int interleave_first, int interleave) : Toolbar() { bool Panel::add(const String &name, const PanelItem *item) { - _itemsMap[name] = (PanelItem*)item; + _itemsMap[name] = (PanelItem *)item; _itemsMap[name]->move(_currentItem, _y + 10); _itemsMap[name]->setPanel(this); _currentItem += _interleave; @@ -47,11 +47,10 @@ bool Panel::draw(SDL_Surface *surface) { if (!_drawn && _visible) { GUIElement::draw(surface); for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) { - ((GUIElement*)(iterator->_value))->draw(surface); + ((GUIElement *)(iterator->_value))->draw(surface); } return true; - } - else + } else return false; } @@ -59,7 +58,7 @@ void Panel::forceRedraw() { ItemMap::const_iterator iterator; GUIElement::forceRedraw(); for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) - ((GUIElement*)(iterator->_value))->forceRedraw(); + ((GUIElement *)(iterator->_value))->forceRedraw(); } bool Panel::action(int x, int y, bool pushed) { @@ -69,7 +68,7 @@ bool Panel::action(int x, int y, bool pushed) { return false; for (iterator = _itemsMap.begin(); !result && iterator != _itemsMap.end(); ++iterator) - result = ((GUIElement*)(iterator->_value))->action(x, y, pushed); + result = ((GUIElement *)(iterator->_value))->action(x, y, pushed); return result; } diff --git a/backends/platform/wince/CEgui/Panel.h b/backends/platform/wince/CEgui/Panel.h index e6b693360d..1a8a580dba 100644 --- a/backends/platform/wince/CEgui/Panel.h +++ b/backends/platform/wince/CEgui/Panel.h @@ -51,7 +51,7 @@ public: virtual bool action(int x, int y, bool pushed); private: - typedef HashMap<String, PanelItem*, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap; + typedef HashMap<String, PanelItem *, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap; ItemMap _itemsMap; int _interleave; diff --git a/backends/platform/wince/CEgui/PanelItem.h b/backends/platform/wince/CEgui/PanelItem.h index 14b62f0f20..9968aa8d5e 100644 --- a/backends/platform/wince/CEgui/PanelItem.h +++ b/backends/platform/wince/CEgui/PanelItem.h @@ -36,7 +36,7 @@ namespace CEGUI { class Panel; class PanelItem : public GUIElement { -friend class Panel; + friend class Panel; public: PanelItem(WORD reference); virtual ~PanelItem(); diff --git a/backends/platform/wince/CEgui/PanelKeyboard.cpp b/backends/platform/wince/CEgui/PanelKeyboard.cpp index 5ca125898d..3512b34da3 100644 --- a/backends/platform/wince/CEgui/PanelKeyboard.cpp +++ b/backends/platform/wince/CEgui/PanelKeyboard.cpp @@ -30,8 +30,9 @@ namespace CEGUI { const char KEYBOARD_MAPPING_ALPHA[][14] = { {"abcdefghijklm"}, {"nopqrstuvwxyz"} }; const char KEYBOARD_MAPPING_NUMERIC[][6] = { {"12345"}, {"67890"} }; -const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1,SDLK_ESCAPE}, {224,SDLK_UP}, {32,SDLK_SPACE} }, - { {224,SDLK_LEFT}, {224,SDLK_DOWN}, {224,SDLK_RIGHT} } }; +const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1, SDLK_ESCAPE}, {224, SDLK_UP}, {32, SDLK_SPACE} }, + { {224, SDLK_LEFT}, {224, SDLK_DOWN}, {224, SDLK_RIGHT} } +}; PanelKeyboard::PanelKeyboard(WORD reference) : Toolbar() { setBackground(reference); @@ -51,21 +52,23 @@ bool PanelKeyboard::action(int x, int y, bool pushed) { int keyCode = 0; if (x < 185) { // Alpha selection - keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y+20][((x + 10) / 14) - 1]; + keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y + 20][((x + 10) / 14) - 1]; } else if (x >= 186 && x <= 255) { // Numeric selection - keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y+20][((x - 187 + 10) / 14) - 1]; + keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y + 20][((x - 187 + 10) / 14) - 1]; } else if (x >= 258 && x <= 300) { // Special keys - keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][0]; - keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][1]; + keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y + 20][((x - 259 + 10) / 14) - 1][0]; + keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y + 20][((x - 259 + 10) / 14) - 1][1]; } else if (x >= 302 && x <= 316) { - if (y < _y +20) { + if (y < _y + 20) { // Backspace - keyAscii = VK_BACK; keyCode = keyAscii; + keyAscii = VK_BACK; + keyCode = keyAscii; } else { // Enter - keyAscii = 13; keyCode = 13; + keyAscii = 13; + keyCode = 13; } } diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.cpp b/backends/platform/wince/CEgui/SDL_ImageResource.cpp index 8dad5f0a0c..872b94a442 100644 --- a/backends/platform/wince/CEgui/SDL_ImageResource.cpp +++ b/backends/platform/wince/CEgui/SDL_ImageResource.cpp @@ -32,7 +32,7 @@ SDL_ImageResource::SDL_ImageResource() : _surface(0) { } -SDL_Surface* SDL_ImageResource::load(WORD resourceID) { +SDL_Surface *SDL_ImageResource::load(WORD resourceID) { HRSRC resource; HGLOBAL resourceGlobal; LPVOID resourcePointer; @@ -62,7 +62,7 @@ SDL_Surface* SDL_ImageResource::load(WORD resourceID) { return _surface; } -SDL_Surface* SDL_ImageResource::get() { +SDL_Surface *SDL_ImageResource::get() { return _surface; } diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.h b/backends/platform/wince/CEgui/SDL_ImageResource.h index 5affd5c33c..397ced1434 100644 --- a/backends/platform/wince/CEgui/SDL_ImageResource.h +++ b/backends/platform/wince/CEgui/SDL_ImageResource.h @@ -36,8 +36,8 @@ namespace CEGUI { class SDL_ImageResource { public: SDL_ImageResource(); - SDL_Surface* load(WORD resourceID); - SDL_Surface* get(); + SDL_Surface *load(WORD resourceID); + SDL_Surface *get(); int height(); int width(); virtual ~SDL_ImageResource(); diff --git a/backends/platform/wince/CEgui/ToolbarHandler.cpp b/backends/platform/wince/CEgui/ToolbarHandler.cpp index 78f69119c3..ed2a72245a 100644 --- a/backends/platform/wince/CEgui/ToolbarHandler.cpp +++ b/backends/platform/wince/CEgui/ToolbarHandler.cpp @@ -29,15 +29,15 @@ namespace CEGUI { ToolbarHandler::ToolbarHandler(): -_current(""), _active(NULL) { + _current(""), _active(NULL) { } bool ToolbarHandler::add(const String &name, const Toolbar &toolbar) { - _toolbarMap[name] = (Toolbar*)&toolbar; + _toolbarMap[name] = (Toolbar *)&toolbar; if (!_active) { - _active = &((Toolbar&)toolbar); + _active = &((Toolbar &)toolbar); _current = name; } @@ -53,7 +53,7 @@ bool ToolbarHandler::setActive(const String &name) { return false; if (_current == name) return true; - _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel) + _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel) _current = name; _active = _toolbarMap[name]; _active->forceRedraw(); @@ -67,8 +67,7 @@ bool ToolbarHandler::action(int x, int y, bool pushed) { return _active->action(x / 2, (y - _offset) / 2, pushed); else return _active->action(x, y - _offset, pushed); - } - else + } else return false; } @@ -118,7 +117,7 @@ int ToolbarHandler::getOffset() { return _offset; } -Toolbar* ToolbarHandler::active() { +Toolbar *ToolbarHandler::active() { return _active; } diff --git a/backends/platform/wince/CEgui/ToolbarHandler.h b/backends/platform/wince/CEgui/ToolbarHandler.h index e3bf590768..0f794d7d61 100644 --- a/backends/platform/wince/CEgui/ToolbarHandler.h +++ b/backends/platform/wince/CEgui/ToolbarHandler.h @@ -57,7 +57,7 @@ public: virtual ~ToolbarHandler(); private: - HashMap<String, Toolbar*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap; + HashMap<String, Toolbar *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap; String _current; Toolbar *_active; int _offset; diff --git a/backends/platform/wince/CEkeys/EventsBuffer.cpp b/backends/platform/wince/CEkeys/EventsBuffer.cpp index c9f4af2304..beea272d2b 100644 --- a/backends/platform/wince/CEkeys/EventsBuffer.cpp +++ b/backends/platform/wince/CEkeys/EventsBuffer.cpp @@ -29,55 +29,55 @@ namespace CEKEYS { - bool EventsBuffer::simulateKey(GUI::Key *key, bool pushed) { - SDL_Event ev = {0}; - - if (!key->keycode()) - key->setKey(key->ascii(), key->ascii()); - else if (!key->ascii()) - key->setKey(key->keycode()); - - ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP); - ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field - ev.key.keysym.sym = (SDLKey)key->keycode(); - ev.key.keysym.mod = KMOD_RESERVED; - return (SDL_PushEvent(&ev) == 0); - } - - bool EventsBuffer::simulateMouseMove(int x, int y) { - SDL_Event ev = {0}; - - ev.type = SDL_MOUSEMOTION; - ev.motion.x = x; - ev.motion.y = y; - return (SDL_PushEvent(&ev) == 0); - } - - bool EventsBuffer::simulateMouseLeftClick(int x, int y, bool pushed) { - SDL_Event ev = {0}; - static bool state = false; - - if (pushed == state) return 0; - state = pushed; - ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP); - ev.button.button = SDL_BUTTON_LEFT; - ev.button.x = x; - ev.button.y = y; - return (SDL_PushEvent(&ev) == 0); - } - - bool EventsBuffer::simulateMouseRightClick(int x, int y, bool pushed) { - SDL_Event ev = {0}; - static bool state = false; - - if (pushed == state) return 0; - state = pushed; - ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP); - ev.button.button = SDL_BUTTON_RIGHT; - ev.button.x = x; - ev.button.y = y; - return (SDL_PushEvent(&ev) == 0); - } +bool EventsBuffer::simulateKey(GUI::Key *key, bool pushed) { + SDL_Event ev = {0}; + + if (!key->keycode()) + key->setKey(key->ascii(), key->ascii()); + else if (!key->ascii()) + key->setKey(key->keycode()); + + ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP); + ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field + ev.key.keysym.sym = (SDLKey)key->keycode(); + ev.key.keysym.mod = KMOD_RESERVED; + return (SDL_PushEvent(&ev) == 0); +} + +bool EventsBuffer::simulateMouseMove(int x, int y) { + SDL_Event ev = {0}; + + ev.type = SDL_MOUSEMOTION; + ev.motion.x = x; + ev.motion.y = y; + return (SDL_PushEvent(&ev) == 0); +} + +bool EventsBuffer::simulateMouseLeftClick(int x, int y, bool pushed) { + SDL_Event ev = {0}; + static bool state = false; + + if (pushed == state) return 0; + state = pushed; + ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP); + ev.button.button = SDL_BUTTON_LEFT; + ev.button.x = x; + ev.button.y = y; + return (SDL_PushEvent(&ev) == 0); +} + +bool EventsBuffer::simulateMouseRightClick(int x, int y, bool pushed) { + SDL_Event ev = {0}; + static bool state = false; + + if (pushed == state) return 0; + state = pushed; + ev.type = (pushed ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP); + ev.button.button = SDL_BUTTON_RIGHT; + ev.button.x = x; + ev.button.y = y; + return (SDL_PushEvent(&ev) == 0); +} } diff --git a/backends/platform/wince/CEkeys/EventsBuffer.h b/backends/platform/wince/CEkeys/EventsBuffer.h index 22590db03c..9b766c6ca9 100644 --- a/backends/platform/wince/CEkeys/EventsBuffer.h +++ b/backends/platform/wince/CEkeys/EventsBuffer.h @@ -34,14 +34,14 @@ namespace CEKEYS { - class EventsBuffer { - public: - static bool simulateKey(GUI::Key *key, bool pushed); - static bool simulateMouseMove(int x, int y); - static bool simulateMouseLeftClick(int x, int y, bool pushed); - static bool simulateMouseRightClick(int x, int y, bool pushed); - - }; +class EventsBuffer { +public: + static bool simulateKey(GUI::Key *key, bool pushed); + static bool simulateMouseMove(int x, int y); + static bool simulateMouseLeftClick(int x, int y, bool pushed); + static bool simulateMouseRightClick(int x, int y, bool pushed); + +}; } #endif diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile index 8ad134648b..21bff06f95 100644 --- a/backends/platform/wince/Makefile +++ b/backends/platform/wince/Makefile @@ -113,7 +113,7 @@ INCLUDES := -I$(srcdir) -I. -I$(srcdir)/engines -Imissing/gcc -Ilibs/include -Il CFLAGS := ifndef UNOPTIMIZED_BUILD -CFLAGS += -O3 -march=armv4 -mtune=xscale +CFLAGS += -O3 -fno-inline-functions -march=armv4 -mtune=xscale endif LDFLAGS := -Wl,-Map,scummvm.exe.map -Wl,--stack,65536 diff --git a/backends/platform/wince/missing/io.h b/backends/platform/wince/missing/io.h index 8c66e9405b..96bc6a9ea1 100644 --- a/backends/platform/wince/missing/io.h +++ b/backends/platform/wince/missing/io.h @@ -5,9 +5,9 @@ #define strdup _strdup #ifndef _FILE_DEFINED - typedef void FILE; - #define _FILE_DEFINED +typedef void FILE; +#define _FILE_DEFINED #endif -FILE* wce_fopen(const char* fname, const char* fmode); +FILE *wce_fopen(const char *fname, const char *fmode); #define fopen wce_fopen diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp index 92af3e6961..c855247ae1 100644 --- a/backends/platform/wince/missing/missing.cpp +++ b/backends/platform/wince/missing/missing.cpp @@ -50,7 +50,7 @@ char *strdup(const char *strSource); // common missing functions required by both gcc and evc void *bsearch(const void *key, const void *base, size_t nmemb, - size_t size, int (*compar)(const void *, const void *)) { + size_t size, int (*compar)(const void *, const void *)) { // Perform binary search size_t lo = 0; size_t hi = nmemb; @@ -63,17 +63,17 @@ void *bsearch(const void *key, const void *base, size_t nmemb, else if (tmp > 0) lo = mid + 1; else - return (void *)p; + return const_cast<void *>(p); } return NULL; } -static char cwd[MAX_PATH+1] = ""; +static char cwd[MAX_PATH + 1] = ""; EXT_C char *getcwd(char *buffer, int maxlen) { - TCHAR fileUnc[MAX_PATH+1]; - char* plast; + TCHAR fileUnc[MAX_PATH + 1]; + char *plast; if (cwd[0] == 0) { GetModuleFileName(NULL, fileUnc, MAX_PATH); @@ -94,7 +94,7 @@ EXT_C char *getcwd(char *buffer, int maxlen) { #undef GetCurrentDirectory #endif EXT_C void GetCurrentDirectory(int len, char *buf) { - getcwd(buf,len); + getcwd(buf, len); } /* @@ -103,8 +103,8 @@ fully qualified paths refer to root folder rather than current folder (concept not implemented in CE). */ #undef fopen -EXT_C FILE *wce_fopen(const char* fname, const char* fmode) { - char fullname[MAX_PATH+1]; +EXT_C FILE *wce_fopen(const char *fname, const char *fmode) { + char fullname[MAX_PATH + 1]; if (!fname || fname[0] == '\0') return NULL; @@ -118,8 +118,8 @@ EXT_C FILE *wce_fopen(const char* fname, const char* fmode) { } /* Remove file by name */ -int remove(const char* path) { - TCHAR pathUnc[MAX_PATH+1]; +int remove(const char *path) { + TCHAR pathUnc[MAX_PATH + 1]; MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); return !DeleteFile(pathUnc); } @@ -128,15 +128,15 @@ int remove(const char* path) { /* check out file access permissions */ int _access(const char *path, int mode) { TCHAR fname[MAX_PATH]; - char fullname[MAX_PATH+1]; + char fullname[MAX_PATH + 1]; if (path[0] != '\\' && path[0] != '/') { getcwd(fullname, MAX_PATH); strcat(fullname, "\\"); strcat(fullname, path); - MultiByteToWideChar(CP_ACP, 0, fullname, -1, fname, sizeof(fname)/sizeof(TCHAR)); + MultiByteToWideChar(CP_ACP, 0, fullname, -1, fname, sizeof(fname) / sizeof(TCHAR)); } else - MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname)/sizeof(TCHAR)); + MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname) / sizeof(TCHAR)); WIN32_FIND_DATA ffd; HANDLE h = FindFirstFile(fname, &ffd); @@ -144,10 +144,10 @@ int _access(const char *path, int mode) { if (h == INVALID_HANDLE_VALUE) { // WORKAROUND: WinCE 3.0 doesn't find paths ending in '\' - if (path[strlen(path)-1] == '\\') { + if (path[strlen(path) - 1] == '\\') { char p2[MAX_PATH]; - strncpy(p2, path, strlen(path)-1); - p2[strlen(path) - 1]= '\0'; + strncpy(p2, path, strlen(path) - 1); + p2[strlen(path) - 1] = '\0'; return _access(p2, mode); } else return -1; //Can't find file @@ -158,7 +158,7 @@ int _access(const char *path, int mode) { // hits for files that don't exist. TRIPLE checking for the same fname // seems to weed out those false positives. // Exhibited in kyra engine. - HANDLE h = FindFirstFile(fname, &ffd); + h = FindFirstFile(fname, &ffd); FindClose(h); if (h == INVALID_HANDLE_VALUE) return -1; //Can't find file @@ -170,13 +170,13 @@ int _access(const char *path, int mode) { return 0; //Always return success if target is directory and exists } switch (mode) { - case 00: //Check existence - return 0; - case 06: //Check Read & Write permission - case 02: //Check Write permission - return ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? -1 : 0; - case 04: //Check Read permission - return 0; //Assume always have read permission + case 00: //Check existence + return 0; + case 06: //Check Read & Write permission + case 02: //Check Write permission + return ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? -1 : 0; + case 04: //Check Read permission + return 0; //Assume always have read permission } //Bad mode value supplied, return failure return -1; @@ -188,7 +188,7 @@ int _access(const char *path, int mode) { char *strdup(const char *strSource) { char *buffer; size_z len = strlen(strSource) + 1; - buffer = (char*)malloc(len); + buffer = (char *)malloc(len); if (buffer) memcpy(buffer, strSource, len); return buffer; @@ -199,25 +199,25 @@ char *strdup(const char *strSource) { #ifndef __MINGW32CE__ int islower(int c) { - return (c>='a' && c<='z'); + return (c >= 'a' && c <= 'z'); } int isspace(int c) { - return (c==' ' || c=='\f' || c=='\n' || c=='\r' || c=='\t' || c=='\v'); + return (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'); } int isalpha(int c) { - return ((c>='a' && c<='z') || (c>='A' && c<='Z')); + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); } int isalnum(int c) { - return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9')); + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')); } int isprint(int c) { //static const char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~"; //return (isalnum(c) || strchr(punct, c)); - return (32 <= c && c <= 126); // based on BSD manpage + return (32 <= c && c <= 126); // based on BSD manpage } #endif diff --git a/backends/platform/wince/missing/time.h b/backends/platform/wince/missing/time.h index f2bc5e4f89..a0ba6c246e 100644 --- a/backends/platform/wince/missing/time.h +++ b/backends/platform/wince/missing/time.h @@ -6,8 +6,7 @@ #include <stdlib.h> #ifndef __MINGW32CE__ -struct tm -{ +struct tm { short tm_year; short tm_mon; short tm_mday; @@ -23,8 +22,8 @@ struct tm #define EXT_C #endif -EXT_C time_t time(time_t* dummy); -EXT_C struct tm* localtime(time_t* dummy); +EXT_C time_t time(time_t *dummy); +EXT_C struct tm *localtime(time_t *dummy); unsigned int clock(); diff --git a/backends/platform/wince/portdefs.h b/backends/platform/wince/portdefs.h index cbf2006be2..8ad643946f 100644 --- a/backends/platform/wince/portdefs.h +++ b/backends/platform/wince/portdefs.h @@ -34,10 +34,10 @@ int isprint(int c); int isspace(int c); char *strrchr(const char *s, int c); char *strdup(const char *s); -int _stricmp( const char *string1, const char *string2 ); -int stricmp( const char *string1, const char *string2 ); -void assert( void* expression ); -void assert( int expression ); +int _stricmp(const char *string1, const char *string2); +int stricmp(const char *string1, const char *string2); +void assert(void *expression); +void assert(int expression); long int strtol(const char *nptr, char **endptr, int base); char *_strdup(const char *s); char *strpbrk(const char *s, const char *accept); @@ -47,20 +47,20 @@ char *strpbrk(const char *s, const char *accept); #ifdef _WIN32_WCE #ifndef __GNUC__ - void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *)); - char *getcwd(char *buf, int size); - typedef int ptrdiff_t; - void GetCurrentDirectory(int len, char *buf); - #define INVALID_FILE_ATTRIBUTES 0xffffffff +void *bsearch(const void *, const void *, size_t, size_t, int (*x)(const void *, const void *)); +char *getcwd(char *buf, int size); +typedef int ptrdiff_t; +void GetCurrentDirectory(int len, char *buf); +#define INVALID_FILE_ATTRIBUTES 0xffffffff #else - #include <math.h> - #undef GetCurrentDirectory - extern "C" void GetCurrentDirectory(int len, char *buf); - #define stricmp _stricmp - #define strnicmp _strnicmp - #define snprintf _snprintf - #define strdup _strdup - #define fopen wce_fopen +#include <math.h> +#undef GetCurrentDirectory +extern "C" void GetCurrentDirectory(int len, char *buf); +#define stricmp _stricmp +#define strnicmp _strnicmp +#define snprintf _snprintf +#define strdup _strdup +#define fopen wce_fopen #endif #include <windows.h> @@ -75,12 +75,12 @@ char *strpbrk(const char *s, const char *accept); //#include <direct.h> #ifdef __MINGW32CE__ - void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *)); +void *bsearch(const void *, const void *, size_t, size_t, int (*x)(const void *, const void *)); #endif int remove(const char *path); int _access(const char *path, int mode); -void drawError(char*); +void drawError(char *); #define vsnprintf _vsnprintf diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index ade90b2dfb..b54aebe6bd 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -23,6 +23,7 @@ * */ + // Disable symbol overrides so that we can use system headers. #define FORBIDDEN_SYMBOL_ALLOW_ALL @@ -32,6 +33,7 @@ #include "common/debug.h" #include "common/events.h" #include "common/util.h" +#include "common/textconsole.h" #include "common/timer.h" #include "common/translation.h" @@ -43,13 +45,12 @@ #include "audio/mixer_intern.h" #include "audio/fmopl.h" -#include "backends/timer/default/default-timer.h" +#include "backends/timer/sdl/sdl-timer.h" #include "gui/Actions.h" #include "gui/KeysDialog.h" #include "gui/message.h" -#include "backends/platform/wince/resource.h" #include "backends/platform/wince/CEActionsPocket.h" #include "backends/platform/wince/CEActionsSmartphone.h" #include "backends/platform/wince/CEgui/ItemAction.h" @@ -60,39 +61,22 @@ #include "backends/platform/wince/CEException.h" #include "backends/platform/wince/CEScaler.h" -#ifdef USE_VORBIS -#ifndef USE_TREMOR -#include <vorbis/vorbisfile.h> -#else -#include <tremor/ivorbisfile.h> -#endif -#endif +#include "backends/graphics/wincesdl/wincesdl-graphics.h" +#include "backends/events/wincesdl/wincesdl-events.h" +#include "backends/mixer/wincesdl/wincesdl-mixer.h" #ifdef DYNAMIC_MODULES #include "backends/plugins/win32/win32-provider.h" #endif #ifdef __GNUC__ -extern "C" _CRTIMP FILE* __cdecl _wfreopen (const wchar_t*, const wchar_t*, FILE*); +extern "C" _CRTIMP FILE *__cdecl _wfreopen(const wchar_t *, const wchar_t *, FILE *); #endif -#define SAMPLES_PER_SEC_OLD 11025 -#define SAMPLES_PER_SEC_NEW 22050 - using namespace CEGUI; // ******************************************************************************************** -// Internal GUI names - -#define NAME_MAIN_PANEL "MainPanel" -#define NAME_PANEL_KEYBOARD "Keyboard" -#define NAME_ITEM_OPTIONS "Options" -#define NAME_ITEM_SKIP "Skip" -#define NAME_ITEM_SOUND "Sound" -#define NAME_ITEM_ORIENTATION "Orientation" -#define NAME_ITEM_BINDKEYS "Bindkeys" - // stdin/err redirection #define STDOUT_FNAME "\\scummvm_stdout.txt" #define STDERR_FNAME "\\scummvm_stderr.txt" @@ -106,34 +90,6 @@ bool OSystem_WINCE3::_soundMaster = true; bool _isSmartphone = false; bool _hasSmartphoneResolution = false; -// Graphics mode consts - -// Low end devices 240x320 - -static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = { - {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, - {0, 0, 0} -}; - -// High end device 480x640 - -static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = { - {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, - {"2x", "2x", GFX_DOUBLESIZE}, -#ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :) - {"2xsai", "2xSAI", GFX_2XSAI}, - {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI}, - {"supereagle", "SuperEagle", GFX_SUPEREAGLE}, -#endif - {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X}, -#ifndef _MSC_VER - {"hq2x", "HQ2x", GFX_HQ2X}, - {"tv2x", "TV2x", GFX_TV2X}, -#endif - {"dotmatrix", "DotMatrix", GFX_DOTMATRIX}, - {0, 0, 0} -}; - #define DEFAULT_CONFIG_FILE "scummvm.ini" // ******************************************************************************************** @@ -144,7 +100,7 @@ bool isSmartphone() { } const TCHAR *ASCIItoUnicode(const char *str) { - static TCHAR ustr[MAX_PATH]; // size good enough + static TCHAR ustr[MAX_PATH]; // size good enough MultiByteToWideChar(CP_ACP, 0, str, strlen(str) + 1, ustr, sizeof(ustr) / sizeof(TCHAR)); return ustr; @@ -173,7 +129,7 @@ int SDL_main(int argc, char **argv) { // thanks to joostp and DJWillis extern void (*__CTOR_LIST__)(); void (**constructor)() = &__CTOR_LIST__; - constructor++; // First item in list of constructors has special meaning (platform dependent), ignore it. + constructor++; // First item in list of constructors has special meaning (platform dependent), ignore it. while (*constructor) { (*constructor)(); constructor++; @@ -238,10 +194,10 @@ int SDL_main(int argc, char **argv) { res = scummvm_main(argc, argv); // Free OSystem - delete (OSystem_WINCE3 *)g_system; + delete(OSystem_WINCE3 *)g_system; #if !defined(DEBUG) && !defined(__GNUC__) } - __except (handleException(GetExceptionInformation())) { + __except(handleException(GetExceptionInformation())) { } #endif @@ -264,22 +220,22 @@ int console_main(int argc, char *argv[]) { char *bufp, *appname; appname = argv[0]; - if ( (bufp=strrchr(argv[0], '\\')) != NULL ) + if ((bufp = strrchr(argv[0], '\\')) != NULL) appname = bufp + 1; - else if ( (bufp=strrchr(argv[0], '/')) != NULL ) + else if ((bufp = strrchr(argv[0], '/')) != NULL) appname = bufp + 1; - if ( (bufp=strrchr(appname, '.')) == NULL ) + if ((bufp = strrchr(appname, '.')) == NULL) n = strlen(appname); else - n = (bufp-appname); + n = (bufp - appname); bufp = (char *) alloca(n + 1); strncpy(bufp, appname, n); bufp[n] = '\0'; appname = bufp; - if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) { + if (SDL_Init(SDL_INIT_NOPARACHUTE) < 0) { error("WinMain() error: %d", SDL_GetError()); return(FALSE); } @@ -344,31 +300,31 @@ int dynamic_modules_main(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int int nLen; if (wcsncmp(szCmdLine, TEXT("\\"), 1)) { - nLen = wcslen(szCmdLine)+128+1; - bufp = (wchar_t *) alloca(nLen*2); - wcscpy (bufp, TEXT("\"")); - GetModuleFileName(NULL, bufp+1, 128-3); - wcscpy (bufp+wcslen(bufp), TEXT("\" ")); - wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp)); + nLen = wcslen(szCmdLine) + 128 + 1; + bufp = (wchar_t *) alloca(nLen * 2); + wcscpy(bufp, TEXT("\"")); + GetModuleFileName(NULL, bufp + 1, 128 - 3); + wcscpy(bufp + wcslen(bufp), TEXT("\" ")); + wcsncpy(bufp + wcslen(bufp), szCmdLine, nLen - wcslen(bufp)); } else bufp = szCmdLine; - nLen = wcslen(bufp)+1; + nLen = wcslen(bufp) + 1; cmdline = (char *) alloca(nLen); WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL); // Parse command line into argv and argc argc = ParseCommandLine(cmdline, NULL); - argv = (char **) alloca((argc+1)*(sizeof *argv)); + argv = (char **) alloca((argc + 1) * (sizeof * argv)); ParseCommandLine(cmdline, argv); // fix gdb-emulator combo while (argc > 1 && !strstr(argv[0], ".exe")) { OutputDebugString(TEXT("SDL: gdb argv[0] fixup\n")); - *(argv[1]-1) = ' '; + *(argv[1] - 1) = ' '; int i; - for (i=1; i<argc; i++) - argv[i] = argv[i+1]; + for (i = 1; i < argc; i++) + argv[i] = argv[i + 1]; argc--; } @@ -380,7 +336,6 @@ int dynamic_modules_main(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int // ******************************************************************************************** - // ******************************************************************************************** void pumpMessages() { @@ -407,47 +362,53 @@ static Uint32 timer_handler_wrapper(Uint32 interval) { } void OSystem_WINCE3::initBackend() { - // Instantiate our own sound mixer - // mixer init is rerun when a game engine is selected. - setupMixer(); + + assert(!_inited); + + // Create the backend custom managers + if (_eventSource == 0) + _eventSource = new WINCESdlEventSource(); + + if (_mixerManager == 0) { + _mixerManager = new WINCESdlMixerManager(); + + // Setup and start mixer + _mixerManager->init(); + } + + if (_graphicsManager == 0) + _graphicsManager = new WINCESdlGraphicsManager(_eventSource); + + ((WINCESdlEventSource *)_eventSource)->init((WINCESdlGraphicsManager *)_graphicsManager); // Create the timer. CE SDL does not support multiple timers (SDL_AddTimer). // We work around this by using the SetTimer function, since we only use // one timer in scummvm (for the time being) _timer = _int_timer = new DefaultTimerManager(); - _timerID = NULL; // OSystem_SDL will call removetimer with this, it's ok + //_timerID = NULL; // OSystem_SDL will call removetimer with this, it's ok SDL_SetTimer(10, &timer_handler_wrapper); // Chain init OSystem_SDL::initBackend(); - // Query SDL for screen size and init screen dependent stuff - OSystem_WINCE3::initScreenInfos(); - _isSmartphone = CEDevice::isSmartphone(); - create_toolbar(); - _hasSmartphoneResolution = CEDevice::hasSmartphoneResolution() || CEDevice::isSmartphone(); - if (_hasSmartphoneResolution) - _panelVisible = false; // init correctly in smartphones - // Initialize global key mapping GUI::Actions::init(); GUI_Actions::Instance()->initInstanceMain(this); - if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version + if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version warning("Setting default action mappings"); - GUI_Actions::Instance()->saveMapping(); // write defaults + GUI_Actions::Instance()->saveMapping(); // write defaults } - loadDeviceConfiguration(); + // Call parent implementation of this method + //OSystem_SDL::initBackend(); + + _inited = true; } int OSystem_WINCE3::getScreenWidth() { return _platformScreenWidth; } -int OSystem_WINCE3::getScreenHeight() { - return _platformScreenHeight; -} - void OSystem_WINCE3::initScreenInfos() { // sdl port ensures that we use correctly full screen _isOzone = 0; @@ -457,6 +418,10 @@ void OSystem_WINCE3::initScreenInfos() { _platformScreenHeight = r[0]->h; } +int OSystem_WINCE3::getScreenHeight() { + return _platformScreenHeight; +} + bool OSystem_WINCE3::isOzone() { return _isOzone; } @@ -473,496 +438,37 @@ Common::String OSystem_WINCE3::getDefaultConfigFileName() { OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(), - _orientationLandscape(0), _newOrientation(0), _panelInitialized(false), _canBeAspectScaled(false), - _panelVisible(true), _panelStateForced(false), _forceHideMouse(false), _unfilteredkeys(false), - _freeLook(false), _forcePanelInvisible(false), _toolbarHighDrawn(false), _zoomUp(false), _zoomDown(false), - _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false), _noDoubleTapRMB(false), - _saveToolbarState(false), _saveActiveToolbar(NAME_MAIN_PANEL), _rbutton(false), _hasfocus(true), - _usesEmulatedMouse(false), _mouseBackupOld(NULL), _mouseBackupToolbar(NULL), _mouseBackupDim(0) -{ - memset(&_mouseCurState, 0, sizeof(_mouseCurState)); - if (_isSmartphone) { - _mouseCurState.x = 20; - _mouseCurState.y = 20; - } - + _forcePanelInvisible(false) { + // Initialze File System Factory + _fsFactory = new WindowsFilesystemFactory(); _mixer = 0; - _screen = NULL; } -void OSystem_WINCE3::swap_panel_visibility() { - //if (!_forcePanelInvisible && !_panelStateForced) { - if (_zoomDown || _zoomUp) return; - - if (_panelVisible) { - if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD) - _panelVisible = !_panelVisible; - else - _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); - } else { - _toolbarHandler.setActive(NAME_MAIN_PANEL); - _panelVisible = !_panelVisible; - } - _toolbarHandler.setVisible(_panelVisible); - _toolbarHighDrawn = false; - - if (_videoMode.screenHeight > 240) - addDirtyRect(0, 400, 640, 80); - else - addDirtyRect(0, 200, 320, 40); - - if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible) - internUpdateScreen(); - else { - update_scalers(); - hotswapGFXMode(); - } - //} +OSystem_WINCE3::~OSystem_WINCE3() { + delete _fsFactory; + delete _mixer; } -void OSystem_WINCE3::swap_panel() { - _toolbarHighDrawn = false; - //if (!_panelStateForced) { - if (_toolbarHandler.activeName() == NAME_PANEL_KEYBOARD && _panelVisible) - _toolbarHandler.setActive(NAME_MAIN_PANEL); - else - _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); - - if (_videoMode.screenHeight > 240) - addDirtyRect(0, 400, 640, 80); - else - addDirtyRect(0, 200, 320, 40); - - _toolbarHandler.setVisible(true); - if (!_panelVisible) { - _panelVisible = true; - update_scalers(); - hotswapGFXMode(); - } - //} -} - -void OSystem_WINCE3::swap_smartphone_keyboard() { - _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); - _panelVisible = !_panelVisible; - _toolbarHandler.setVisible(_panelVisible); - if (_videoMode.screenHeight > 240) - addDirtyRect(0, 0, 640, 80); - else - addDirtyRect(0, 0, 320, 40); - internUpdateScreen(); -} - -void OSystem_WINCE3::smartphone_rotate_display() { - _orientationLandscape = _newOrientation = _orientationLandscape == 1 ? 2 : 1; - ConfMan.setInt("landscape", _orientationLandscape); - ConfMan.flushToDisk(); - hotswapGFXMode(); +FilesystemFactory *OSystem_WINCE3::getFilesystemFactory() { + return _fsFactory; } void OSystem_WINCE3::swap_sound_master() { _soundMaster = !_soundMaster; - if (_toolbarHandler.activeName() == NAME_MAIN_PANEL) - _toolbarHandler.forceRedraw(); // redraw sound icon -} - -void OSystem_WINCE3::add_right_click(bool pushed) { - int x, y; - retrieve_mouse_location(x, y); - EventsBuffer::simulateMouseRightClick(x, y, pushed); -} - -void OSystem_WINCE3::swap_mouse_visibility() { - _forceHideMouse = !_forceHideMouse; - if (_forceHideMouse) - undrawMouse(); -} - -void OSystem_WINCE3::swap_freeLook() { - _freeLook = !_freeLook; -} -void OSystem_WINCE3::swap_zoom_up() { - if (_zoomUp) { - // restore visibility - _toolbarHandler.setVisible(_saveToolbarZoom); - // restore scaler - _scaleFactorYd = 2; - _scalerProc = DownscaleAllByHalf; - _zoomUp = false; - _zoomDown = false; - } else { - // only active if running on a PocketPC - if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf) - return; - if (_scalerProc == DownscaleAllByHalf) { - _saveToolbarZoom = _toolbarHandler.visible(); - _toolbarHandler.setVisible(false); - // set zoom scaler - _scaleFactorYd = 1; - _scalerProc = DownscaleHorizByHalf; - } + //WINCESdlGraphicsManager _graphicsManager - _zoomDown = false; - _zoomUp = true; - } - // redraw whole screen - addDirtyRect(0, 0, 640, 480); - internUpdateScreen(); + if (((WINCESdlGraphicsManager *)_graphicsManager)->_toolbarHandler.activeName() == NAME_MAIN_PANEL) + ((WINCESdlGraphicsManager *)_graphicsManager)->_toolbarHandler.forceRedraw(); // redraw sound icon } -void OSystem_WINCE3::swap_zoom_down() { - if (_zoomDown) { - // restore visibility - _toolbarHandler.setVisible(_saveToolbarZoom); - // restore scaler - _scaleFactorYd = 2; - _scalerProc = DownscaleAllByHalf; - _zoomDown = false; - _zoomUp = false; - } else { - // only active if running on a PocketPC - if (_scalerProc != DownscaleAllByHalf && _scalerProc != DownscaleHorizByHalf) - return; - if (_scalerProc == DownscaleAllByHalf) { - _saveToolbarZoom = _toolbarHandler.visible(); - _toolbarHandler.setVisible(false); - // set zoom scaler - _scaleFactorYd = 1; - _scalerProc = DownscaleHorizByHalf; - } - - _zoomUp = false; - _zoomDown = true; - } - // redraw whole screen - addDirtyRect(0, 0, 640, 480); - internUpdateScreen(); -} - -// Smartphone actions -void OSystem_WINCE3::initZones() { - int i; - - _currentZone = 0; - for (i = 0; i < TOTAL_ZONES; i++) { - _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)) * _scaleFactorXm / _scaleFactorXd; - _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)) * _scaleFactorYm / _scaleFactorYd; - } -} - -void OSystem_WINCE3::loadDeviceConfigurationElement(String element, int &value, int defaultValue) { - value = ConfMan.getInt(element, ConfMan.kApplicationDomain); - if (!value) { - value = defaultValue; - ConfMan.setInt(element, value, ConfMan.kApplicationDomain); - } -} - -void OSystem_WINCE3::loadDeviceConfiguration() { - loadDeviceConfigurationElement("repeatTrigger", _keyRepeatTrigger, 200); - loadDeviceConfigurationElement("repeatX", _repeatX, 4); - loadDeviceConfigurationElement("repeatY", _repeatY, 4); - loadDeviceConfigurationElement("stepX1", _stepX1, 2); - loadDeviceConfigurationElement("stepX2", _stepX2, 10); - loadDeviceConfigurationElement("stepX3", _stepX3, 40); - loadDeviceConfigurationElement("stepY1", _stepY1, 2); - loadDeviceConfigurationElement("stepY2", _stepY2, 10); - loadDeviceConfigurationElement("stepY3", _stepY3, 20); - ConfMan.flushToDisk(); -} - -void OSystem_WINCE3::add_left_click(bool pushed) { - int x, y; - retrieve_mouse_location(x, y); - EventsBuffer::simulateMouseLeftClick(x, y, pushed); -} - -void OSystem_WINCE3::move_cursor_up() { - int x, y; - _usesEmulatedMouse = true; - retrieve_mouse_location(x, y); - if (_keyRepeat > _repeatY) - y -= _stepY3; - else if (_keyRepeat) - y -= _stepY2; - else - y -= _stepY1; - - if (y < 0) - y = 0; - - EventsBuffer::simulateMouseMove(x, y); -} - -void OSystem_WINCE3::move_cursor_down() { - int x, y; - _usesEmulatedMouse = true; - retrieve_mouse_location(x, y); - if (_keyRepeat > _repeatY) - y += _stepY3; - else if (_keyRepeat) - y += _stepY2; - else - y += _stepY1; - - if (y > _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd) - y = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd; - - EventsBuffer::simulateMouseMove(x, y); -} - -void OSystem_WINCE3::move_cursor_left() { - int x, y; - _usesEmulatedMouse = true; - retrieve_mouse_location(x, y); - if (_keyRepeat > _repeatX) - x -= _stepX3; - else if (_keyRepeat) - x -= _stepX2; - else - x -= _stepX1; - - if (x < 0) - x = 0; - - EventsBuffer::simulateMouseMove(x, y); -} - -void OSystem_WINCE3::move_cursor_right() { - int x, y; - _usesEmulatedMouse = true; - retrieve_mouse_location(x, y); - if (_keyRepeat > _repeatX) - x += _stepX3; - else if (_keyRepeat) - x += _stepX2; - else - x += _stepX1; - - if (x > _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd) - x = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd; - - EventsBuffer::simulateMouseMove(x, y); -} - -void OSystem_WINCE3::switch_zone() { - int x, y; - int i; - retrieve_mouse_location(x, y); - - for (i = 0; i < TOTAL_ZONES; i++) - if (x >= _zones[i].x && y >= _zones[i].y && - x <= _zones[i].x + _zones[i].width && y <= _zones[i].y + _zones[i].height) { - _mouseXZone[i] = x; - _mouseYZone[i] = y; - break; - } - _currentZone = i + 1; - if (_currentZone >= TOTAL_ZONES) - _currentZone = 0; - - EventsBuffer::simulateMouseMove(_mouseXZone[_currentZone], _mouseYZone[_currentZone]); -} - -void OSystem_WINCE3::create_toolbar() { - PanelKeyboard *keyboard; - - // Add the keyboard - keyboard = new PanelKeyboard(PANEL_KEYBOARD); - _toolbarHandler.add(NAME_PANEL_KEYBOARD, *keyboard); - _toolbarHandler.setVisible(false); -} - -void OSystem_WINCE3::setupMixer() { - SDL_AudioSpec desired; - int thread_priority; - - uint32 sampleRate = compute_sample_rate(); - if (sampleRate == 0) - warning("OSystem_WINCE3::setupMixer called with sample rate 0 - audio will not work"); - else if (_mixer && _mixer->getOutputRate() == sampleRate) { - debug(1, "Skipping sound mixer re-init: samplerate is good"); - return; - } - - memset(&desired, 0, sizeof(desired)); - desired.freq = sampleRate; - desired.format = AUDIO_S16SYS; - desired.channels = 2; - desired.samples = 128; - desired.callback = private_sound_proc; - desired.userdata = this; - - // Create the mixer instance - if (_mixer == 0) - _mixer = new Audio::MixerImpl(this, sampleRate); - - // Add sound thread priority - if (!ConfMan.hasKey("sound_thread_priority")) - thread_priority = THREAD_PRIORITY_NORMAL; - else - thread_priority = ConfMan.getInt("sound_thread_priority"); - - desired.thread_priority = thread_priority; - - SDL_CloseAudio(); - if (SDL_OpenAudio(&desired, NULL) != 0) { - warning("Could not open audio device: %s", SDL_GetError()); - _mixer->setReady(false); - - } else { - debug(1, "Sound opened OK, mixing at %d Hz", sampleRate); - - // Re-create mixer to match the output rate - int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType); - int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); - int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType); - int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType); - delete _mixer; - _mixer = new Audio::MixerImpl(this, sampleRate); - _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4); - _mixer->setReady(true); - SDL_PauseAudio(0); - } -} - -void OSystem_WINCE3::private_sound_proc(void *param, byte *buf, int len) { - OSystem_WINCE3 *this_ = (OSystem_WINCE3 *)param; - assert(this_); - - if (this_->_mixer) - this_->_mixer->mixCallback(buf, len); - if (!_soundMaster) - memset(buf, 0, len); -} - -#ifdef USE_VORBIS -bool OSystem_WINCE3::checkOggHighSampleRate() { - char trackFile[255]; - FILE *testFile; - OggVorbis_File *test_ov_file = new OggVorbis_File; - - // FIXME: The following sprintf assumes that "path" is always - // terminated by a path separator. This is *not* true in general. - // This code really should check for the path separator, or even - // better, use the FSNode API. - sprintf(trackFile, "%sTrack1.ogg", ConfMan.get("path").c_str()); - // Check if we have an OGG audio track - testFile = fopen(trackFile, "rb"); - if (testFile) { - if (!ov_open(testFile, test_ov_file, NULL, 0)) { - bool highSampleRate = (ov_info(test_ov_file, -1)->rate == 22050); - ov_clear(test_ov_file); - delete test_ov_file; - return highSampleRate; - } - } - - // Do not test for OGG samples - too big and too slow anyway :) - - delete test_ov_file; - return false; -} -#endif - -uint32 OSystem_WINCE3::compute_sample_rate() { - uint32 sampleRate; - - // Force at least medium quality FM synthesis for FOTAQ - Common::String gameid(ConfMan.get("gameid")); - if (gameid == "queen") { - if (!((ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) || - (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")))) { - ConfMan.setBool("FM_medium_quality", true); - ConfMan.flushToDisk(); - } - } - // See if the output frequency is forced by the game - if (gameid == "ft" || gameid == "dig" || gameid == "comi" || gameid == "queen" || gameid == "sword" || gameid == "agi") - sampleRate = SAMPLES_PER_SEC_NEW; - else { - if (ConfMan.hasKey("high_sample_rate") && ConfMan.getBool("high_sample_rate")) - sampleRate = SAMPLES_PER_SEC_NEW; - else - sampleRate = SAMPLES_PER_SEC_OLD; - } - -#ifdef USE_VORBIS - // Modify the sample rate on the fly if OGG is involved - if (sampleRate == SAMPLES_PER_SEC_OLD) - if (checkOggHighSampleRate()) - sampleRate = SAMPLES_PER_SEC_NEW; -#endif - - return sampleRate; -} void OSystem_WINCE3::engineInit() { check_mappings(); // called here to initialize virtual keys handling //update_game_settings(); // finalize mixer init - setupMixer(); -} - -const OSystem::GraphicsMode *OSystem_WINCE3::getSupportedGraphicsModes() const { - if (CEDevice::hasWideResolution()) - return s_supportedGraphicsModesHigh; - else - return s_supportedGraphicsModesLow; -} - -bool OSystem_WINCE3::hasFeature(Feature f) { - return (f == kFeatureVirtualKeyboard); -} - -void OSystem_WINCE3::setFeatureState(Feature f, bool enable) { - switch (f) { - case kFeatureFullscreenMode: - return; - - case kFeatureVirtualKeyboard: - if (_hasSmartphoneResolution) - return; - _toolbarHighDrawn = false; - if (enable) { - _panelStateForced = true; - if (!_toolbarHandler.visible()) swap_panel_visibility(); - //_saveToolbarState = _toolbarHandler.visible(); - _saveActiveToolbar = _toolbarHandler.activeName(); - _toolbarHandler.setActive(NAME_PANEL_KEYBOARD); - _toolbarHandler.setVisible(true); - } else - if (_panelStateForced) { - _panelStateForced = false; - _toolbarHandler.setActive(_saveActiveToolbar); - //_toolbarHandler.setVisible(_saveToolbarState); - } - return; - - case kFeatureDisableKeyFiltering: - if (_hasSmartphoneResolution) - _unfilteredkeys = enable; - return; - - default: - OSystem_SDL::setFeatureState(f, enable); - } -} - -bool OSystem_WINCE3::getFeatureState(Feature f) { - switch (f) { - case kFeatureFullscreenMode: - return false; - case kFeatureVirtualKeyboard: - return (_panelStateForced); - default: - return OSystem_SDL::getFeatureState(f); - } + _mixerManager->init(); } void OSystem_WINCE3::check_mappings() { @@ -974,7 +480,7 @@ void OSystem_WINCE3::check_mappings() { return; GUI_Actions::Instance()->initInstanceGame(); - instance = (CEActionsPocket*)GUI_Actions::Instance(); + instance = (CEActionsPocket *)GUI_Actions::Instance(); // Some games need to map the right click button, signal it here if it wasn't done if (instance->needsRightClickMapping()) { @@ -1014,1472 +520,39 @@ void OSystem_WINCE3::check_mappings() { // Extra warning for Zak Mc Kracken if (strncmp(gameid.c_str(), "zak", 3) == 0 && - !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) { + !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) { GUI::MessageDialog alert(_("Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory")); alert.runModal(); } } -void OSystem_WINCE3::update_game_settings() { - Common::String gameid(ConfMan.get("gameid")); - - // Finish panel initialization - if (!_panelInitialized && !gameid.empty()) { - Panel *panel; - _panelInitialized = true; - // Add the main panel - panel = new Panel(0, 32); - panel->setBackground(IMAGE_PANEL); - // Save - panel->add(NAME_ITEM_OPTIONS, new ItemAction(ITEM_OPTIONS, POCKET_ACTION_SAVE)); - // Skip - panel->add(NAME_ITEM_SKIP, new ItemAction(ITEM_SKIP, POCKET_ACTION_SKIP)); - // sound - panel->add(NAME_ITEM_SOUND, new ItemSwitch(ITEM_SOUND_OFF, ITEM_SOUND_ON, &_soundMaster)); - // bind keys - panel->add(NAME_ITEM_BINDKEYS, new ItemAction(ITEM_BINDKEYS, POCKET_ACTION_BINDKEYS)); - // portrait/landscape - screen dependent - // FIXME : will still display the portrait/landscape icon when using a scaler (but will be disabled) - if (ConfMan.hasKey("landscape")) { - if (ConfMan.get("landscape")[0] > 57) { - _newOrientation = _orientationLandscape = ConfMan.getBool("landscape"); - //ConfMan.removeKey("landscape", ""); - ConfMan.setInt("landscape", _orientationLandscape); - } else - _newOrientation = _orientationLandscape = ConfMan.getInt("landscape"); - } else { - _newOrientation = _orientationLandscape = 0; - } - panel->add(NAME_ITEM_ORIENTATION, new ItemSwitch(ITEM_VIEW_LANDSCAPE, ITEM_VIEW_PORTRAIT, &_newOrientation, 2)); - _toolbarHandler.add(NAME_MAIN_PANEL, *panel); - _toolbarHandler.setActive(NAME_MAIN_PANEL); - _toolbarHandler.setVisible(true); - - if (_videoMode.mode == GFX_NORMAL && ConfMan.hasKey("landscape") && ConfMan.getInt("landscape")) { - setGraphicsMode(GFX_NORMAL); - hotswapGFXMode(); - } - - if (_hasSmartphoneResolution) - panel->setVisible(false); - - _saveToolbarState = true; - } - - if (ConfMan.hasKey("no_doubletap_rightclick")) - _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick"); -} - -void OSystem_WINCE3::initSize(uint w, uint h, const Graphics::PixelFormat *format) { - if (_hasSmartphoneResolution && h == 240) - h = 200; // mainly for the launcher - - if (_isSmartphone && !ConfMan.hasKey("landscape")) { - ConfMan.setInt("landscape", 1); - ConfMan.flushToDisk(); - } - - _canBeAspectScaled = false; - if (w == 320 && h == 200 && !_hasSmartphoneResolution) { - _canBeAspectScaled = true; - h = 240; // use the extra 40 pixels height for the toolbar - } - - if (h == 400) // touche engine fixup - h += 80; - - if (!_hasSmartphoneResolution) { - if (h == 240) - _toolbarHandler.setOffset(200); - else - _toolbarHandler.setOffset(400); - } else { - if (h == 240) - _toolbarHandler.setOffset(200); - else // 176x220 - _toolbarHandler.setOffset(0); - } - - if (w != (uint) _videoMode.screenWidth || h != (uint) _videoMode.screenHeight) - _scalersChanged = false; - - _videoMode.overlayWidth = w; - _videoMode.overlayHeight = h; - - OSystem_SDL::initSize(w, h, format); - - if (_scalersChanged) { - unloadGFXMode(); - loadGFXMode(); - _scalersChanged = false; - } - - update_game_settings(); -} - - -int OSystem_WINCE3::getDefaultGraphicsMode() const { - return GFX_NORMAL; -} - void OSystem_WINCE3::setGraphicsModeIntern() { // Scalers have been pre-selected for the desired mode. // No further tuning required. } -bool OSystem_WINCE3::update_scalers() { - _videoMode.aspectRatioCorrection = false; - - if (CEDevice::hasPocketPCResolution()) { - if (_videoMode.mode != GFX_NORMAL) - return false; - - if ((!_orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) - || CEDevice::hasSquareQVGAResolution() ) { - if (getScreenWidth() != 320) { - _scaleFactorXm = 3; - _scaleFactorXd = 4; - _scaleFactorYm = 1; - _scaleFactorYd = 1; - _scalerProc = DownscaleHorizByThreeQuarters; - } else { - _scaleFactorXm = 1; - _scaleFactorXd = 1; - _scaleFactorYm = 1; - _scaleFactorYd = 1; - _scalerProc = Normal1x; - } - } else if ( _orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) { - if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) { - _scaleFactorXm = 1; - _scaleFactorXd = 1; - _scaleFactorYm = 6; - _scaleFactorYd = 5; - _scalerProc = Normal1xAspect; - _videoMode.aspectRatioCorrection = true; - } else { - _scaleFactorXm = 1; - _scaleFactorXd = 1; - _scaleFactorYm = 1; - _scaleFactorYd = 1; - _scalerProc = Normal1x; - } - } else if (_videoMode.screenWidth == 640 && !(isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) { - _scaleFactorXm = 1; - _scaleFactorXd = 2; - _scaleFactorYm = 1; - _scaleFactorYd = 2; - _scalerProc = DownscaleAllByHalf; - } else if (_videoMode.screenWidth == 640 && (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) { - _scaleFactorXm = 1; - _scaleFactorXd = 1; - _scaleFactorYm = 1; - _scaleFactorYd = 1; - _scalerProc = Normal1x; - } - - return true; - } else if (CEDevice::hasWideResolution()) { -#ifdef USE_ARM_SCALER_ASM - if ( _videoMode.mode == GFX_DOUBLESIZE && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth) ) { - if ( !_panelVisible && !_overlayVisible && _canBeAspectScaled ) { - _scaleFactorXm = 2; - _scaleFactorXd = 1; - _scaleFactorYm = 12; - _scaleFactorYd = 5; - _scalerProc = Normal2xAspect; - _videoMode.aspectRatioCorrection = true; - } else if ( (_panelVisible || _overlayVisible) && _canBeAspectScaled ) { - _scaleFactorXm = 2; - _scaleFactorXd = 1; - _scaleFactorYm = 2; - _scaleFactorYd = 1; - _scalerProc = Normal2x; - } - return true; - } -#endif - } else if (CEDevice::hasSmartphoneResolution()) { - if (_videoMode.mode != GFX_NORMAL) - return false; - - if (_videoMode.screenWidth > 320) - error("Game resolution not supported on Smartphone"); -#ifdef ARM - _scaleFactorXm = 11; - _scaleFactorXd = 16; -#else - _scaleFactorXm = 2; - _scaleFactorXd = 3; -#endif - _scaleFactorYm = 7; - _scaleFactorYd = 8; - _scalerProc = SmartphoneLandscape; - initZones(); - return true; - } - - return false; -} - -bool OSystem_WINCE3::setGraphicsMode(int mode) { - - Common::StackLock lock(_graphicsMutex); - int oldScaleFactorXm = _scaleFactorXm; - int oldScaleFactorXd = _scaleFactorXd; - int oldScaleFactorYm = _scaleFactorYm; - int oldScaleFactorYd = _scaleFactorYd; - - _scaleFactorXm = -1; - _scaleFactorXd = -1; - _scaleFactorYm = -1; - _scaleFactorYd = -1; - - if (ConfMan.hasKey("landscape")) - if (ConfMan.get("landscape")[0] > 57) { - _newOrientation = _orientationLandscape = ConfMan.getBool("landscape"); - ConfMan.setInt("landscape", _orientationLandscape); - } else - _newOrientation = _orientationLandscape = ConfMan.getInt("landscape"); - else - _newOrientation = _orientationLandscape = 0; - - if (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640) && mode) - _scaleFactorXm = -1; - - if (CEDevice::hasPocketPCResolution() && !CEDevice::hasWideResolution() && _orientationLandscape) - _videoMode.mode = GFX_NORMAL; - else - _videoMode.mode = mode; - - if (_scaleFactorXm < 0) { - /* Standard scalers, from the SDL backend */ - switch (_videoMode.mode) { - case GFX_NORMAL: - _videoMode.scaleFactor = 1; - _scalerProc = Normal1x; - break; - case GFX_DOUBLESIZE: - _videoMode.scaleFactor = 2; - _scalerProc = Normal2x; - break; - case GFX_TRIPLESIZE: - _videoMode.scaleFactor = 3; - _scalerProc = Normal3x; - break; - case GFX_2XSAI: - _videoMode.scaleFactor = 2; - _scalerProc = _2xSaI; - break; - case GFX_SUPER2XSAI: - _videoMode.scaleFactor = 2; - _scalerProc = Super2xSaI; - break; - case GFX_SUPEREAGLE: - _videoMode.scaleFactor = 2; - _scalerProc = SuperEagle; - break; - case GFX_ADVMAME2X: - _videoMode.scaleFactor = 2; - _scalerProc = AdvMame2x; - break; - case GFX_ADVMAME3X: - _videoMode.scaleFactor = 3; - _scalerProc = AdvMame3x; - break; -#ifdef USE_HQ_SCALERS - case GFX_HQ2X: - _videoMode.scaleFactor = 2; - _scalerProc = HQ2x; - break; - case GFX_HQ3X: - _videoMode.scaleFactor = 3; - _scalerProc = HQ3x; - break; -#endif - case GFX_TV2X: - _videoMode.scaleFactor = 2; - _scalerProc = TV2x; - break; - case GFX_DOTMATRIX: - _videoMode.scaleFactor = 2; - _scalerProc = DotMatrix; - break; - - default: - error("unknown gfx mode %d", mode); - } - } - - // Check if the scaler can be accepted, if not get back to normal scaler - if (_videoMode.scaleFactor && ((_videoMode.scaleFactor * _videoMode.screenWidth > getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenWidth > getScreenHeight()) - || (_videoMode.scaleFactor * _videoMode.screenHeight > getScreenWidth() && _videoMode.scaleFactor * _videoMode.screenHeight > getScreenHeight()))) { - _videoMode.scaleFactor = 1; - _scalerProc = Normal1x; - } - - // Common scaler system was used - if (_scaleFactorXm < 0) { - _scaleFactorXm = _videoMode.scaleFactor; - _scaleFactorXd = 1; - _scaleFactorYm = _videoMode.scaleFactor; - _scaleFactorYd = 1; - } - - _forceFull = true; - - if (oldScaleFactorXm != _scaleFactorXm || - oldScaleFactorXd != _scaleFactorXd || - oldScaleFactorYm != _scaleFactorYm || - oldScaleFactorYd != _scaleFactorYd) { - _scalersChanged = true; - } - else - _scalersChanged = false; - - - return true; - -} - -bool OSystem_WINCE3::loadGFXMode() { - int displayWidth; - int displayHeight; - unsigned int flags = SDL_FULLSCREEN | SDL_SWSURFACE; - - _videoMode.fullscreen = true; // forced - _forceFull = true; - - _tmpscreen = NULL; - - // Recompute scalers if necessary - update_scalers(); - - // Create the surface that contains the 8 bit game data - _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0); - if (_screen == NULL) - error("_screen failed (%s)", SDL_GetError()); - - // Create the surface that contains the scaled graphics in 16 bit mode - // Always use full screen mode to have a "clean screen" - if (!_videoMode.aspectRatioCorrection) { - displayWidth = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd; - displayHeight = _videoMode.screenHeight * _scaleFactorYm / _scaleFactorYd; - } else { - displayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - displayHeight = _videoMode.screenHeight* _videoMode.scaleFactor; - } - - switch (_orientationLandscape) { - case 1: - flags |= SDL_LANDSCVIDEO; - break; - case 2: - flags |= SDL_INVLNDVIDEO; - break; - default: - flags |= SDL_PORTRTVIDEO; - } - _hwscreen = SDL_SetVideoMode(displayWidth, displayHeight, 16, flags); - - if (_hwscreen == NULL) { - warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError()); - quit(); - } - - // see what orientation sdl finally accepted - if (_hwscreen->flags & SDL_PORTRTVIDEO) - _orientationLandscape = _newOrientation = 0; - else if (_hwscreen->flags & SDL_LANDSCVIDEO) - _orientationLandscape = _newOrientation = 1; - else - _orientationLandscape = _newOrientation = 2; - - // Create the surface used for the graphics in 16 bit before scaling, and also the overlay - // Distinguish 555 and 565 mode - if (_hwscreen->format->Rmask == 0x7C00) - InitScalers(555); - else - InitScalers(565); - _overlayFormat.bytesPerPixel = _hwscreen->format->BytesPerPixel; - _overlayFormat.rLoss = _hwscreen->format->Rloss; - _overlayFormat.gLoss = _hwscreen->format->Gloss; - _overlayFormat.bLoss = _hwscreen->format->Bloss; - _overlayFormat.aLoss = _hwscreen->format->Aloss; - _overlayFormat.rShift = _hwscreen->format->Rshift; - _overlayFormat.gShift = _hwscreen->format->Gshift; - _overlayFormat.bShift = _hwscreen->format->Bshift; - _overlayFormat.aShift = _hwscreen->format->Ashift; - - // Need some extra bytes around when using 2xSaI - _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask); - - if (_tmpscreen == NULL) - error("_tmpscreen creation failed (%s)", SDL_GetError()); - - // Overlay - if (CEDevice::hasDesktopResolution()) { - _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd, 16, 0, 0, 0, 0); - if (_overlayscreen == NULL) - error("_overlayscreen failed (%s)", SDL_GetError()); - _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth * _scaleFactorXm / _scaleFactorXd + 3, _videoMode.overlayHeight * _scaleFactorYm / _scaleFactorYd + 3, 16, 0, 0, 0, 0); - if (_tmpscreen2 == NULL) - error("_tmpscreen2 failed (%s)", SDL_GetError()); - } else { - _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, 0, 0, 0, 0); - if (_overlayscreen == NULL) - error("_overlayscreen failed (%s)", SDL_GetError()); - _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, 0, 0, 0, 0); - if (_tmpscreen2 == NULL) - error("_tmpscreen2 failed (%s)", SDL_GetError()); - } - - // Toolbar - _toolbarHighDrawn = false; - uint16 *toolbar_screen = (uint16 *)calloc(320 * 40, sizeof(uint16)); // *not* leaking memory here - _toolbarLow = SDL_CreateRGBSurfaceFrom(toolbar_screen, 320, 40, 16, 320 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask); - - if (_toolbarLow == NULL) - error("_toolbarLow failed (%s)", SDL_GetError()); - - if (_videoMode.screenHeight > 240) { - uint16 *toolbar_screen = (uint16 *)calloc(640 * 80, sizeof(uint16)); - _toolbarHigh = SDL_CreateRGBSurfaceFrom(toolbar_screen, 640, 80, 16, 640 * 2, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask); - - if (_toolbarHigh == NULL) - error("_toolbarHigh failed (%s)", SDL_GetError()); - } else - _toolbarHigh = NULL; - - - // keyboard cursor control, some other better place for it? - _km.x_max = _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd - 1; - _km.y_max = _videoMode.screenHeight * _scaleFactorXm / _scaleFactorXd - 1; - _km.delay_time = 25; - _km.last_time = 0; - - return true; -} - -void OSystem_WINCE3::unloadGFXMode() { - if (_screen) { - SDL_FreeSurface(_screen); - _screen = NULL; - } - - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; - } - - if (_tmpscreen) { - SDL_FreeSurface(_tmpscreen); - _tmpscreen = NULL; - } -} - -bool OSystem_WINCE3::hotswapGFXMode() { - if (!_screen) - return false; - - // Keep around the old _screen & _tmpscreen so we can restore the screen data - // after the mode switch. (also for the overlay) - SDL_Surface *old_screen = _screen; - SDL_Surface *old_tmpscreen = _tmpscreen; - SDL_Surface *old_overlayscreen = _overlayscreen; - SDL_Surface *old_tmpscreen2 = _tmpscreen2; - - // Release the HW screen surface - SDL_FreeSurface(_hwscreen); - - // Release toolbars - free(_toolbarLow->pixels); - SDL_FreeSurface(_toolbarLow); - if (_toolbarHigh) { - free(_toolbarHigh->pixels); - SDL_FreeSurface(_toolbarHigh); - } - - // Setup the new GFX mode - if (!loadGFXMode()) { - unloadGFXMode(); - - _screen = old_screen; - _overlayscreen = old_overlayscreen; - - return false; - } - - // reset palette - SDL_SetColors(_screen, _currentPalette, 0, 256); - - // Restore old screen content - SDL_BlitSurface(old_screen, NULL, _screen, NULL); - SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL); - if (_overlayVisible) { - SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL); - SDL_BlitSurface(old_tmpscreen2, NULL, _tmpscreen2, NULL); - } - - // Free the old surfaces - SDL_FreeSurface(old_screen); - SDL_FreeSurface(old_tmpscreen); - SDL_FreeSurface(old_overlayscreen); - SDL_FreeSurface(old_tmpscreen2); - - // Blit everything back to the screen - _toolbarHighDrawn = false; - internUpdateScreen(); - - // Make sure that a Common::EVENT_SCREEN_CHANGED gets sent later -> FIXME this crashes when no game has been loaded. -// _modeChanged = true; - - return true; -} - -void OSystem_WINCE3::internUpdateScreen() { - SDL_Surface *srcSurf, *origSurf; - static bool old_overlayVisible = false; - int numRectsOut = 0; - int16 routx, routy, routw, routh, stretch, shakestretch; - - assert(_hwscreen != NULL); - - // bail if the application is minimized, be nice to OS - if (!_hasfocus) { - Sleep(20); - return; - } - - // If the shake position changed, fill the dirty area with blackness - if (_currentShakePos != _newShakePos) { - SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _scaleFactorXm / _scaleFactorXd, _newShakePos * _scaleFactorYm / _scaleFactorYd}; - if (_videoMode.aspectRatioCorrection) - blackrect.h = real2Aspect(blackrect.h - 1) + 1; - SDL_FillRect(_hwscreen, &blackrect, 0); - _currentShakePos = _newShakePos; - _forceFull = true; - } - - // Make sure the mouse is drawn, if it should be drawn. - drawMouse(); - - // Check whether the palette was changed in the meantime and update the - // screen surface accordingly. - if (_paletteDirtyEnd != 0) { - SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, _paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart); - _paletteDirtyEnd = 0; - _forceFull = true; - } +void OSystem_WINCE3::initSDL() { + // Check if SDL has not been initialized + if (!_initedSDL) { + uint32 sdlFlags = SDL_INIT_EVENTTHREAD; + if (ConfMan.hasKey("disable_sdl_parachute")) + sdlFlags |= SDL_INIT_NOPARACHUTE; - if (!_overlayVisible) { - origSurf = _screen; - srcSurf = _tmpscreen; - } else { - origSurf = _overlayscreen; - srcSurf = _tmpscreen2; - } - - if (old_overlayVisible != _overlayVisible) { - old_overlayVisible = _overlayVisible; - update_scalers(); - } - - // Force a full redraw if requested - if (_forceFull) { - _numDirtyRects = 1; - - _dirtyRectList[0].x = 0; - if (!_zoomDown) - _dirtyRectList[0].y = 0; - else - _dirtyRectList[0].y = _videoMode.screenHeight / 2; - _dirtyRectList[0].w = _videoMode.screenWidth; - if (!_zoomUp && !_zoomDown) - _dirtyRectList[0].h = _videoMode.screenHeight; - else - _dirtyRectList[0].h = _videoMode.screenHeight / 2; - - _toolbarHandler.forceRedraw(); - } - - // Only draw anything if necessary - if (_numDirtyRects > 0) { - - SDL_Rect *r, *rout; - SDL_Rect dst; - uint32 srcPitch, dstPitch; - SDL_Rect *last_rect = _dirtyRectList + _numDirtyRects; - bool toolbarVisible = _toolbarHandler.visible(); - int toolbarOffset = _toolbarHandler.getOffset(); - - for (r = _dirtyRectList; r != last_rect; ++r) { - dst = *r; - dst.x++; // Shift rect by one since 2xSai needs to access the data around - dst.y++; // any pixel to scale it, and we want to avoid mem access crashes. - // NOTE: This is also known as BLACK MAGIC, copied from the sdl backend - if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0) - error("SDL_BlitSurface failed: %s", SDL_GetError()); + if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) { + SDL_VideoInit("windib", 0); + sdlFlags ^= SDL_INIT_VIDEO; } - SDL_LockSurface(srcSurf); - SDL_LockSurface(_hwscreen); - - srcPitch = srcSurf->pitch; - dstPitch = _hwscreen->pitch; - - for (r = _dirtyRectList, rout = _dirtyRectOut; r != last_rect; ++r) { - - // always clamp to enclosing, downsampled-grid-aligned rect in the downscaled image - if (_scaleFactorXd != 1) { - stretch = r->x % _scaleFactorXd; - r->x -= stretch; - r->w += stretch; - r->w = (r->x + r->w + _scaleFactorXd - 1) / _scaleFactorXd * _scaleFactorXd - r->x; - } - if (_scaleFactorYd != 1) { - stretch = r->y % _scaleFactorYd; - r->y -= stretch; - r->h += stretch; - r->h = (r->y + r->h + _scaleFactorYd - 1) / _scaleFactorYd * _scaleFactorYd - r->y; - } - - // transform - shakestretch = _currentShakePos * _scaleFactorYm / _scaleFactorYd; - routx = r->x * _scaleFactorXm / _scaleFactorXd; // locate position in scaled screen - routy = r->y * _scaleFactorYm / _scaleFactorYd + shakestretch; // adjust for shake offset - routw = r->w * _scaleFactorXm / _scaleFactorXd; - routh = r->h * _scaleFactorYm / _scaleFactorYd - shakestretch; - - // clipping destination rectangle inside device screen (more strict, also more tricky but more stable) - // note that all current scalers do not make dst rect exceed left/right, unless chosen badly (FIXME) - if (_zoomDown) routy -= 240; // adjust for zoom position - if (routy + routh < 0) continue; - if (routy < 0) { - routh += routy; - r->y -= routy * _scaleFactorYd / _scaleFactorYm; - routy = 0; - r->h = routh * _scaleFactorYd / _scaleFactorYm; - } - if (_orientationLandscape) { - if (routy > _platformScreenWidth) continue; - if (routy + routh > _platformScreenWidth) { - routh = _platformScreenWidth - routy; - r->h = routh * _scaleFactorYd / _scaleFactorYm; - } - } else { - if (routy > _platformScreenHeight) continue; - if (routy + routh > _platformScreenHeight) { - routh = _platformScreenHeight - routy; - r->h = routh * _scaleFactorYd / _scaleFactorYm; - } - } - - // check if the toolbar is overwritten - if (toolbarVisible && r->y + r->h >= toolbarOffset) - _toolbarHandler.forceRedraw(); + // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers) + if (SDL_Init(sdlFlags) == -1) + error("Could not initialize SDL: %s", SDL_GetError()); - // blit it (with added voodoo from the sdl backend, shifting the source rect again) - _scalerProc( (byte *)srcSurf->pixels + (r->x * 2 + 2)+ (r->y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + routx * 2 + routy * dstPitch, dstPitch, - r->w, r->h - _currentShakePos); + // Enable unicode support if possible + SDL_EnableUNICODE(1); - // add this rect to output - rout->x = routx; rout->y = routy - shakestretch; - rout->w = routw; rout->h = routh + shakestretch; - numRectsOut++; - rout++; - - } - SDL_UnlockSurface(srcSurf); - SDL_UnlockSurface(_hwscreen); - } - // Add the toolbar if needed - SDL_Rect toolbar_rect[1]; - if (_panelVisible && _toolbarHandler.draw(_toolbarLow, &toolbar_rect[0])) { - // It can be drawn, scale it - uint32 srcPitch, dstPitch; - SDL_Surface *toolbarSurface; - ScalerProc *toolbarScaler; - - if (_videoMode.screenHeight > 240) { - if (!_toolbarHighDrawn) { - // Resize the toolbar - SDL_LockSurface(_toolbarLow); - SDL_LockSurface(_toolbarHigh); - Normal2x((byte*)_toolbarLow->pixels, _toolbarLow->pitch, (byte*)_toolbarHigh->pixels, _toolbarHigh->pitch, toolbar_rect[0].w, toolbar_rect[0].h); - SDL_UnlockSurface(_toolbarHigh); - SDL_UnlockSurface(_toolbarLow); - _toolbarHighDrawn = true; - } - toolbar_rect[0].w *= 2; - toolbar_rect[0].h *= 2; - toolbarSurface = _toolbarHigh; - } - else - toolbarSurface = _toolbarLow; - - drawToolbarMouse(toolbarSurface, true); // draw toolbar mouse if applicable - - // Apply the appropriate scaler - SDL_LockSurface(toolbarSurface); - SDL_LockSurface(_hwscreen); - srcPitch = toolbarSurface->pitch; - dstPitch = _hwscreen->pitch; - - toolbarScaler = _scalerProc; - if (_videoMode.scaleFactor == 2) - toolbarScaler = Normal2x; - else if (_videoMode.scaleFactor == 3) - toolbarScaler = Normal3x; - toolbarScaler((byte *)toolbarSurface->pixels, srcPitch, - (byte *)_hwscreen->pixels + (_toolbarHandler.getOffset() * _scaleFactorYm / _scaleFactorYd * dstPitch), - dstPitch, toolbar_rect[0].w, toolbar_rect[0].h); - SDL_UnlockSurface(toolbarSurface); - SDL_UnlockSurface(_hwscreen); - - // And blit it - toolbar_rect[0].y = _toolbarHandler.getOffset(); - toolbar_rect[0].x = toolbar_rect[0].x * _scaleFactorXm / _scaleFactorXd; - toolbar_rect[0].y = toolbar_rect[0].y * _scaleFactorYm / _scaleFactorYd; - toolbar_rect[0].w = toolbar_rect[0].w * _scaleFactorXm / _scaleFactorXd; - toolbar_rect[0].h = toolbar_rect[0].h * _scaleFactorYm / _scaleFactorYd; - - SDL_UpdateRects(_hwscreen, 1, toolbar_rect); - - drawToolbarMouse(toolbarSurface, false); // undraw toolbar mouse - } - - // Finally, blit all our changes to the screen - if (numRectsOut > 0) - SDL_UpdateRects(_hwscreen, numRectsOut, _dirtyRectOut); - - _numDirtyRects = 0; - _forceFull = false; -} - -Graphics::Surface *OSystem_WINCE3::lockScreen() { - // Make sure mouse pointer is not painted over the playfield at the time of locking - undrawMouse(); - return OSystem_SDL::lockScreen(); -} - -void OSystem_WINCE3::unlockScreen() { - OSystem_SDL::unlockScreen(); -} - -bool OSystem_WINCE3::saveScreenshot(const char *filename) { - assert(_hwscreen != NULL); - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - SDL_SaveBMP(_hwscreen, filename); - return true; -} - -void OSystem_WINCE3::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { - assert (_transactionMode == kTransactionNone); - - if (_overlayscreen == NULL) - return; - - // Clip the coordinates - if (x < 0) { - w += x; - buf -= x; - x = 0; - } - - if (y < 0) { - h += y; buf -= y * pitch; - y = 0; + _initedSDL = true; } - - if (w > _videoMode.overlayWidth - x) { - w = _videoMode.overlayWidth - x; - } - - if (h > _videoMode.overlayHeight - y) { - h = _videoMode.overlayHeight - y; - } - - if (w <= 0 || h <= 0) - return; - - // Mark the modified region as dirty - addDirtyRect(x, y, w, h); - - undrawMouse(); - - if (SDL_LockSurface(_overlayscreen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2; - do { - memcpy(dst, buf, w * 2); - dst += _overlayscreen->pitch; - buf += pitch; - } while (--h); - - SDL_UnlockSurface(_overlayscreen); -} - -void OSystem_WINCE3::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) { - assert (_transactionMode == kTransactionNone); - assert(src); - - if (_screen == NULL) - return; - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - - /* Clip the coordinates */ - if (x < 0) { - w += x; - src -= x; - x = 0; - } - - if (y < 0) { - h += y; - src -= y * pitch; - y = 0; - } - - if (w > _videoMode.screenWidth - x) { - w = _videoMode.screenWidth - x; - } - - if (h > _videoMode.screenHeight - y) { - h = _videoMode.screenHeight - y; - } - - if (w <= 0 || h <= 0) - return; - - addDirtyRect(x, y, w, h); - - undrawMouse(); - - // Try to lock the screen surface - if (SDL_LockSurface(_screen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x; - - if (_videoMode.screenWidth == pitch && pitch == w) { - memcpy(dst, src, h*w); - } else { - do { - memcpy(dst, src, w); - src += pitch; - dst += _videoMode.screenWidth; - } while (--h); - } - - // Unlock the screen surface - SDL_UnlockSurface(_screen); -} - -void OSystem_WINCE3::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { - - undrawMouse(); - if (w == 0 || h == 0) - return; - - _mouseCurState.w = w; - _mouseCurState.h = h; - - _mouseHotspotX = hotspot_x; - _mouseHotspotY = hotspot_y; - - _mouseKeyColor = keycolor; - - free(_mouseData); - - _mouseData = (byte *) malloc(w * h); - memcpy(_mouseData, buf, w * h); - - if (w > _mouseBackupDim || h > _mouseBackupDim) { - // mouse has been undrawn, adjust sprite backup area - free(_mouseBackupOld); - free(_mouseBackupToolbar); - uint16 tmp = (w > h) ? w : h; - _mouseBackupOld = (byte *) malloc(tmp * tmp * 2); // can hold 8bpp (playfield) or 16bpp (overlay) data - _mouseBackupToolbar = (uint16 *) malloc(tmp * tmp * 2); // 16 bpp - _mouseBackupDim = tmp; - } -} - -void OSystem_WINCE3::setMousePos(int x, int y) { - if (x != _mouseCurState.x || y != _mouseCurState.y) { - undrawMouse(); - _mouseCurState.x = x; - _mouseCurState.y = y; - updateScreen(); - } -} - - -void OSystem_WINCE3::internDrawMouse() { - if (!_mouseNeedsRedraw || !_mouseVisible || !_mouseData) - return; - - int x = _mouseCurState.x - _mouseHotspotX; - int y = _mouseCurState.y - _mouseHotspotY; - int w = _mouseCurState.w; - int h = _mouseCurState.h; - byte color; - const byte *src = _mouseData; // Image representing the mouse - int width; - - // clip the mouse rect, and adjust the src pointer accordingly - if (x < 0) { - w += x; - src -= x; - x = 0; - } - if (y < 0) { - h += y; - src -= y * _mouseCurState.w; - y = 0; - } - - if (w > _videoMode.screenWidth - x) - w = _videoMode.screenWidth - x; - if (h > _videoMode.screenHeight - y) - h = _videoMode.screenHeight - y; - - // Quick check to see if anything has to be drawn at all - if (w <= 0 || h <= 0) - return; - - // Draw the mouse cursor; backup the covered area in "bak" - if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - // Mark as dirty - addDirtyRect(x, y, w, h); - - if (!_overlayVisible) { - byte *bak = _mouseBackupOld; // Surface used to backup the area obscured by the mouse - byte *dst; // Surface we are drawing into - - dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x; - while (h > 0) { - width = w; - while (width > 0) { - *bak++ = *dst; - color = *src++; - if (color != _mouseKeyColor) // transparent, don't draw - *dst = color; - dst++; - width--; - } - src += _mouseCurState.w - w; - bak += _mouseBackupDim - w; - dst += _videoMode.screenWidth - w; - h--; - } - - } else { - uint16 *bak = (uint16 *)_mouseBackupOld; // Surface used to backup the area obscured by the mouse - byte *dst; // Surface we are drawing into - - dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2; - while (h > 0) { - width = w; - while (width > 0) { - *bak++ = *(uint16 *)dst; - color = *src++; - if (color != 0xFF) // 0xFF = transparent, don't draw - *(uint16 *)dst = SDL_MapRGB(_overlayscreen->format, _currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b); - dst += 2; - width--; - } - src += _mouseCurState.w - w; - bak += _mouseBackupDim - w; - dst += _overlayscreen->pitch - w * 2; - h--; - } - } - - SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen); - - // Finally, set the flag to indicate the mouse has been drawn - _mouseNeedsRedraw = false; -} - -void OSystem_WINCE3::undrawMouse() { - assert (_transactionMode == kTransactionNone); - - if (_mouseNeedsRedraw) - return; - - int old_mouse_x = _mouseCurState.x - _mouseHotspotX; - int old_mouse_y = _mouseCurState.y - _mouseHotspotY; - int old_mouse_w = _mouseCurState.w; - int old_mouse_h = _mouseCurState.h; - - // clip the mouse rect, and adjust the src pointer accordingly - if (old_mouse_x < 0) { - old_mouse_w += old_mouse_x; - old_mouse_x = 0; - } - if (old_mouse_y < 0) { - old_mouse_h += old_mouse_y; - old_mouse_y = 0; - } - - if (old_mouse_w > _videoMode.screenWidth - old_mouse_x) - old_mouse_w = _videoMode.screenWidth - old_mouse_x; - if (old_mouse_h > _videoMode.screenHeight - old_mouse_y) - old_mouse_h = _videoMode.screenHeight - old_mouse_y; - - // Quick check to see if anything has to be drawn at all - if (old_mouse_w <= 0 || old_mouse_h <= 0) - return; - - - if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - int y; - if (!_overlayVisible) { - byte *dst, *bak = _mouseBackupOld; - - // No need to do clipping here, since drawMouse() did that already - dst = (byte *)_screen->pixels + old_mouse_y * _videoMode.screenWidth + old_mouse_x; - for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _videoMode.screenWidth) - memcpy(dst, bak, old_mouse_w); - } else { - byte *dst; - uint16 *bak = (uint16 *)_mouseBackupOld; - - // No need to do clipping here, since drawMouse() did that already - dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2; - for (y = 0; y < old_mouse_h; ++y, bak += _mouseBackupDim, dst += _overlayscreen->pitch) - memcpy(dst, bak, old_mouse_w << 1); - } - - addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h); - - SDL_UnlockSurface(_overlayVisible ? _overlayscreen : _screen); - - _mouseNeedsRedraw = true; -} - -bool OSystem_WINCE3::showMouse(bool visible) { - if (_mouseVisible == visible) - return visible; - - if (visible == false) - undrawMouse(); - - bool last = _mouseVisible; - _mouseVisible = visible; - _mouseNeedsRedraw = true; - - return last; -} - -void OSystem_WINCE3::drawToolbarMouse(SDL_Surface *surf, bool draw) { - - if (!_mouseData || !_usesEmulatedMouse) - return; - - int x = _mouseCurState.x - _mouseHotspotX; - int y = _mouseCurState.y - _mouseHotspotY - _toolbarHandler.getOffset(); - int w = _mouseCurState.w; - int h = _mouseCurState.h; - byte color; - const byte *src = _mouseData; - int width; - - // clip - if (x < 0) { - w += x; - src -= x; - x = 0; - } - if (y < 0) { - h += y; - src -= y * _mouseCurState.w; - y = 0; - } - if (w > surf->w - x) - w = surf->w - x; - if (h > surf->h - y) - h = surf->h - y; - if (w <= 0 || h <= 0) - return; - - if (SDL_LockSurface(surf) == -1) - error("SDL_LockSurface failed at internDrawToolbarMouse: %s", SDL_GetError()); - - uint16 *bak = _mouseBackupToolbar; // toolbar surfaces are 16bpp - uint16 *dst; - dst = (uint16 *)surf->pixels + y * surf->w + x; - - if (draw) { // blit it - while (h > 0) { - width = w; - while (width > 0) { - *bak++ = *dst; - color = *src++; - if (color != _mouseKeyColor) // transparent color - *dst = 0xFFFF; - dst++; - width--; - } - src += _mouseCurState.w - w; - bak += _mouseBackupDim - w; - dst += surf->w - w; - h--; - } - } else { // restore bg - for (y = 0; y < h; ++y, bak += _mouseBackupDim, dst += surf->w) - memcpy(dst, bak, w << 1); - } - - SDL_UnlockSurface(surf); -} - -void OSystem_WINCE3::blitCursor() { -} - -void OSystem_WINCE3::showOverlay() { - assert (_transactionMode == kTransactionNone); - - if (_overlayVisible) - return; - - undrawMouse(); - _overlayVisible = true; - update_scalers(); - clearOverlay(); -} - -void OSystem_WINCE3::hideOverlay() { - assert (_transactionMode == kTransactionNone); - - if (!_overlayVisible) - return; - - undrawMouse(); - _overlayVisible = false; - clearOverlay(); - _forceFull = true; -} - -void OSystem_WINCE3::drawMouse() { - if (!(_toolbarHandler.visible() && _mouseCurState.y >= _toolbarHandler.getOffset() && !_usesEmulatedMouse) && !_forceHideMouse) - internDrawMouse(); -} - -void OSystem_WINCE3::fillMouseEvent(Common::Event &event, int x, int y) { - event.mouse.x = x; - event.mouse.y = y; - - // Update the "keyboard mouse" coords - _km.x = event.mouse.x; - _km.y = event.mouse.y; - - // Adjust for the screen scaling - if (_zoomDown) - event.mouse.y += 240; - - event.mouse.x = event.mouse.x * _scaleFactorXd / _scaleFactorXm; - event.mouse.y = event.mouse.y * _scaleFactorYd / _scaleFactorYm; -} - -void OSystem_WINCE3::retrieve_mouse_location(int &x, int &y) { - x = _mouseCurState.x; - y = _mouseCurState.y; - - x = x * _scaleFactorXm / _scaleFactorXd; - y = y * _scaleFactorYm / _scaleFactorYd; - - if (_zoomDown) - y -= 240; -} - -void OSystem_WINCE3::warpMouse(int x, int y) { - if (_mouseCurState.x != x || _mouseCurState.y != y) { - SDL_WarpMouse(x * _scaleFactorXm / _scaleFactorXd, y * _scaleFactorYm / _scaleFactorYd); - - // SDL_WarpMouse() generates a mouse movement event, so - // set_mouse_pos() would be called eventually. However, the - // cannon script in CoMI calls this function twice each time - // the cannon is reloaded. Unless we update the mouse position - // immediately the second call is ignored, causing the cannon - // to change its aim. - - setMousePos(x, y); - } -} - -void OSystem_WINCE3::addDirtyRect(int x, int y, int w, int h, bool mouseRect) { - - if (_forceFull || _paletteDirtyEnd) - return; - - OSystem_SDL::addDirtyRect(x, y, w, h, false); -} - -static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) { - if (GUI::Actions::Instance()->mappingActive()) - return key; - - if (unfilter) { - switch (key) { - case SDLK_ESCAPE: - return SDLK_BACKSPACE; - case SDLK_F8: - return SDLK_ASTERISK; - case SDLK_F9: - return SDLK_HASH; - default: - return key; - } - } - - if (key >= SDLK_KP0 && key <= SDLK_KP9) { - return key - SDLK_KP0 + '0'; - } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { - return key; - } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { - return 0; - } - return key; -} - -bool OSystem_WINCE3::pollEvent(Common::Event &event) { - SDL_Event ev; - ev.type = SDL_NOEVENT; - DWORD currentTime; - bool keyEvent = false; - int deltaX, deltaY; - - memset(&event, 0, sizeof(Common::Event)); - - handleKbdMouse(); - - // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED - if (_modeChanged) { - _modeChanged = false; - event.type = Common::EVENT_SCREEN_CHANGED; - _screenChangeCount++; - return true; - } - - CEDevice::wakeUp(); - - currentTime = GetTickCount(); - - while (SDL_PollEvent(&ev)) { - switch (ev.type) { - case SDL_KEYDOWN: - debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym)); - // KMOD_RESERVED is used if the key has been injected by an external buffer - if (ev.key.keysym.mod != KMOD_RESERVED && !_unfilteredkeys) { - keyEvent = true; - _lastKeyPressed = ev.key.keysym.sym; - _keyRepeatTime = currentTime; - _keyRepeat = 0; - - if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true)) - return true; - } - - if (GUI_Actions::Instance()->mappingActive()) - event.kbd.flags = 0xFF; - else if (ev.key.keysym.sym == SDLK_PAUSE) { - _lastKeyPressed = 0; - event.type = Common::EVENT_PREDICTIVE_DIALOG; - return true; - } event.type = Common::EVENT_KEYDOWN; - if (!_unfilteredkeys) - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - else - event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); - event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); - - if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { - event.kbd.ascii ^= 0x20; - event.kbd.flags = Common::KBD_SHIFT; - } - - return true; - - case SDL_KEYUP: - debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym)); - // KMOD_RESERVED is used if the key has been injected by an external buffer - if (ev.key.keysym.mod != KMOD_RESERVED && !_unfilteredkeys) { - keyEvent = true; - _lastKeyPressed = 0; - - if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false)) - return true; - } - - if (GUI_Actions::Instance()->mappingActive()) - event.kbd.flags = 0xFF; - else if (ev.key.keysym.sym == SDLK_PAUSE) { - _lastKeyPressed = 0; - return false; // chew up the show agi dialog key up event - } - - event.type = Common::EVENT_KEYUP; - if (!_unfilteredkeys) - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - else - event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); - event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); - - if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { - event.kbd.ascii ^= 0x20; - event.kbd.flags = Common::KBD_SHIFT; - } - - return true; - - case SDL_MOUSEMOTION: - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, ev.motion.x, ev.motion.y); - setMousePos(event.mouse.x, event.mouse.y); - return true; - - case SDL_MOUSEBUTTONDOWN: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONDOWN; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONDOWN; - else - break; - fillMouseEvent(event, ev.button.x, ev.button.y); - - - if (event.mouse.x > _tapX) - deltaX = event.mouse.x - _tapX; - else - deltaX = _tapX - event.mouse.x; - if (event.mouse.y > _tapY) - deltaY = event.mouse.y - _tapY; - else - deltaY = _tapY - event.mouse.y; - _closeClick = (deltaX <= 5 && deltaY <= 5); - - if (!_isSmartphone) { - // handle double-taps - if (_tapTime) { // second tap - if (_closeClick && (GetTickCount() - _tapTime < 1000)) { - if (event.mouse.y <= 20 && _panelInitialized) { // top of screen (show panel) - swap_panel_visibility(); - } else if (!_noDoubleTapRMB) { // right click - event.type = Common::EVENT_RBUTTONDOWN; - _rbutton = true; - } - } - _tapTime = 0; - } else { - _tapTime = GetTickCount(); - _tapX = event.mouse.x; - _tapY = event.mouse.y; - } - } - - if (_freeLook && !_closeClick) { - _rbutton = false; - _tapTime = 0; - _tapX = event.mouse.x; - _tapY = event.mouse.y; - event.type = Common::EVENT_MOUSEMOVE; - setMousePos(event.mouse.x, event.mouse.y); - } - - - if (_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) { - if (!_toolbarHandler.drawn()) { - _toolbarHighDrawn = false; - internUpdateScreen(); - } - if (_newOrientation != _orientationLandscape){ - _orientationLandscape = _newOrientation; - _toolbarHighDrawn = false; - ConfMan.setInt("landscape", _orientationLandscape); - ConfMan.flushToDisk(); - hotswapGFXMode(); - } - return false; - } - - return true; - - case SDL_MOUSEBUTTONUP: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONUP; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONUP; - else - break; - - if (_rbutton) { - event.type = Common::EVENT_RBUTTONUP; - _rbutton = false; - } - - fillMouseEvent(event, ev.button.x, ev.button.y); - - if (_freeLook && !_closeClick) { - _tapX = event.mouse.x; - _tapY = event.mouse.y; - event.type = Common::EVENT_MOUSEMOVE; - setMousePos(event.mouse.x, event.mouse.y); - } - - if (_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) { - if (!_toolbarHandler.drawn()) { - _toolbarHighDrawn = false; - internUpdateScreen(); - } - return false; - - } - return true; - - case SDL_VIDEOEXPOSE: - _forceFull = true; - break; - - case SDL_QUIT: - event.type = Common::EVENT_QUIT; - return true; - - case SDL_ACTIVEEVENT: - if (ev.active.state & SDL_APPMOUSEFOCUS) - debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost"); - if (ev.active.state & SDL_APPINPUTFOCUS) - debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost"); - if (ev.active.state & SDL_APPACTIVE) - debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost"); - if (ev.active.state & SDL_APPINPUTFOCUS) { - _hasfocus = ev.active.gain; - SDL_PauseAudio(!_hasfocus); - _forceFull |= _hasfocus; - } - break; - } - } - - // Simulate repeated key for backend - if (!keyEvent && _lastKeyPressed && currentTime > _keyRepeatTime + _keyRepeatTrigger) { - _keyRepeatTime = currentTime; - _keyRepeat++; - GUI_Actions::Instance()->performMapped(_lastKeyPressed, true); - } - - return false; } void OSystem_WINCE3::quit() { @@ -2497,19 +570,14 @@ void OSystem_WINCE3::getTimeAndDate(TimeDate &t) const { SYSTEMTIME systime; GetLocalTime(&systime); - t.tm_year = systime.wYear - 1900; - t.tm_mon = systime.wMonth - 1; - t.tm_mday = systime.wDay; - t.tm_hour = systime.wHour; - t.tm_min = systime.wMinute; - t.tm_sec = systime.wSecond; + t.tm_year = systime.wYear - 1900; + t.tm_mon = systime.wMonth - 1; + t.tm_mday = systime.wDay; + t.tm_hour = systime.wHour; + t.tm_min = systime.wMinute; + t.tm_sec = systime.wSecond; } int OSystem_WINCE3::_platformScreenWidth; int OSystem_WINCE3::_platformScreenHeight; bool OSystem_WINCE3::_isOzone; -OSystem_WINCE3::zoneDesc OSystem_WINCE3::_zones[TOTAL_ZONES] = { - { 0, 0, 320, 145 }, - { 0, 145, 150, 55 }, - { 150, 145, 170, 55 } -}; diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h index 6cc6e538e1..d7ede8ca81 100644 --- a/backends/platform/wince/wince-sdl.h +++ b/backends/platform/wince/wince-sdl.h @@ -35,7 +35,10 @@ #include "backends/platform/wince/CEkeys/CEKeys.h" #include "backends/platform/wince/CEDevice.h" -#define TOTAL_ZONES 3 +#include "backends/graphics/wincesdl/wincesdl-graphics.h" +#include "backends/events/wincesdl/wincesdl-events.h" +#include "backends/timer/default/default-timer.h" +#include "backends/fs/windows/windows-fs-factory.h" // defines used for implementing the raw frame buffer access method (2003+) #define GETRAWFRAMEBUFFER 0x00020001 @@ -46,202 +49,45 @@ class OSystem_WINCE3 : public OSystem_SDL { public: OSystem_WINCE3(); - - // Update the dirty areas of the screen - void internUpdateScreen(); + virtual ~OSystem_WINCE3(); void setGraphicsModeIntern(); - void initSize(uint w, uint h, const Graphics::PixelFormat *format); void initBackend(); - // Overloaded from SDL backend (toolbar handling) - bool pollEvent(Common::Event &event); - // Overloaded from SDL backend (toolbar handling) - void drawMouse(); - // Overloaded from SDL backend (mouse and new scaler handling) - void fillMouseEvent(Common::Event &event, int x, int y); - // Overloaded from SDL backend (new scaler handling) - void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false); - // Overloaded from SDL backend (new scaler handling) - void warpMouse(int x, int y); // Overloaded from SDL backend void quit(); - // Overloaded from SDL backend (master volume and sample rate subtleties) - void setupMixer(); // Overloaded from OSystem void engineInit(); void getTimeAndDate(TimeDate &t) const; virtual Common::String getDefaultConfigFileName(); + virtual FilesystemFactory *getFilesystemFactory(); - - // Overloaded from SDL_Common (FIXME) - void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend - void undrawMouse(); - void blitCursor(); - bool showMouse(bool visible); - void setMousePos(int x, int y); - void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME) - void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); - void showOverlay(); - void hideOverlay(); - Graphics::Surface *lockScreen(); - void unlockScreen(); - - // GUI and action stuff - void swap_panel_visibility(); - void swap_panel(); void swap_sound_master(); - void add_right_click(bool pushed); - void swap_mouse_visibility(); - void swap_freeLook(); - void swap_zoom_up(); - void swap_zoom_down(); - void swap_smartphone_keyboard(); - -//#ifdef WIN32_PLATFORM_WFSP - // Smartphone actions - - void initZones(); - void loadDeviceConfigurationElement(String element, int &value, int defaultValue); - void loadDeviceConfiguration(); - void add_left_click(bool pushed); - void move_cursor_up(); - void move_cursor_down(); - void move_cursor_left(); - void move_cursor_right(); - void switch_zone(); - void smartphone_rotate_display(); -//#endif static int getScreenWidth(); static int getScreenHeight(); static void initScreenInfos(); static bool isOzone(); -protected: - bool loadGFXMode(); - void unloadGFXMode(); - bool hotswapGFXMode(); - bool saveScreenshot(const char *filename); - + static bool _soundMaster; // turn off sound after all calculations + // static since needed by the SDL callback - const GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(int mode); - //int getGraphicsMode() const; - int getDefaultGraphicsMode() const; - - bool hasFeature(Feature f); - void setFeatureState(Feature f, bool enable); - bool getFeatureState(Feature f); - - void internDrawMouse(); - void drawToolbarMouse(SDL_Surface *surf, bool draw); +protected: + void initSDL(); + Audio::MixerImpl *_mixer; + DefaultTimerManager *_timer; + FilesystemFactory *_fsFactory; private: - -#ifdef USE_VORBIS - bool checkOggHighSampleRate(); -#endif - - static void private_sound_proc(void *param, byte *buf, int len); - - bool update_scalers(); - void create_toolbar(); - void update_game_settings(); void check_mappings(); - uint32 compute_sample_rate(); - - void retrieve_mouse_location(int &x, int &y); - - CEGUI::ToolbarHandler _toolbarHandler; - SDL_Surface *_toolbarLow; // toolbar 320x40 - SDL_Surface *_toolbarHigh; // toolbar 640x80 - bool _toolbarHighDrawn; // cache toolbar 640x80 - - bool _freeLook; // freeLook mode (do not send mouse button events) - - bool _forceHideMouse; // force invisible mouse cursor - - bool _forcePanelInvisible; // force panel visibility for some cases - bool _panelVisible; // panel visibility - bool _panelStateForced; // panel visibility forced by external call - - bool _panelInitialized; // only initialize the toolbar once - - bool _unfilteredkeys; // discard key mapping temporarily (agi pred. dialog) - static bool _soundMaster; // turn off sound after all calculations - // static since needed by the SDL callback - int _orientationLandscape; // current orientation - int _newOrientation; // new orientation - - bool _saveToolbarState; // save visibility when forced - String _saveActiveToolbar; // save active toolbar when forced - - bool _saveToolbarZoom; // save visibility when zooming - bool _zoomUp; // zooming up mode - bool _zoomDown; // zooming down mode - - bool _noDoubleTapRMB; // disable double tap -> rmb click - bool _rbutton; // double tap -> right button simulation - bool _closeClick; // flag when taps are spatially close together - - bool _usesEmulatedMouse; // emulated mousemove ever been used in this session - - bool _canBeAspectScaled; // game screen size allows for aspect scaling - - int _scaleFactorXm; // scaler X * - int _scaleFactorXd; // scaler X / - int _scaleFactorYm; // scaler Y * - int _scaleFactorYd; // scaler Y / - SDL_Rect _dirtyRectOut[NUM_DIRTY_RECT]; - bool _scalersChanged; - bool _hasfocus; // scummvm has the top window + bool _forcePanelInvisible; // force panel visibility for some cases static int _platformScreenWidth; static int _platformScreenHeight; - static bool _isOzone; // true if running on Windows 2003 SE - - // Keyboard tap - int _tapX; - int _tapY; - long _tapTime; - - // Mouse - int _mouseHotspotX, _mouseHotspotY; - byte *_mouseBackupOld; - uint16 *_mouseBackupToolbar; - uint16 _mouseBackupDim; - - // Smartphone specific variables - - int _lastKeyPressed; // last key pressed - int _keyRepeat; // number of time the last key was repeated - int _keyRepeatTime; // elapsed time since the key was pressed - int _keyRepeatTrigger; // minimum time to consider the key was repeated - - int _repeatX; // repeat trigger for left and right cursor moves - int _repeatY; // repeat trigger for up and down cursor moves - int _stepX1; // offset for left and right cursor moves (slowest) - int _stepX2; // offset for left and right cursor moves (faster) - int _stepX3; // offset for left and right cursor moves (fastest) - int _stepY1; // offset for up and down cursor moves (slowest) - int _stepY2; // offset for up and down cursor moves (faster) - int _stepY3; // offset for up and down cursor moves (fastest) - - int _mouseXZone[TOTAL_ZONES]; - int _mouseYZone[TOTAL_ZONES]; - int _currentZone; - - struct zoneDesc { - int x; - int y; - int width; - int height; - }; - - static zoneDesc _zones[TOTAL_ZONES]; + static bool _isOzone; // true if running on Windows 2003 SE + }; #endif diff --git a/backends/plugins/dynamic-plugin.h b/backends/plugins/dynamic-plugin.h index 32d411656c..775e887105 100644 --- a/backends/plugins/dynamic-plugin.h +++ b/backends/plugins/dynamic-plugin.h @@ -27,6 +27,7 @@ #define BACKENDS_PLUGINS_DYNAMICPLUGIN_H #include "base/plugins.h" +#include "common/textconsole.h" class DynamicPlugin : public Plugin { diff --git a/backends/plugins/elf/memory-manager.cpp b/backends/plugins/elf/memory-manager.cpp index b2ac497771..d32ac2da28 100644 --- a/backends/plugins/elf/memory-manager.cpp +++ b/backends/plugins/elf/memory-manager.cpp @@ -28,6 +28,7 @@ #if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) #include "backends/plugins/elf/memory-manager.h" +#include "common/debug.h" #include "common/util.h" #include <malloc.h> diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp index 0e16f165b3..75e10cf810 100644 --- a/backends/saves/default/default-saves.cpp +++ b/backends/saves/default/default-saves.cpp @@ -60,7 +60,7 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) { Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) { Common::String savePathName = getSavePath(); checkPath(Common::FSNode(savePathName)); - if (getError() != Common::kNoError) + if (getError().getCode() != Common::kNoError) return Common::StringArray(); // recreate FSNode since checkPath may have changed/created the directory @@ -84,7 +84,7 @@ Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String // Ensure that the savepath is valid. If not, generate an appropriate error. Common::String savePathName = getSavePath(); checkPath(Common::FSNode(savePathName)); - if (getError() != Common::kNoError) + if (getError().getCode() != Common::kNoError) return 0; // recreate FSNode since checkPath may have changed/created the directory @@ -104,7 +104,7 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String // Ensure that the savepath is valid. If not, generate an appropriate error. Common::String savePathName = getSavePath(); checkPath(Common::FSNode(savePathName)); - if (getError() != Common::kNoError) + if (getError().getCode() != Common::kNoError) return 0; // recreate FSNode since checkPath may have changed/created the directory @@ -121,7 +121,7 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) { Common::String savePathName = getSavePath(); checkPath(Common::FSNode(savePathName)); - if (getError() != Common::kNoError) + if (getError().getCode() != Common::kNoError) return false; // recreate FSNode since checkPath may have changed/created the directory diff --git a/backends/saves/posix/posix-saves.cpp b/backends/saves/posix/posix-saves.cpp index 866cd912e5..37db208223 100644 --- a/backends/saves/posix/posix-saves.cpp +++ b/backends/saves/posix/posix-saves.cpp @@ -23,6 +23,10 @@ * */ + +// Enable mkdir +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + #include "common/scummsys.h" #if defined(UNIX) && !defined(DISABLE_DEFAULT_SAVEFILEMANAGER) @@ -31,6 +35,7 @@ #include "common/config-manager.h" #include "common/savefile.h" +#include "common/textconsole.h" #include <stdio.h> #include <string.h> diff --git a/backends/saves/psp/psp-saves.cpp b/backends/saves/psp/psp-saves.cpp index 66c63dfdea..5752d2fa5f 100644 --- a/backends/saves/psp/psp-saves.cpp +++ b/backends/saves/psp/psp-saves.cpp @@ -23,6 +23,20 @@ * */ +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include "common/scummsys.h" #ifdef __PSP__ diff --git a/backends/saves/savefile.cpp b/backends/saves/savefile.cpp index d2fc913f14..9888146049 100644 --- a/backends/saves/savefile.cpp +++ b/backends/saves/savefile.cpp @@ -25,14 +25,11 @@ #include "common/util.h" #include "common/savefile.h" - -#include <stdio.h> -#include <string.h> +#include "common/str.h" namespace Common { -bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) { - +bool SaveFileManager::copySavefile(const String &oldFilename, const String &newFilename) { InSaveFile *inFile = 0; OutSaveFile *outFile = 0; uint32 size = 0; @@ -57,9 +54,8 @@ bool SaveFileManager::renameSavefile(const String &oldFilename, const String &ne if (!error) { outFile->write(buffer, size); outFile->finalize(); - if (!outFile->err()) { - success = removeSavefile(oldFilename); - } + + success = !outFile->err(); } } @@ -71,6 +67,13 @@ bool SaveFileManager::renameSavefile(const String &oldFilename, const String &ne return success; } +bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) { + if (!copySavefile(oldFilename, newFilename)) + return false; + + return removeSavefile(oldFilename); +} + String SaveFileManager::popErrorDesc() { String err = _errorDesc; clearError(); diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp index dd468bbe09..b5060c4c8d 100644 --- a/backends/timer/default/default-timer.cpp +++ b/backends/timer/default/default-timer.cpp @@ -34,7 +34,7 @@ struct TimerSlot { uint32 interval; // in microseconds uint32 nextFireTime; // in milliseconds - uint32 nextFireTimeMicro; // mircoseconds part of nextFire + uint32 nextFireTimeMicro; // microseconds part of nextFire TimerSlot *next; }; diff --git a/backends/timer/default/default-timer.h b/backends/timer/default/default-timer.h index e7ac3d122f..9a353f58c3 100644 --- a/backends/timer/default/default-timer.h +++ b/backends/timer/default/default-timer.h @@ -28,8 +28,6 @@ #include "common/timer.h" #include "common/mutex.h" -class OSystem; - struct TimerSlot; class DefaultTimerManager : public Common::TimerManager { @@ -40,9 +38,9 @@ private: public: DefaultTimerManager(); - ~DefaultTimerManager(); - bool installTimerProc(TimerProc proc, int32 interval, void *refCon); - void removeTimerProc(TimerProc proc); + virtual ~DefaultTimerManager(); + virtual bool installTimerProc(TimerProc proc, int32 interval, void *refCon); + virtual void removeTimerProc(TimerProc proc); /** * Timer callback, to be invoked at regular time intervals by the backend. diff --git a/backends/timer/psp/timer.cpp b/backends/timer/psp/timer.cpp index 746ff97197..9e36b43490 100644 --- a/backends/timer/psp/timer.cpp +++ b/backends/timer/psp/timer.cpp @@ -23,6 +23,20 @@ * */ +// Disable printf override in common/forbidden.h to avoid +// clashes with pspdebug.h from the PSP SDK. +// That header file uses +// __attribute__((format(printf,1,2))); +// which gets messed up by our override mechanism; this could +// be avoided by either changing the PSP SDK to use the equally +// legal and valid +// __attribute__((format(__printf__,1,2))); +// or by refining our printf override to use a varadic macro +// (which then wouldn't be portable, though). +// Anyway, for now we just disable the printf override globally +// for the PSP port +#define FORBIDDEN_SYMBOL_EXCEPTION_printf + #include "common/scummsys.h" #if defined (__PSP__) diff --git a/backends/timer/sdl/sdl-timer.cpp b/backends/timer/sdl/sdl-timer.cpp index 0a4cd428de..647ddba2d3 100644 --- a/backends/timer/sdl/sdl-timer.cpp +++ b/backends/timer/sdl/sdl-timer.cpp @@ -30,6 +30,8 @@ #include "backends/timer/sdl/sdl-timer.h" +#include "common/textconsole.h" + static Uint32 timer_handler(Uint32 interval, void *param) { ((DefaultTimerManager *)param)->handler(); return interval; diff --git a/backends/vkeybd/image-map.cpp b/backends/vkeybd/image-map.cpp index b0a77b5220..f4b4541d7e 100644 --- a/backends/vkeybd/image-map.cpp +++ b/backends/vkeybd/image-map.cpp @@ -27,6 +27,8 @@ #ifdef ENABLE_VKEYBD +#include "common/textconsole.h" + #include "backends/vkeybd/image-map.h" #include "backends/vkeybd/polygon.h" diff --git a/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml b/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml index 86f39d3d4d..85a27c71ca 100644 --- a/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml +++ b/backends/vkeybd/packs/vkeybd_default/vkeybd_default.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> -<keyboard initial_mode="lowercase" v_align="bottom" h_align="centre"> +<keyboard initial_mode="lowercase" v_align="bottom" h_align="center"> <!-- coords key = "start x, start y, end x, end y" --> <!-- Lowercase --> <mode name="lowercase" resolutions="320x240,640x480"> diff --git a/backends/vkeybd/virtual-keyboard-gui.cpp b/backends/vkeybd/virtual-keyboard-gui.cpp index c5ab39e46b..9ffda6e3a7 100644 --- a/backends/vkeybd/virtual-keyboard-gui.cpp +++ b/backends/vkeybd/virtual-keyboard-gui.cpp @@ -36,7 +36,7 @@ namespace Common { static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, OverlayColor transparent) { - if (surf_dst->bytesPerPixel != sizeof(OverlayColor) || surf_src->bytesPerPixel != sizeof(OverlayColor)) + if (surf_dst->format.bytesPerPixel != sizeof(OverlayColor) || surf_src->format.bytesPerPixel != sizeof(OverlayColor)) return; const OverlayColor *src = (const OverlayColor *)surf_src->pixels; @@ -133,7 +133,7 @@ void VirtualKeyboardGUI::setupDisplayArea(Rect& r, OverlayColor forecolor) { _dispI = 0; _dispForeColor = forecolor; _dispBackColor = _dispForeColor + 0xFF; - _dispSurface.create(r.width(), _dispFont->getFontHeight(), sizeof(OverlayColor)); + _dispSurface.create(r.width(), _dispFont->getFontHeight(), _system->getOverlayFormat()); _dispSurface.fillRect(Rect(_dispSurface.w, _dispSurface.h), _dispBackColor); _displayEnabled = true; } @@ -163,7 +163,7 @@ void VirtualKeyboardGUI::run() { _system->showOverlay(); _system->clearOverlay(); } - _overlayBackup.create(_screenW, _screenH, sizeof(OverlayColor)); + _overlayBackup.create(_screenW, _screenH, _system->getOverlayFormat()); _system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w); setupCursor(); @@ -203,7 +203,7 @@ void VirtualKeyboardGUI::moveToDefaultPosition() case VirtualKeyboard::kAlignLeft: x = 0; break; - case VirtualKeyboard::kAlignCentre: + case VirtualKeyboard::kAlignCenter: x = (_screenW - kbdW) / 2; break; case VirtualKeyboard::kAlignRight: @@ -265,7 +265,7 @@ void VirtualKeyboardGUI::screenChanged() { _screenW = newScreenW; _screenH = newScreenH; - _overlayBackup.create(_screenW, _screenH, sizeof(OverlayColor)); + _overlayBackup.create(_screenW, _screenH, _system->getOverlayFormat()); _system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w); if (!_kbd->checkModeResolutions()) { @@ -358,7 +358,7 @@ void VirtualKeyboardGUI::redraw() { if (w <= 0 || h <= 0) return; Graphics::Surface surf; - surf.create(w, h, sizeof(OverlayColor)); + surf.create(w, h, _system->getOverlayFormat()); OverlayColor *dst = (OverlayColor *)surf.pixels; const OverlayColor *src = (OverlayColor *) _overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top); diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp index a81258b25f..3ebdfdc653 100644 --- a/backends/vkeybd/virtual-keyboard-parser.cpp +++ b/backends/vkeybd/virtual-keyboard-parser.cpp @@ -84,7 +84,7 @@ bool VirtualKeyboardParser::parserCallback_keyboard(ParserNode *node) { if (h.equalsIgnoreCase("left")) _keyboard->_hAlignment = VirtualKeyboard::kAlignLeft; else if (h.equalsIgnoreCase("centre") || h.equalsIgnoreCase("center")) - _keyboard->_hAlignment = VirtualKeyboard::kAlignCentre; + _keyboard->_hAlignment = VirtualKeyboard::kAlignCenter; else if (h.equalsIgnoreCase("right")) _keyboard->_hAlignment = VirtualKeyboard::kAlignRight; } diff --git a/backends/vkeybd/virtual-keyboard-parser.h b/backends/vkeybd/virtual-keyboard-parser.h index 9723744dc4..1327008a80 100644 --- a/backends/vkeybd/virtual-keyboard-parser.h +++ b/backends/vkeybd/virtual-keyboard-parser.h @@ -51,7 +51,7 @@ keyboard layouts for different screen resolutions. ** Example keyboard pack description file ** ******************************************** -<keyboard modes="normal,caps" initial_mode="normal" v_align="bottom" h_align="centre"> +<keyboard modes="normal,caps" initial_mode="normal" v_align="bottom" h_align="center"> <mode name="normal" resolutions="640x400,320x200"> <layout resolution="640x400" bitmap="normal_640x400.bmp" transparent_color="255,0,255"> <map> diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp index 31fde8c0fa..e1a25474e7 100644 --- a/backends/vkeybd/virtual-keyboard.cpp +++ b/backends/vkeybd/virtual-keyboard.cpp @@ -33,6 +33,7 @@ #include "backends/vkeybd/virtual-keyboard-parser.h" #include "backends/vkeybd/keycode-descriptions.h" #include "common/config-manager.h" +#include "common/textconsole.h" #include "common/unzip.h" #define KEY_START_CHAR ('[') @@ -71,7 +72,7 @@ void VirtualKeyboard::reset() { deleteEvents(); _modes.clear(); _initialMode = _currentMode = 0; - _hAlignment = kAlignCentre; + _hAlignment = kAlignCenter; _vAlignment = kAlignBottom; _keyQueue.clear(); _loaded = false; @@ -136,7 +137,7 @@ bool VirtualKeyboard::loadKeyboardPack(const String &packName) { _loaded = _parser->parse(); if (_loaded) { - printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str()); + debug("Keyboard pack '%s' loaded successfully", packName.c_str()); } else { warning("Error parsing the keyboard pack '%s'", packName.c_str()); diff --git a/backends/vkeybd/virtual-keyboard.h b/backends/vkeybd/virtual-keyboard.h index db94cbe476..169cd67833 100644 --- a/backends/vkeybd/virtual-keyboard.h +++ b/backends/vkeybd/virtual-keyboard.h @@ -134,7 +134,7 @@ protected: enum HorizontalAlignment { kAlignLeft, - kAlignCentre, + kAlignCenter, kAlignRight }; |