diff options
Diffstat (limited to 'backends')
127 files changed, 5235 insertions, 4078 deletions
diff --git a/backends/audiocd/audiocd.h b/backends/audiocd/audiocd.h index 0afc6af991..76c3998862 100644 --- a/backends/audiocd/audiocd.h +++ b/backends/audiocd/audiocd.h @@ -110,7 +110,7 @@ public: /** * Initialize the specified CD drive for audio playback. * @param drive the drive id - * @return true if the CD drive was inited succesfully + * @return true if the CD drive was inited successfully */ virtual bool openCD(int drive) = 0; diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp index 3e0005dedd..3e95c3e26a 100644 --- a/backends/base-backend.cpp +++ b/backends/base-backend.cpp @@ -57,7 +57,7 @@ void BaseBackend::initBackend() { void BaseBackend::fillScreen(uint32 col) { Graphics::Surface *screen = lockScreen(); - if (screen && screen->pixels) - memset(screen->pixels, col, screen->h * screen->pitch); + if (screen && screen->getPixels()) + memset(screen->getPixels(), col, screen->h * screen->pitch); unlockScreen(); } diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index 38a0c8d46f..30f3b3790c 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -54,6 +54,8 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) : _currentKeyDown.ascii = 0; _currentKeyDown.flags = 0; + _keyRepeatTime = 0; + #ifdef ENABLE_VKEYBD _vk = new Common::VirtualKeyboard(); #endif @@ -84,7 +86,8 @@ void DefaultEventManager::init() { } bool DefaultEventManager::pollEvent(Common::Event &event) { - uint32 time = g_system->getMillis(); + // Skip recording of these events + uint32 time = g_system->getMillis(true); bool result = false; _dispatcher.dispatch(); diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index 0ca5bbb059..e84a8f8c01 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -106,7 +106,9 @@ void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { } void SdlEventSource::handleKbdMouse() { - uint32 curTime = g_system->getMillis(); + // Skip recording of these events + uint32 curTime = g_system->getMillis(true); + if (curTime >= _km.last_time + _km.delay_time) { _km.last_time = curTime; if (_km.x_down_count == 1) { @@ -389,8 +391,17 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { return false; case SDL_VIDEORESIZE: - if (_graphicsManager) + if (_graphicsManager) { _graphicsManager->notifyResize(ev.resize.w, ev.resize.h); + + // If the screen changed, send an Common::EVENT_SCREEN_CHANGED + int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID(); + if (screenID != _lastScreenID) { + _lastScreenID = screenID; + event.type = Common::EVENT_SCREEN_CHANGED; + return true; + } + } return false; case SDL_QUIT: diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h index 54e3958972..2b66a6e6e1 100644 --- a/backends/fs/abstract-fs.h +++ b/backends/fs/abstract-fs.h @@ -100,7 +100,7 @@ public: * @param mode Mode to use while listing the directory. * @param hidden Whether to include hidden files or not in the results. * - * @return true if succesful, false otherwise (e.g. when the directory does not exist). + * @return true if successful, false otherwise (e.g. when the directory does not exist). */ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const = 0; diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp index fe388c2a6e..6d713f10be 100644 --- a/backends/fs/amigaos4/amigaos4-fs.cpp +++ b/backends/fs/amigaos4/amigaos4-fs.cpp @@ -335,7 +335,7 @@ bool AmigaOSFilesystemNode::isReadable() const { // Regular RWED protection flags are low-active or inverted, thus the negation. // moreover pseudo root filesystem (null _pFileLock) is readable whatever the // protection says - bool readable = !(_nProt & EXDF_READ) || _pFileLock == 0; + bool readable = !(_nProt & EXDF_OTR_READ) || _pFileLock == 0; return readable; } @@ -344,7 +344,7 @@ bool AmigaOSFilesystemNode::isWritable() const { // Regular RWED protection flags are low-active or inverted, thus the negation. // moreover pseudo root filesystem (null _pFileLock) is never writable whatever // the protection says (because of the pseudo nature) - bool writable = !(_nProt & EXDF_WRITE) && _pFileLock !=0; + bool writable = !(_nProt & EXDF_OTR_WRITE) && _pFileLock !=0; return writable; } @@ -367,8 +367,14 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const { dosList = IDOS->NextDosEntry(dosList, LDF_VOLUMES); while (dosList) { if (dosList->dol_Type == DLT_VOLUME && - dosList->dol_Name && - dosList->dol_Task) { + dosList->dol_Name) { + + // Original was + // dosList->dol_Name && + // dosList->dol_Task) { + // which errored using SDK 53.24 with a 'struct dosList' has no member called 'dol_Task' + // I removed dol_Task because it's not used anywhere else + // and it neither brought up further errors nor crashes or regressions. // Copy name to buffer IDOS->CopyStringBSTRToC(dosList->dol_Name, buffer, MAXPATHLEN); diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 24397228e6..74258b8910 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -37,6 +37,27 @@ class GraphicsManager : public PaletteManager { public: virtual ~GraphicsManager() {} + /** + * Makes this graphics manager active. That means it should be ready to + * process inputs now. However, even without being active it should be + * able to query the supported modes and other bits. + * + * HACK: Actually this is specific to SdlGraphicsManager subclasses. + * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager + * because there is no relation between these two. + */ + virtual void activateManager() {} + + /** + * Makes this graphics manager inactive. This should allow another + * graphics manager to become active again. + * + * HACK: Actually this is specific to SdlGraphicsManager subclasses. + * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager + * because there is no relation between these two. + */ + virtual void deactivateManager() {} + virtual bool hasFeature(OSystem::Feature f) = 0; virtual void setFeatureState(OSystem::Feature f, bool enable) = 0; virtual bool getFeatureState(OSystem::Feature f) = 0; diff --git a/backends/graphics/opengl/debug.cpp b/backends/graphics/opengl/debug.cpp new file mode 100644 index 0000000000..69006bb975 --- /dev/null +++ b/backends/graphics/opengl/debug.cpp @@ -0,0 +1,65 @@ +/* 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. + * + */ + +#include "backends/graphics/opengl/debug.h" +#include "backends/graphics/opengl/opengl-sys.h" + +#include "common/str.h" +#include "common/textconsole.h" + +#ifdef OPENGL_DEBUG + +namespace OpenGL { + +namespace { +Common::String getGLErrStr(GLenum error) { + switch (error) { + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + } + + return Common::String::format("(Unknown GL error code 0x%X)", error); +} +} // End of anonymous namespace + +void checkGLError(const char *expr, const char *file, int line) { + GLenum error = glGetError(); + + if (error != GL_NO_ERROR) { + // We cannot use error here because we do not know whether we have a + // working screen or not. + warning("GL ERROR: %s on %s (%s:%d)", getGLErrStr(error).c_str(), expr, file, line); + } +} +} // End of namespace OpenGL + +#endif diff --git a/backends/platform/bada/application.h b/backends/graphics/opengl/debug.h index 2b0d37f1ef..ff6b678870 100644 --- a/backends/platform/bada/application.h +++ b/backends/graphics/opengl/debug.h @@ -11,7 +11,7 @@ * * 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 + * 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 @@ -20,35 +20,20 @@ * */ -#ifndef BADA_APPLICATION_H -#define BADA_APPLICATION_H +#ifndef BACKENDS_GRAPHICS_OPENGL_DEBUG_H +#define BACKENDS_GRAPHICS_OPENGL_DEBUG_H -#include <FBase.h> -#include <FApp.h> -#include <FGraphics.h> -#include <FUi.h> -#include <FSystem.h> +#define OPENGL_DEBUG -#include "backends/platform/bada/system.h" +#ifdef OPENGL_DEBUG -class BadaScummVM : public Osp::App::Application { -public: - BadaScummVM(); - ~BadaScummVM(); +namespace OpenGL { +void checkGLError(const char *expr, const char *file, int line); +} // End of namespace OpenGL - static Osp::App::Application *createInstance(void); - - bool OnAppInitializing(Osp::App::AppRegistry &appRegistry); - bool OnAppTerminating(Osp::App::AppRegistry &appRegistry, bool forcedTermination = false); - void OnForeground(void); - void OnBackground(void); - void OnLowMemory(void); - void OnBatteryLevelChanged(Osp::System::BatteryLevel batteryLevel); - void OnUserEventReceivedN(RequestId requestId, Osp::Base::Collection::IList *pArgs); - -private: - void pauseGame(bool pause); - BadaAppForm *_appForm; -}; +#define GLCALL(x) do { (x); OpenGL::checkGLError(#x, __FILE__, __LINE__); } while (false) +#else +#define GLCALL(x) do { (x); } while (false) +#endif #endif diff --git a/backends/graphics/opengl/extensions.cpp b/backends/graphics/opengl/extensions.cpp new file mode 100644 index 0000000000..4482ef82b5 --- /dev/null +++ b/backends/graphics/opengl/extensions.cpp @@ -0,0 +1,48 @@ +/* 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. + * + */ + +#include "backends/graphics/opengl/extensions.h" +#include "backends/graphics/opengl/opengl-sys.h" + +#include "common/tokenizer.h" + +namespace OpenGL { + +bool g_extNPOTSupported = false; + +void initializeGLExtensions() { + const char *extString = (const char *)glGetString(GL_EXTENSIONS); + + // Initialize default state. + g_extNPOTSupported = false; + + Common::StringTokenizer tokenizer(extString, " "); + while (!tokenizer.empty()) { + Common::String token = tokenizer.nextToken(); + + if (token == "GL_ARB_texture_non_power_of_two") { + g_extNPOTSupported = true; + } + } +} + +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/glerrorcheck.h b/backends/graphics/opengl/extensions.h index 2d5491bdfd..87452429e2 100644 --- a/backends/graphics/opengl/glerrorcheck.h +++ b/backends/graphics/opengl/extensions.h @@ -8,28 +8,34 @@ * 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 + * 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(DEBUG) +#ifndef BACKENDS_GRAPHICS_OPENGL_EXTENSIONS_H +#define BACKENDS_GRAPHICS_OPENGL_EXTENSIONS_H -// If not in debug, do nothing -#define CHECK_GL_ERROR() do {} while (false) +namespace OpenGL { -#else +/** + * Checks for availability of extensions we want to use and initializes them + * when available. + */ +void initializeGLExtensions(); -// If in debug, check for an error after a GL call -#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__) +/** + * Whether non power of two textures are supported + */ +extern bool g_extNPOTSupported; -void checkGlError(const char *file, int line); +} // End of namespace OpenGL #endif diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp deleted file mode 100644 index ca674563df..0000000000 --- a/backends/graphics/opengl/gltexture.cpp +++ /dev/null @@ -1,225 +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. - * - */ - -#include "common/scummsys.h" - -#if defined(USE_OPENGL) - -#include "backends/graphics/opengl/gltexture.h" -#include "backends/graphics/opengl/glerrorcheck.h" - -#include "common/rect.h" -#include "common/array.h" -#include "common/util.h" -#include "common/tokenizer.h" - -// Supported GL extensions -static bool npot_supported = false; -static bool glext_inited = false; - -/*static inline GLint xdiv(int numerator, int denominator) { - assert(numerator < (1 << 16)); - return (numerator << 16) / denominator; -}*/ - -static GLuint nextHigher2(GLuint v) { - if (v == 0) - return 1; - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return ++v; -} - -void GLTexture::initGLExtensions() { - - // Return if extensions were already checked - if (glext_inited) - return; - - // Get a string with all extensions - const char *ext_string = (const char *)glGetString(GL_EXTENSIONS); - CHECK_GL_ERROR(); - Common::StringTokenizer tokenizer(ext_string, " "); - // Iterate all string tokens - while (!tokenizer.empty()) { - Common::String token = tokenizer.nextToken(); - if (token == "GL_ARB_texture_non_power_of_two") - npot_supported = true; - } - - glext_inited = true; -} - -GLTexture::GLTexture(byte bpp, GLenum internalFormat, GLenum format, GLenum type) - : - _bytesPerPixel(bpp), - _internalFormat(internalFormat), - _glFormat(format), - _glType(type), - _textureWidth(0), - _textureHeight(0), - _realWidth(0), - _realHeight(0), - _refresh(false), - _filter(GL_NEAREST) { - - // Generate the texture ID - glGenTextures(1, &_textureName); CHECK_GL_ERROR(); -} - -GLTexture::~GLTexture() { - // Delete the texture - glDeleteTextures(1, &_textureName); CHECK_GL_ERROR(); -} - -void GLTexture::refresh() { - // Delete previous texture - glDeleteTextures(1, &_textureName); CHECK_GL_ERROR(); - - // Generate the texture ID - glGenTextures(1, &_textureName); CHECK_GL_ERROR(); - _refresh = true; -} - -void GLTexture::allocBuffer(GLuint w, GLuint h) { - _realWidth = w; - _realHeight = h; - - if (!_refresh) { - if (npot_supported && _filter == GL_LINEAR) { - // Check if we already allocated a correctly-sized buffer - // This is so we don't need to duplicate the last row/column - if (w == _textureWidth && h == _textureHeight) - return; - } else { - // Check if we already have a large enough buffer - if (w <= _textureWidth && h <= _textureHeight) - return; - } - } - - if (npot_supported) { - _textureWidth = w; - _textureHeight = h; - } else { - _textureWidth = nextHigher2(w); - _textureHeight = nextHigher2(h); - } - - // Select this OpenGL texture - glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR(); - - // Set the texture parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _filter); CHECK_GL_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _filter); CHECK_GL_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR(); - - // Allocate room for the texture - glTexImage2D(GL_TEXTURE_2D, 0, _internalFormat, - _textureWidth, _textureHeight, 0, _glFormat, _glType, NULL); CHECK_GL_ERROR(); - - _refresh = false; -} - -void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) { - // Skip empty updates. - if (w * h == 0) - return; - - // Select this OpenGL texture - glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR(); - - // Check if the buffer has its data contiguously - if ((int)w * _bytesPerPixel == pitch) { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, - _glFormat, _glType, buf); CHECK_GL_ERROR(); - } else { - // Update the texture row by row - const byte *src = (const byte *)buf; - GLuint curY = y; - GLuint height = h; - do { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, curY, - w, 1, _glFormat, _glType, src); CHECK_GL_ERROR(); - curY++; - src += pitch; - } while (--height); - } - - // If we're in linear filter mode, repeat the last row/column if the real dimensions - // doesn't match the texture dimensions. - if (_filter == GL_LINEAR) { - if (_realWidth != _textureWidth && x + w == _realWidth) { - const byte *src = (const byte *)buf + (w - 1) * _bytesPerPixel; - GLuint curY = y; - GLuint height = h; - - do { - glTexSubImage2D(GL_TEXTURE_2D, 0, x + w, - curY, 1, 1, _glFormat, _glType, src); CHECK_GL_ERROR(); - - curY++; - src += pitch; - } while (--height); - } - - if (_realHeight != _textureHeight && y + h == _realHeight) { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y + h, - w, 1, _glFormat, _glType, (const byte *)buf + pitch * (h - 1)); CHECK_GL_ERROR(); - } - } -} - -void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { - // Select this OpenGL texture - glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR(); - - // Calculate the texture rect that will be drawn - const GLfloat texWidth = (GLfloat)_realWidth / _textureWidth;//xdiv(_surface.w, _textureWidth); - const GLfloat texHeight = (GLfloat)_realHeight / _textureHeight;//xdiv(_surface.h, _textureHeight); - const GLfloat texcoords[] = { - 0, 0, - texWidth, 0, - 0, texHeight, - texWidth, texHeight, - }; - glTexCoordPointer(2, GL_FLOAT, 0, texcoords); CHECK_GL_ERROR(); - - // Calculate the screen rect where the texture will be drawn - const GLshort vertices[] = { - x, y, - (GLshort)(x + w), y, - x, (GLshort)(y + h), - (GLshort)(x + w), (GLshort)(y + h), - }; - glVertexPointer(2, GL_SHORT, 0, vertices); CHECK_GL_ERROR(); - - // Draw the texture to the screen buffer - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); CHECK_GL_ERROR(); -} - -#endif diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h deleted file mode 100644 index 8ff9838ff7..0000000000 --- a/backends/graphics/opengl/gltexture.h +++ /dev/null @@ -1,131 +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. - * - */ - -#ifndef BACKENDS_GRAPHICS_OPENGL_GLTEXTURE_H -#define BACKENDS_GRAPHICS_OPENGL_GLTEXTURE_H - -#include "common/scummsys.h" - -#ifdef WIN32 -#if defined(ARRAYSIZE) && !defined(_WINDOWS_) -#undef ARRAYSIZE -#endif -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef ARRAYSIZE -#endif - -// HACK: At this point in Windows platforms, common/util.h has been included -// via common/rect.h (from backends/graphics/sdl/sdl-graphics.h), via -// backends/graphics/openglsdl/openglsdl-graphics.h. Thus, we end up with -// COMMON_UTIL_H defined, and ARRAYSIZE undefined (bad!). Therefore, -// ARRAYSIZE is undefined in openglsdl-graphics.cpp. This is a temporary -// hackish solution fo fix compilation under Windows. -#if !defined(ARRAYSIZE) && defined(COMMON_UTIL_H) -#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0]))) -#endif - -#if defined(BADA) -#include <FGraphicsOpengl.h> -using namespace Osp::Graphics::Opengl; -#elif defined(USE_GLES) -#include <GLES/gl.h> -#elif defined(SDL_BACKEND) -#include <SDL_opengl.h> -#else -#include <GL/gl.h> -#endif - -#include "graphics/surface.h" - -/** - * OpenGL texture manager class - */ -class GLTexture { -public: - /** - * Initialize OpenGL Extensions - */ - static void initGLExtensions(); - - GLTexture(byte bpp, GLenum internalFormat, GLenum format, GLenum type); - ~GLTexture(); - - /** - * Refresh the texture after a context change. The - * process will be completed on next allocBuffer call. - */ - void refresh(); - - /** - * Allocates memory needed for the given size. - */ - void allocBuffer(GLuint width, GLuint height); - - /** - * Updates the texture pixels. - */ - void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, - GLuint w, GLuint h); - - /** - * Draws the texture to the screen buffer. - */ - void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); - - /** - * Get the texture width. - */ - GLuint getWidth() const { return _realWidth; } - - /** - * Get the texture height. - */ - GLuint getHeight() const { return _realHeight; } - - /** - * Get the bytes per pixel. - */ - uint getBytesPerPixel() const { return _bytesPerPixel; } - - /** - * Set the texture filter. - * @filter the filter type, GL_NEAREST or GL_LINEAR - */ - void setFilter(GLint filter) { _filter = filter; } - -private: - const byte _bytesPerPixel; - const GLenum _internalFormat; - const GLenum _glFormat; - const GLenum _glType; - - GLuint _realWidth; - GLuint _realHeight; - GLuint _textureName; - GLuint _textureWidth; - GLuint _textureHeight; - GLint _filter; - bool _refresh; -}; - -#endif diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 48e2663d44..a97f680f15 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -8,102 +8,90 @@ * 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. * */ -#include "common/scummsys.h" - -#if defined(USE_OPENGL) #include "backends/graphics/opengl/opengl-graphics.h" -#include "backends/graphics/opengl/glerrorcheck.h" -#include "common/config-manager.h" -#include "common/file.h" -#include "common/mutex.h" +#include "backends/graphics/opengl/texture.h" +#include "backends/graphics/opengl/debug.h" +#include "backends/graphics/opengl/extensions.h" + #include "common/textconsole.h" #include "common/translation.h" +#include "common/algorithm.h" +#include "common/file.h" #ifdef USE_OSD #include "common/tokenizer.h" +#include "common/rect.h" #endif -#include "graphics/font.h" + +#include "graphics/conversion.h" +#ifdef USE_OSD #include "graphics/fontman.h" +#include "graphics/font.h" +#endif + +namespace OpenGL { OpenGLGraphicsManager::OpenGLGraphicsManager() - : + : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), + _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0), + _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(), + _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr), + _overlayVisible(false), _cursor(nullptr), + _cursorX(0), _cursorY(0), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0), + _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorKeyColor(0), + _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) #ifdef USE_OSD - _osdTexture(0), _osdAlpha(0), _osdFadeStartTime(0), _requireOSDUpdate(false), + , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr) #endif - _gameTexture(0), _overlayTexture(0), _cursorTexture(0), - _screenChangeCount(1 << (sizeof(int) * 8 - 2)), _screenNeedsRedraw(false), - _shakePos(0), - _overlayVisible(false), _overlayNeedsRedraw(false), - _transactionMode(kTransactionNone), - _cursorNeedsRedraw(false), _cursorPaletteDisabled(true), - _cursorVisible(false), _cursorKeyColor(0), - _cursorDontScale(false), - _formatBGR(false), - _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0) { - - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); - memset(&_videoMode, 0, sizeof(_videoMode)); - memset(&_transactionDetails, 0, sizeof(_transactionDetails)); - - _videoMode.mode = OpenGL::GFX_NORMAL; - _videoMode.scaleFactor = 2; - _videoMode.fullscreen = ConfMan.getBool("fullscreen"); - _videoMode.antialiasing = false; - - _gamePalette = (byte *)calloc(sizeof(byte) * 3, 256); - _cursorPalette = (byte *)calloc(sizeof(byte) * 3, 256); + { + memset(_gamePalette, 0, sizeof(_gamePalette)); } OpenGLGraphicsManager::~OpenGLGraphicsManager() { - free(_gamePalette); - free(_cursorPalette); - - _screenData.free(); - _overlayData.free(); - _cursorData.free(); - _osdSurface.free(); - - delete _gameTexture; - delete _overlayTexture; - delete _cursorTexture; + delete _gameScreen; + delete _overlay; + delete _cursor; +#ifdef USE_OSD + delete _osd; +#endif } -// -// Feature -// - bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { - return - (f == OSystem::kFeatureAspectRatioCorrection) || - (f == OSystem::kFeatureCursorPalette); + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + case OSystem::kFeatureCursorPalette: + return true; + + case OSystem::kFeatureOverlaySupportsAlpha: + return _defaultFormatAlpha.aBits() > 3; + + default: + return false; + } } void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { switch (f) { - case OSystem::kFeatureFullscreenMode: - setFullscreenMode(enable); - break; - case OSystem::kFeatureAspectRatioCorrection: - _videoMode.aspectRatioCorrection = enable; - _transactionDetails.needRefresh = true; + assert(_transactionMode != kTransactionNone); + _currentState.aspectRatioCorrection = enable; break; case OSystem::kFeatureCursorPalette: - _cursorPaletteDisabled = !enable; - _cursorNeedsRedraw = true; + _cursorPaletteEnabled = enable; + updateCursorPalette(); break; default: @@ -113,1191 +101,1013 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { switch (f) { - case OSystem::kFeatureFullscreenMode: - return _videoMode.fullscreen; - case OSystem::kFeatureAspectRatioCorrection: - return _videoMode.aspectRatioCorrection; + return _currentState.aspectRatioCorrection; case OSystem::kFeatureCursorPalette: - return !_cursorPaletteDisabled; + return _cursorPaletteEnabled; default: return false; } } -// -// Screen format and modes -// +namespace { -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"gl1", _s("OpenGL Normal"), OpenGL::GFX_NORMAL}, - {"gl2", _s("OpenGL Conserve"), OpenGL::GFX_CONSERVE}, - {"gl4", _s("OpenGL Original"), OpenGL::GFX_ORIGINAL}, - {0, 0, 0} +const OSystem::GraphicsMode glGraphicsModes[] = { + { "opengl_linear", _s("OpenGL"), GFX_LINEAR }, + { "opengl_nearest", _s("OpenGL (No filtering)"), GFX_NEAREST }, + { nullptr, nullptr, 0 } }; -const OSystem::GraphicsMode *OpenGLGraphicsManager::supportedGraphicsModes() { - return s_supportedGraphicsModes; -} +} // End of anonymous namespace const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; + return glGraphicsModes; } int OpenGLGraphicsManager::getDefaultGraphicsMode() const { - return OpenGL::GFX_NORMAL; + return GFX_LINEAR; } bool OpenGLGraphicsManager::setGraphicsMode(int mode) { - assert(_transactionMode == kTransactionActive); + assert(_transactionMode != kTransactionNone); + + switch (mode) { + case GFX_LINEAR: + case GFX_NEAREST: + _currentState.graphicsMode = mode; + + if (_gameScreen) { + _gameScreen->enableLinearFiltering(mode == GFX_LINEAR); + } - setScale(2); + if (_cursor) { + _cursor->enableLinearFiltering(mode == GFX_LINEAR); + } - if (_oldVideoMode.setup && _oldVideoMode.mode == mode) return true; - switch (mode) { - case OpenGL::GFX_NORMAL: - case OpenGL::GFX_CONSERVE: - case OpenGL::GFX_ORIGINAL: - break; default: - warning("Unknown gfx mode %d", mode); + warning("OpenGLGraphicsManager::setGraphicsMode(%d): Unknown graphics mode", mode); return false; } - - _videoMode.mode = mode; - _transactionDetails.needRefresh = true; - - return true; } int OpenGLGraphicsManager::getGraphicsMode() const { - assert(_transactionMode == kTransactionNone); - return _videoMode.mode; -} - -void OpenGLGraphicsManager::resetGraphicsScale() { - setScale(1); + return _currentState.graphicsMode; } #ifdef USE_RGB_COLOR Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const { - return _screenFormat; + return _currentState.gameFormat; } #endif -void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) { - assert(_transactionMode == kTransactionActive); - -#ifdef USE_RGB_COLOR - Graphics::PixelFormat newFormat; - if (!format) - newFormat = Graphics::PixelFormat::createFormatCLUT8(); - else - newFormat = *format; - - assert(newFormat.bytesPerPixel > 0); - - // Avoid redundant format changes - if (newFormat != _videoMode.format) { - _videoMode.format = newFormat; - _transactionDetails.formatChanged = true; - _screenFormat = newFormat; - } -#endif - - // Avoid redundant res changes - if ((int)width == _videoMode.screenWidth && (int)height == _videoMode.screenHeight) - return; - - _videoMode.screenWidth = width; - _videoMode.screenHeight = height; - - _transactionDetails.sizeChanged = true; -} - -int OpenGLGraphicsManager::getScreenChangeID() const { - return _screenChangeCount; -} - -// -// GFX -// - void OpenGLGraphicsManager::beginGFXTransaction() { assert(_transactionMode == kTransactionNone); + // Start a transaction. + _oldState = _currentState; _transactionMode = kTransactionActive; - _transactionDetails.sizeChanged = false; - _transactionDetails.needRefresh = false; - _transactionDetails.needUpdatescreen = false; - _transactionDetails.filterChanged = false; -#ifdef USE_RGB_COLOR - _transactionDetails.formatChanged = false; -#endif - - _oldVideoMode = _videoMode; } OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { - int errors = OSystem::kTransactionSuccess; + assert(_transactionMode == kTransactionActive); - assert(_transactionMode != kTransactionNone); + uint transactionError = OSystem::kTransactionSuccess; + + bool setupNewGameScreen = false; + if ( _oldState.gameWidth != _currentState.gameWidth + || _oldState.gameHeight != _currentState.gameHeight) { + setupNewGameScreen = true; + } - if (_transactionMode == kTransactionRollback) { - if (_videoMode.fullscreen != _oldVideoMode.fullscreen) { - errors |= OSystem::kTransactionFullscreenFailed; +#ifdef USE_RGB_COLOR + if (_oldState.gameFormat != _currentState.gameFormat) { + setupNewGameScreen = true; + } + + // Check whether the requested format can actually be used. + Common::List<Graphics::PixelFormat> supportedFormats = getSupportedFormats(); + // In case the requested format is not usable we will fall back to CLUT8. + if (Common::find(supportedFormats.begin(), supportedFormats.end(), _currentState.gameFormat) == supportedFormats.end()) { + _currentState.gameFormat = Graphics::PixelFormat::createFormatCLUT8(); + transactionError |= OSystem::kTransactionFormatNotSupported; + } +#endif - _videoMode.fullscreen = _oldVideoMode.fullscreen; - } else if (_videoMode.mode != _oldVideoMode.mode) { - errors |= OSystem::kTransactionModeSwitchFailed; + do { + uint requestedWidth = _currentState.gameWidth; + uint requestedHeight = _currentState.gameHeight; + const uint desiredAspect = getDesiredGameScreenAspect(); + requestedHeight = intToFrac(requestedWidth) / desiredAspect; - _videoMode.mode = _oldVideoMode.mode; - _videoMode.scaleFactor = _oldVideoMode.scaleFactor; + if (!loadVideoMode(requestedWidth, requestedHeight, #ifdef USE_RGB_COLOR - } else if (_videoMode.format != _oldVideoMode.format) { - errors |= OSystem::kTransactionFormatNotSupported; + _currentState.gameFormat +#else + Graphics::PixelFormat::createFormatCLUT8() +#endif + ) + // HACK: This is really nasty but we don't have any guarantees of + // a context existing before, which means we don't know the maximum + // supported texture size before this. Thus, we check whether the + // requested game resolution is supported over here. + || ( _currentState.gameWidth > (uint)Texture::getMaximumTextureSize() + || _currentState.gameHeight > (uint)Texture::getMaximumTextureSize())) { + if (_transactionMode == kTransactionActive) { + // Try to setup the old state in case its valid and is + // actually different from the new one. + if (_oldState.valid && _oldState != _currentState) { + // Give some hints on what failed to set up. + if ( _oldState.gameWidth != _currentState.gameWidth + || _oldState.gameHeight != _currentState.gameHeight) { + transactionError |= OSystem::kTransactionSizeChangeFailed; + } - _videoMode.format = _oldVideoMode.format; - _screenFormat = _videoMode.format; +#ifdef USE_RGB_COLOR + if (_oldState.gameFormat != _currentState.gameFormat) { + transactionError |= OSystem::kTransactionFormatNotSupported; + } #endif - } else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) { - errors |= OSystem::kTransactionSizeChangeFailed; - _videoMode.screenWidth = _oldVideoMode.screenWidth; - _videoMode.screenHeight = _oldVideoMode.screenHeight; - _videoMode.overlayWidth = _oldVideoMode.overlayWidth; - _videoMode.overlayHeight = _oldVideoMode.overlayHeight; - } + if (_oldState.aspectRatioCorrection != _currentState.aspectRatioCorrection) { + transactionError |= OSystem::kTransactionAspectRatioFailed; + } - if (_videoMode.fullscreen == _oldVideoMode.fullscreen && - _videoMode.mode == _oldVideoMode.mode && - _videoMode.screenWidth == _oldVideoMode.screenWidth && - _videoMode.screenHeight == _oldVideoMode.screenHeight) { + if (_oldState.graphicsMode != _currentState.graphicsMode) { + transactionError |= OSystem::kTransactionModeSwitchFailed; + } - _oldVideoMode.setup = false; - } - } + // Roll back to the old state. + _currentState = _oldState; + _transactionMode = kTransactionRollback; - if (_transactionDetails.sizeChanged || _transactionDetails.needRefresh) { - unloadGFXMode(); - if (!loadGFXMode()) { - if (_oldVideoMode.setup) { - _transactionMode = kTransactionRollback; - errors |= endGFXTransaction(); + // Try to set up the old state. + continue; + } } - } else { - clearOverlay(); - _videoMode.setup = true; - _screenChangeCount++; + // DON'T use error(), as this tries to bring up the debug + // console, which WON'T WORK now that we might no have a + // proper screen. + warning("OpenGLGraphicsManager::endGFXTransaction: Could not load any graphics mode!"); + g_system->quit(); } + + // In case we reach this we have a valid state, yay. + _transactionMode = kTransactionNone; + _currentState.valid = true; + } while (_transactionMode == kTransactionRollback); + + if (setupNewGameScreen) { + delete _gameScreen; + _gameScreen = nullptr; + + GLenum glIntFormat, glFormat, glType; #ifdef USE_RGB_COLOR - } else if (_transactionDetails.filterChanged || _transactionDetails.formatChanged) { -#else - } else if (_transactionDetails.filterChanged) { + if (_currentState.gameFormat.bytesPerPixel == 1) { #endif - loadTextures(); - internUpdateScreen(); - } else if (_transactionDetails.needUpdatescreen) { - internUpdateScreen(); + const bool supported = getGLPixelFormat(_defaultFormat, glIntFormat, glFormat, glType); + assert(supported); + _gameScreen = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormat); + _gameScreen->setPalette(0, 255, _gamePalette); +#ifdef USE_RGB_COLOR + } else { + const bool supported = getGLPixelFormat(_currentState.gameFormat, glIntFormat, glFormat, glType); + assert(supported); + _gameScreen = new Texture(glIntFormat, glFormat, glType, _currentState.gameFormat); + } +#endif + + _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight); + _gameScreen->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + // We fill the screen to all black or index 0 for CLUT8. + if (_currentState.gameFormat.bytesPerPixel == 1) { + _gameScreen->fill(0); + } else { + _gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0)); + } } - _transactionMode = kTransactionNone; - return (OSystem::TransactionError)errors; -} + // Update our display area and cursor scaling. This makes sure we pick up + // aspect ratio correction and game screen changes correctly. + recalculateDisplayArea(); + recalculateCursorScaling(); -// -// Screen -// + // Something changed, so update the screen change ID. + ++_screenChangeID; -int16 OpenGLGraphicsManager::getHeight() { - return _videoMode.screenHeight; + // Since transactionError is a ORd list of TransactionErrors this is + // clearly wrong. But our API is simply broken. + return (OSystem::TransactionError)transactionError; } -int16 OpenGLGraphicsManager::getWidth() { - return _videoMode.screenWidth; +int OpenGLGraphicsManager::getScreenChangeID() const { + return _screenChangeID; } -void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { - assert(colors); - +void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) { + Graphics::PixelFormat requestedFormat; #ifdef USE_RGB_COLOR - assert(_screenFormat.bytesPerPixel == 1); + if (!format) { + requestedFormat = Graphics::PixelFormat::createFormatCLUT8(); + } else { + requestedFormat = *format; + } + _currentState.gameFormat = requestedFormat; #endif - // Save the screen palette - memcpy(_gamePalette + start * 3, colors, num * 3); - - _screenNeedsRedraw = true; - - if (_cursorPaletteDisabled) - _cursorNeedsRedraw = true; + _currentState.gameWidth = width; + _currentState.gameHeight = height; } -void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { - assert(colors); - -#ifdef USE_RGB_COLOR - assert(_screenFormat.bytesPerPixel == 1); -#endif +int16 OpenGLGraphicsManager::getWidth() { + return _currentState.gameWidth; +} - // Copies current palette to buffer - memcpy(colors, _gamePalette + start * 3, num * 3); +int16 OpenGLGraphicsManager::getHeight() { + return _currentState.gameHeight; } void OpenGLGraphicsManager::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) { - assert(x >= 0 && x < _screenData.w); - assert(y >= 0 && y < _screenData.h); - assert(h > 0 && y + h <= _screenData.h); - assert(w > 0 && x + w <= _screenData.w); - - // Copy buffer data to game screen internal buffer - const byte *src = (const byte *)buf; - byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch + x * _screenData.format.bytesPerPixel; - for (int i = 0; i < h; i++) { - memcpy(dst, src, w * _screenData.format.bytesPerPixel); - src += pitch; - dst += _screenData.pitch; - } - - // Extend dirty area if not full screen redraw is flagged - if (!_screenNeedsRedraw) { - const Common::Rect dirtyRect(x, y, x + w, y + h); - _screenDirtyRect.extend(dirtyRect); - } + _gameScreen->copyRectToTexture(x, y, w, h, buf, pitch); } -Graphics::Surface *OpenGLGraphicsManager::lockScreen() { - return &_screenData; +void OpenGLGraphicsManager::fillScreen(uint32 col) { + // FIXME: This does not conform to the OSystem specs because fillScreen + // is always taking CLUT8 color values and use color indexed mode. This is, + // however, plain odd and probably was a forgotten when we introduced + // RGB support. Thus, we simply do the "sane" thing here and hope OSystem + // gets fixed one day. + _gameScreen->fill(col); } -void OpenGLGraphicsManager::unlockScreen() { - _screenNeedsRedraw = true; +void OpenGLGraphicsManager::setShakePos(int shakeOffset) { + _gameScreenShakeOffset = shakeOffset; } -void OpenGLGraphicsManager::fillScreen(uint32 col) { - if (_gameTexture == NULL) +void OpenGLGraphicsManager::updateScreen() { + if (!_gameScreen) { return; + } -#ifdef USE_RGB_COLOR - if (_screenFormat.bytesPerPixel == 1) { - memset(_screenData.pixels, col, _screenData.h * _screenData.pitch); - } else if (_screenFormat.bytesPerPixel == 2) { - uint16 *pixels = (uint16 *)_screenData.pixels; - uint16 col16 = (uint16)col; - for (int i = 0; i < _screenData.w * _screenData.h; i++) { - pixels[i] = col16; - } - } else if (_screenFormat.bytesPerPixel == 3) { - uint8 *pixels = (uint8 *)_screenData.pixels; - byte r = (col >> 16) & 0xFF; - byte g = (col >> 8) & 0xFF; - byte b = col & 0xFF; - for (int i = 0; i < _screenData.w * _screenData.h; i++) { - pixels[0] = r; - pixels[1] = g; - pixels[2] = b; - pixels += 3; + // Clear the screen buffer + GLCALL(glClear(GL_COLOR_BUFFER_BIT)); + + const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); + + // First step: Draw the (virtual) game screen. + glPushMatrix(); + + // Adjust game screen shake position + GLCALL(glTranslatef(0, shakeOffset, 0)); + + // Draw the game screen + _gameScreen->draw(_displayX, _displayY, _displayWidth, _displayHeight); + + glPopMatrix(); + + // Second step: Draw the overlay if visible. + if (_overlayVisible) { + _overlay->draw(0, 0, _outputScreenWidth, _outputScreenHeight); + } + + // Third step: Draw the cursor if visible. + if (_cursorVisible && _cursor) { + glPushMatrix(); + + // Adjust game screen shake position, but only when the overlay is not + // visible. + if (!_overlayVisible) { + GLCALL(glTranslatef(0, shakeOffset, 0)); } - } else if (_screenFormat.bytesPerPixel == 4) { - uint32 *pixels = (uint32 *)_screenData.pixels; - for (int i = 0; i < _screenData.w * _screenData.h; i++) { - pixels[i] = col; + + _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled, + _cursorWidthScaled, _cursorHeightScaled); + + glPopMatrix(); + } + +#ifdef USE_OSD + // Fourth step: Draw the OSD. + if (_osdAlpha > 0) { + Common::StackLock lock(_osdMutex); + + // Update alpha value. + const int diff = g_system->getMillis(false) - _osdFadeStartTime; + if (diff > 0) { + if (diff >= kOSDFadeOutDuration) { + // Back to full transparency. + _osdAlpha = 0; + } else { + // Do a fade out. + _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration; + } } + + // Set the OSD transparency. + GLCALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f)); + + // Draw the OSD texture. + _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight); + + // Reset color. + GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); } -#else - memset(_screenData.pixels, col, _screenData.h * _screenData.pitch); #endif - _screenNeedsRedraw = true; } -void OpenGLGraphicsManager::updateScreen() { - assert(_transactionMode == kTransactionNone); - internUpdateScreen(); +Graphics::Surface *OpenGLGraphicsManager::lockScreen() { + return _gameScreen->getSurface(); } -void OpenGLGraphicsManager::setShakePos(int shakeOffset) { - assert(_transactionMode == kTransactionNone); - _shakePos = shakeOffset; +void OpenGLGraphicsManager::unlockScreen() { + _gameScreen->flagDirty(); } -void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect &rect) { +void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) { } void OpenGLGraphicsManager::clearFocusRectangle() { } -// -// Overlay -// - -void OpenGLGraphicsManager::showOverlay() { - assert(_transactionMode == kTransactionNone); +int16 OpenGLGraphicsManager::getOverlayWidth() { + if (_overlay) { + return _overlay->getWidth(); + } else { + return 0; + } +} - if (_overlayVisible) - return; +int16 OpenGLGraphicsManager::getOverlayHeight() { + if (_overlay) { + return _overlay->getHeight(); + } else { + return 0; + } +} +void OpenGLGraphicsManager::showOverlay() { _overlayVisible = true; - - clearOverlay(); } void OpenGLGraphicsManager::hideOverlay() { - assert(_transactionMode == kTransactionNone); - - if (!_overlayVisible) - return; - _overlayVisible = false; - - clearOverlay(); } Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const { - return _overlayFormat; + return _overlay->getFormat(); } -void OpenGLGraphicsManager::clearOverlay() { - // Set all pixels to 0 - memset(_overlayData.pixels, 0, _overlayData.h * _overlayData.pitch); - _overlayNeedsRedraw = true; +void OpenGLGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) { + _overlay->copyRectToTexture(x, y, w, h, buf, pitch); } -void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { - const byte *src = (byte *)_overlayData.pixels; - byte *dst = (byte *)buf; - for (int i = 0; i < _overlayData.h; i++) { - // Copy overlay data to buffer - memcpy(dst, src, _overlayData.pitch); - dst += pitch; - src += _overlayData.pitch; - } +void OpenGLGraphicsManager::clearOverlay() { + _overlay->fill(0); } -void OpenGLGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) { - assert(_transactionMode == kTransactionNone); - - if (_overlayTexture == NULL) - return; - - const byte *src = (const byte *)buf; - - // Clip the coordinates - if (x < 0) { - w += x; - src -= x * 2; - x = 0; - } - - if (y < 0) { - h += y; - src -= y * pitch; - y = 0; - } - - if (w > _overlayData.w - x) - w = _overlayData.w - x; - - if (h > _overlayData.h - y) - h = _overlayData.h - y; - - if (w <= 0 || h <= 0) - return; +void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { + const Graphics::Surface *overlayData = _overlay->getSurface(); - // Copy buffer data to internal overlay surface - byte *dst = (byte *)_overlayData.pixels + y * _overlayData.pitch; - for (int i = 0; i < h; i++) { - memcpy(dst + x * _overlayData.format.bytesPerPixel, src, w * _overlayData.format.bytesPerPixel); - src += pitch; - dst += _overlayData.pitch; - } + const byte *src = (const byte *)overlayData->getPixels(); + byte *dst = (byte *)buf; - // Extend dirty area if not full screen redraw is flagged - if (!_overlayNeedsRedraw) { - const Common::Rect dirtyRect(x, y, x + w, y + h); - _overlayDirtyRect.extend(dirtyRect); + for (uint h = overlayData->h; h > 0; --h) { + memcpy(dst, src, overlayData->w * overlayData->format.bytesPerPixel); + dst += pitch; + src += overlayData->pitch; } } -int16 OpenGLGraphicsManager::getOverlayHeight() { - return _videoMode.overlayHeight; -} - -int16 OpenGLGraphicsManager::getOverlayWidth() { - return _videoMode.overlayWidth; -} - -// -// Cursor -// - bool OpenGLGraphicsManager::showMouse(bool visible) { - if (_cursorVisible == visible) - return visible; - bool last = _cursorVisible; _cursorVisible = visible; - return last; } void OpenGLGraphicsManager::warpMouse(int x, int y) { - int scaledX = x; - int scaledY = y; - - int16 currentX = _cursorState.x; - int16 currentY = _cursorState.y; - + int16 currentX = _cursorX; + int16 currentY = _cursorY; 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) + // Check whether the (virtual) coordinate actually changed. If not, then + // simply do nothing. This avoids ugly "jittering" due to the actual + // output screen having a bigger resolution than the virtual coordinates. + if (currentX == x && currentY == y) { 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; + // Scale the virtual coordinates into actual physical coordinates. + if (_overlayVisible) { + if (!_overlay) { + return; } + + // It might be confusing that we actually have to handle something + // here when the overlay is visible. This is because for very small + // resolutions we have a minimal overlay size and have to adjust + // for that. + x = (x * _outputScreenWidth) / _overlay->getWidth(); + y = (y * _outputScreenHeight) / _overlay->getHeight(); } 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; + if (!_gameScreen) { + return; } - scaledX += _displayX; - scaledY += _displayY; + x = (x * _displayWidth) / _gameScreen->getWidth(); + y = (y * _displayHeight) / _gameScreen->getHeight(); + + x += _displayX; + y += _displayY; } - setMousePosition(scaledX, scaledY); - setInternalMousePosition(scaledX, scaledY); + setMousePosition(x, y); + setInternalMousePosition(x, y); +} + +namespace { +template<typename DstPixel, typename SrcPixel> +void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) { + const uint srcAdd = srcPitch - w * sizeof(SrcPixel); + const uint dstAdd = dstPitch - w * sizeof(DstPixel); + + while (h-- > 0) { + for (uint x = w; x > 0; --x, ++dst, ++src) { + if (*src == keyColor) { + *dst &= ~alphaMask; + } + } + + dst = (DstPixel *)((byte *)dst + dstAdd); + src = (const SrcPixel *)((const byte *)src + srcAdd); + } } +} // End of anonymous namespace void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { + Graphics::PixelFormat inputFormat; #ifdef USE_RGB_COLOR - if (format) - _cursorFormat = *format; - else - _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); + if (format) { + inputFormat = *format; + } else { + inputFormat = Graphics::PixelFormat::createFormatCLUT8(); + } #else - assert(keycolor <= 255); - _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); + inputFormat = Graphics::PixelFormat::createFormatCLUT8(); #endif - // Allocate space for cursor data - if (_cursorData.w != w || _cursorData.h != h || - _cursorData.format.bytesPerPixel != _cursorFormat.bytesPerPixel) - _cursorData.create(w, h, _cursorFormat); + // In case the color format has changed we will need to create the texture. + if (!_cursor || _cursor->getFormat() != inputFormat) { + delete _cursor; + _cursor = nullptr; - // Save cursor data - memcpy(_cursorData.pixels, buf, h * _cursorData.pitch); + GLenum glIntFormat, glFormat, glType; + + if (inputFormat.bytesPerPixel == 1) { + // In case this is not supported this is a serious programming + // error and the assert a bit below will trigger! + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _cursor = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormatAlpha); + } else { + // Try to use the format specified as input directly. We can only + // do so when it actually has alpha bits. + if (inputFormat.aBits() != 0 && getGLPixelFormat(inputFormat, glIntFormat, glFormat, glType)) { + _cursor = new Texture(glIntFormat, glFormat, glType, inputFormat); + } + + // Otherwise fall back to the default alpha format. + if (!_cursor) { + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _cursor = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + } + } + + assert(_cursor); + _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + } - // Set cursor info - _cursorState.w = w; - _cursorState.h = h; - _cursorState.hotX = hotspotX; - _cursorState.hotY = hotspotY; _cursorKeyColor = keycolor; + _cursorHotspotX = hotspotX; + _cursorHotspotY = hotspotY; _cursorDontScale = dontScale; - _cursorNeedsRedraw = true; - refreshCursorScale(); + _cursor->allocate(w, h); + if (inputFormat.bytesPerPixel == 1) { + // For CLUT8 cursors we can simply copy the input data into the + // texture. + _cursor->copyRectToTexture(0, 0, w, h, buf, w * inputFormat.bytesPerPixel); + } else { + // Otherwise it is a bit more ugly because we have to handle a key + // color properly. + + Graphics::Surface *dst = _cursor->getSurface(); + const uint srcPitch = w * inputFormat.bytesPerPixel; + + // Copy the cursor data to the actual texture surface. This will make + // sure that the data is also converted to the expected format. + Graphics::crossBlit((byte *)dst->getPixels(), (const byte *)buf, dst->pitch, srcPitch, + w, h, dst->format, inputFormat); + + // We apply the color key by setting the alpha bits of the pixels to + // fully transparent. + const uint32 aMask = (0xFF >> dst->format.aLoss) << dst->format.aShift; + if (dst->format.bytesPerPixel == 2) { + if (inputFormat.bytesPerPixel == 2) { + applyColorKey<uint16, uint16>((uint16 *)dst->getPixels(), (const uint16 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } else if (inputFormat.bytesPerPixel == 4) { + applyColorKey<uint16, uint32>((uint16 *)dst->getPixels(), (const uint32 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } + } else { + if (inputFormat.bytesPerPixel == 2) { + applyColorKey<uint32, uint16>((uint32 *)dst->getPixels(), (const uint16 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } else if (inputFormat.bytesPerPixel == 4) { + applyColorKey<uint32, uint32>((uint32 *)dst->getPixels(), (const uint32 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } + } + + // Flag the texture as dirty. + _cursor->flagDirty(); + } + + // In case we actually use a palette set that up properly. + if (inputFormat.bytesPerPixel == 1) { + updateCursorPalette(); + } + + // Update the scaling. + recalculateCursorScaling(); } void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { - assert(colors); + // FIXME: For some reason client code assumes that usage of this function + // automatically enables the cursor palette. + _cursorPaletteEnabled = true; - // Save the cursor palette memcpy(_cursorPalette + start * 3, colors, num * 3); - - _cursorPaletteDisabled = false; - _cursorNeedsRedraw = true; + updateCursorPalette(); } -// -// Misc -// - void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { - assert(_transactionMode == kTransactionNone); - assert(msg); - #ifdef USE_OSD - // Split the message into separate lines. - _osdLines.clear(); + // HACK: Actually no client code should use graphics functions from + // another thread. But the MT-32 emulator still does, thus we need to + // make sure this doesn't happen while a updateScreen call is done. + Common::StackLock lock(_osdMutex); + // Slip up the lines. + Common::Array<Common::String> osdLines; Common::StringTokenizer tokenizer(msg, "\n"); - while (!tokenizer.empty()) - _osdLines.push_back(tokenizer.nextToken()); + while (!tokenizer.empty()) { + osdLines.push_back(tokenizer.nextToken()); + } - // Request update of the texture - _requireOSDUpdate = true; + // Do the actual drawing like the SDL backend. + const Graphics::Font *font = getFontOSD(); + Graphics::Surface *dst = _osd->getSurface(); + _osd->fill(0); + _osd->flagDirty(); - // Init the OSD display parameters, and the fade out + // 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 + width = MIN<int>(width, dst->w); + height = MIN<int>(height, dst->h); + + int dstX = (dst->w - width) / 2; + int dstY = (dst->h - height) / 2; + + // Draw a dark gray rect. + const uint32 color = dst->format.RGBToColor(40, 40, 40); + dst->fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color); + + // Render the message, centered, and in white + const uint32 white = dst->format.RGBToColor(255, 255, 255); + for (uint i = 0; i < osdLines.size(); ++i) { + font->drawString(dst, osdLines[i], + dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, + white, Graphics::kTextAlignCenter); + } + + // Init the OSD display parameters. _osdAlpha = kOSDInitialAlpha; _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; #endif } -// -// Intern -// +void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { + assert(_gameScreen->hasPalette()); -void OpenGLGraphicsManager::setFullscreenMode(bool enable) { - assert(_transactionMode == kTransactionActive); + memcpy(_gamePalette + start * 3, colors, num * 3); + _gameScreen->setPalette(start, num, colors); - if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable) - return; + // We might need to update the cursor palette here. + updateCursorPalette(); +} - if (_transactionMode == kTransactionActive) { - _videoMode.fullscreen = enable; - _transactionDetails.needRefresh = true; - } +void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { + assert(_gameScreen->hasPalette()); + + memcpy(colors, _gamePalette + start * 3, num * 3); } -void OpenGLGraphicsManager::refreshGameScreen() { - if (_screenNeedsRedraw) - _screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h); - - int x = _screenDirtyRect.left; - int y = _screenDirtyRect.top; - int w = _screenDirtyRect.width(); - int h = _screenDirtyRect.height(); - - 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.format.bytesPerPixel; - byte *dst = surface; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - dst[0] = _gamePalette[src[j] * 3]; - dst[1] = _gamePalette[src[j] * 3 + 1]; - dst[2] = _gamePalette[src[j] * 3 + 2]; - dst += 3; - } - src += _screenData.pitch; +void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { + _outputScreenWidth = width; + _outputScreenHeight = height; + + // Setup coordinates system. + GLCALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight)); + + GLCALL(glMatrixMode(GL_PROJECTION)); + GLCALL(glLoadIdentity()); +#ifdef USE_GLES + GLCALL(glOrthof(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); +#else + GLCALL(glOrtho(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); +#endif + GLCALL(glMatrixMode(GL_MODELVIEW)); + GLCALL(glLoadIdentity()); + + uint overlayWidth = width; + uint overlayHeight = height; + + // WORKAROUND: We can only support surfaces up to the maximum supported + // texture size. Thus, in case we encounter a physical size bigger than + // this maximum texture size we will simply use an overlay as big as + // possible and then scale it to the physical display size. This sounds + // bad but actually all recent chips should support full HD resolution + // anyway. Thus, it should not be a real issue for modern hardware. + if ( overlayWidth > (uint)Texture::getMaximumTextureSize() + || overlayHeight > (uint)Texture::getMaximumTextureSize()) { + const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; + + if (outputAspect > (frac_t)FRAC_ONE) { + overlayWidth = Texture::getMaximumTextureSize(); + overlayHeight = intToFrac(overlayWidth) / outputAspect; + } else { + overlayHeight = Texture::getMaximumTextureSize(); + overlayWidth = fracToInt(overlayHeight * outputAspect); } + } - // Update the texture - _gameTexture->updateBuffer(surface, w * 3, x, y, w, h); + // HACK: We limit the minimal overlay size to 256x200, which is the + // minimum of the dimensions of the two resolutions 256x240 (NES) and + // 320x200 (many DOS games use this). This hopefully assure that our + // GUI has working layouts. + overlayWidth = MAX<uint>(overlayWidth, 256); + overlayHeight = MAX<uint>(overlayHeight, 200); + + if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) { + delete _overlay; + _overlay = nullptr; + + GLenum glIntFormat, glFormat, glType; + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _overlay = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + // We always filter the overlay with GL_LINEAR. This assures it's + // readable in case it needs to be scaled and does not affect it + // otherwise. + _overlay->enableLinearFiltering(true); + } + _overlay->allocate(overlayWidth, overlayHeight); + _overlay->fill(0); - // Free the temp surface - delete[] surface; - } else { - // Update the texture - _gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch + - x * _screenData.format.bytesPerPixel, _screenData.pitch, x, y, w, h); +#ifdef USE_OSD + if (!_osd || _osd->getFormat() != _defaultFormatAlpha) { + delete _osd; + _osd = nullptr; + + GLenum glIntFormat, glFormat, glType; + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + // We always filter the osd with GL_LINEAR. This assures it's + // readable in case it needs to be scaled and does not affect it + // otherwise. + _osd->enableLinearFiltering(true); } + _osd->allocate(_overlay->getWidth(), _overlay->getHeight()); + _osd->fill(0); +#endif - _screenNeedsRedraw = false; - _screenDirtyRect = Common::Rect(); + // Re-setup the scaling for the screen and cursor + recalculateDisplayArea(); + recalculateCursorScaling(); + + // Something changed, so update the screen change ID. + ++_screenChangeID; } -void OpenGLGraphicsManager::refreshOverlay() { - if (_overlayNeedsRedraw) - _overlayDirtyRect = Common::Rect(0, 0, _overlayData.w, _overlayData.h); - - int x = _overlayDirtyRect.left; - int y = _overlayDirtyRect.top; - int w = _overlayDirtyRect.width(); - int h = _overlayDirtyRect.height(); - - 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.format.bytesPerPixel; - byte *dst = surface; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - dst[0] = _gamePalette[src[j] * 3]; - dst[1] = _gamePalette[src[j] * 3 + 1]; - dst[2] = _gamePalette[src[j] * 3 + 2]; - dst += 3; - } - src += _screenData.pitch; - } +void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { + // Initialize all extensions. + initializeGLExtensions(); - // Update the texture - _overlayTexture->updateBuffer(surface, w * 3, x, y, w, h); + // Disable 3D properties. + 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)); - // Free the temp surface - delete[] surface; - } else { - // Update the texture - _overlayTexture->updateBuffer((byte *)_overlayData.pixels + y * _overlayData.pitch + - x * _overlayData.format.bytesPerPixel, _overlayData.pitch, x, y, w, h); - } + // Default to black as clear color. + GLCALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); + GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); - _overlayNeedsRedraw = false; - _overlayDirtyRect = Common::Rect(); -} + // Setup alpha blend (for overlay and cursor). + GLCALL(glEnable(GL_BLEND)); + GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); -void OpenGLGraphicsManager::refreshCursor() { - _cursorNeedsRedraw = false; - - // 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) - palette = _gamePalette; - else - palette = _cursorPalette; - - // Convert the paletted cursor to RGBA8888 - const byte *src = (byte *)_cursorData.pixels; - for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { - // Check for keycolor - if (src[i] != _cursorKeyColor) { - dst[0] = palette[src[i] * 3]; - dst[1] = palette[src[i] * 3 + 1]; - dst[2] = palette[src[i] * 3 + 2]; - dst[3] = 255; - } - dst += 4; - } - } else { - const bool gotNoAlpha = (_cursorFormat.aLoss == 8); - - // Convert the RGB cursor to RGBA8888 - if (_cursorFormat.bytesPerPixel == 2) { - const uint16 *src = (uint16 *)_cursorData.pixels; - for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { - // Check for keycolor - if (src[i] != _cursorKeyColor) { - _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]); - - if (gotNoAlpha) - dst[3] = 255; - } - dst += 4; - } - } else if (_cursorFormat.bytesPerPixel == 4) { - const uint32 *src = (uint32 *)_cursorData.pixels; - for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { - // Check for keycolor - if (src[i] != _cursorKeyColor) { - _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]); - - if (gotNoAlpha) - dst[3] = 255; - } - dst += 4; - } - } - } + // Enable rendering with vertex and coord arrays. + GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); + GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - // Update the texture with new cursor - _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h); + GLCALL(glEnable(GL_TEXTURE_2D)); - // Free the temp surface - delete[] surface; -} + // 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. + GLCALL(glPixelStorei(GL_PACK_ALIGNMENT, 4)); -void OpenGLGraphicsManager::refreshCursorScale() { - // Calculate the scale factors of the screen. - // We also totally ignore the aspect of the overlay cursor, since aspect - // ratio correction only applies to the game screen. - // TODO: It might make sense to always ignore scaling of the mouse cursor - // when the overlay is visible. - uint screenScaleFactorX = _videoMode.hardwareWidth * 10000 / _videoMode.screenWidth; - uint screenScaleFactorY = _videoMode.hardwareHeight * 10000 / _videoMode.screenHeight; - - // Ignore scaling when the cursor should not be scaled. - if (_cursorDontScale) { - screenScaleFactorX = 10000; - screenScaleFactorY = 10000; - } + // Query information needed by textures. + Texture::queryTextureInformation(); - // Apply them (without any possible) aspect ratio correction to the - // overlay. - _cursorState.rW = (int16)(_cursorState.w * screenScaleFactorX / 10000); - _cursorState.rH = (int16)(_cursorState.h * screenScaleFactorY / 10000); - _cursorState.rHotX = (int16)(_cursorState.hotX * screenScaleFactorX / 10000); - _cursorState.rHotY = (int16)(_cursorState.hotY * screenScaleFactorY / 10000); - - // Only apply scaling when it's desired. - if (_cursorDontScale) { - screenScaleFactorX = 10000; - screenScaleFactorY = 10000; - } else { - // Make sure we properly scale the cursor according to the desired aspect. - int width, height; - calculateDisplaySize(width, height); - screenScaleFactorX = (width * 10000 / _videoMode.screenWidth); - screenScaleFactorY = (height * 10000 / _videoMode.screenHeight); + // Refresh the output screen dimensions if some are set up. + if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { + setActualScreenSize(_outputScreenWidth, _outputScreenHeight); } - // Apply the scale cursor scaling for the game screen. - _cursorState.vW = (int16)(_cursorState.w * screenScaleFactorX / 10000); - _cursorState.vH = (int16)(_cursorState.h * screenScaleFactorY / 10000); - _cursorState.vHotX = (int16)(_cursorState.hotX * screenScaleFactorX / 10000); - _cursorState.vHotY = (int16)(_cursorState.hotY * screenScaleFactorY / 10000); -} + // TODO: Should we try to convert textures into one of those formats if + // possible? For example, when _gameScreen is CLUT8 we might want to use + // defaultFormat now. + _defaultFormat = defaultFormat; + _defaultFormatAlpha = defaultFormatAlpha; -void OpenGLGraphicsManager::calculateDisplaySize(int &width, int &height) { - if (_videoMode.mode == OpenGL::GFX_ORIGINAL) { - width = _videoMode.screenWidth; - height = _videoMode.screenHeight; - } else { - width = _videoMode.hardwareWidth; - height = _videoMode.hardwareHeight; + if (_gameScreen) { + _gameScreen->recreateInternalTexture(); + } + + if (_overlay) { + _overlay->recreateInternalTexture(); + } - uint aspectRatio = (_videoMode.hardwareWidth * 10000 + 5000) / _videoMode.hardwareHeight; - uint desiredAspectRatio = getAspectRatio(); + if (_cursor) { + _cursor->recreateInternalTexture(); + } - // Adjust one screen dimension for mantaining the aspect ratio - if (aspectRatio < desiredAspectRatio) - height = (width * 10000 + 5000) / desiredAspectRatio; - else if (aspectRatio > desiredAspectRatio) - width = (height * desiredAspectRatio + 5000) / 10000; +#ifdef USE_OSD + if (_osd) { + _osd->recreateInternalTexture(); } +#endif } -void OpenGLGraphicsManager::refreshDisplaySize() { - calculateDisplaySize(_displayWidth, _displayHeight); +void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { + if (_overlayVisible) { + // It might be confusing that we actually have to handle something + // here when the overlay is visible. This is because for very small + // resolutions we have a minimal overlay size and have to adjust + // for that. + // This can also happen when the overlay is smaller than the actual + // display size because of texture size limitations. + if (_overlay) { + x = (x * _overlay->getWidth()) / _outputScreenWidth; + y = (y * _overlay->getHeight()) / _outputScreenHeight; + } + } else if (_gameScreen) { + x -= _displayX; + y -= _displayY; + + const int16 width = _gameScreen->getWidth(); + const int16 height = _gameScreen->getHeight(); + + x = (x * width) / _displayWidth; + y = (y * height) / _displayHeight; - // Adjust x and y for centering the screen - _displayX = (_videoMode.hardwareWidth - _displayWidth) / 2; - _displayY = (_videoMode.hardwareHeight - _displayHeight) / 2; + // Make sure we only supply valid coordinates. + x = CLIP<int16>(x, 0, width - 1); + y = CLIP<int16>(y, 0, height - 1); + } } -void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &intFormat, GLenum &glFormat, GLenum &gltype) { +bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const { if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 - bpp = 4; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_RGBA; - gltype = GL_UNSIGNED_INT_8_8_8_8; - } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)) { // RGB888 - bpp = 3; - intFormat = GL_RGB; - glFormat = GL_RGB; - gltype = GL_UNSIGNED_BYTE; + glType = GL_UNSIGNED_INT_8_8_8_8; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 - bpp = 2; - intFormat = GL_RGB; + glIntFormat = GL_RGB; glFormat = GL_RGB; - gltype = GL_UNSIGNED_SHORT_5_6_5; - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGB5551 - bpp = 2; - intFormat = GL_RGBA; + glType = GL_UNSIGNED_SHORT_5_6_5; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGBA5551 + glIntFormat = GL_RGBA; glFormat = GL_RGBA; - gltype = GL_UNSIGNED_SHORT_5_5_5_1; + glType = GL_UNSIGNED_SHORT_5_5_5_1; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 - bpp = 2; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_RGBA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4; - } else if (pixelFormat.bytesPerPixel == 1) { // CLUT8 - // If uses a palette, create texture as RGB888. The pixel data will be converted - // later. - bpp = 3; - intFormat = GL_RGB; - glFormat = GL_RGB; - gltype = GL_UNSIGNED_BYTE; + glType = GL_UNSIGNED_SHORT_4_4_4_4; + return true; #ifndef USE_GLES } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 // GL_BGRA does not exist in every GLES implementation so should not be configured if // USE_GLES is set. - bpp = 2; - intFormat = GL_RGB; + glIntFormat = GL_RGB; glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV; + glType = GL_UNSIGNED_SHORT_1_5_5_5_REV; + return true; } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888 - bpp = 4; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_BGRA; - gltype = GL_UNSIGNED_INT_8_8_8_8_REV; + glType = GL_UNSIGNED_INT_8_8_8_8_REV; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444 - bpp = 2; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV; + glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; + return true; } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 - bpp = 4; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_RGBA; - gltype = GL_UNSIGNED_INT_8_8_8_8_REV; + glType = GL_UNSIGNED_INT_8_8_8_8_REV; + return true; } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888 - bpp = 4; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_BGRA; - gltype = GL_UNSIGNED_BYTE; - } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0)) { // BGR888 - bpp = 3; - intFormat = GL_RGB; - glFormat = GL_BGR; - gltype = GL_UNSIGNED_BYTE; + glType = GL_UNSIGNED_INT_8_8_8_8; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565 - bpp = 2; - intFormat = GL_RGB; + glIntFormat = GL_RGB; glFormat = GL_BGR; - gltype = GL_UNSIGNED_SHORT_5_6_5; + glType = GL_UNSIGNED_SHORT_5_6_5; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551 - bpp = 2; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_5_5_5_1; + glType = GL_UNSIGNED_SHORT_5_5_5_1; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444 - bpp = 2; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_RGBA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV; + glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444 - bpp = 2; - intFormat = GL_RGBA; + glIntFormat = GL_RGBA; glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4; + glType = GL_UNSIGNED_SHORT_4_4_4_4; + return true; #endif } else { - error("OpenGLGraphicsManager: Pixel format not supported"); + return false; } } -void OpenGLGraphicsManager::internUpdateScreen() { - // Clear the screen buffer - glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR(); - - if (_screenNeedsRedraw || !_screenDirtyRect.isEmpty()) - // Refresh texture if dirty - refreshGameScreen(); - - int scaleFactor = _videoMode.hardwareHeight / _videoMode.screenHeight; - - glPushMatrix(); - - // Adjust game screen shake position - glTranslatef(0, _shakePos * scaleFactor, 0); CHECK_GL_ERROR(); - - // Draw the game screen - _gameTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight); - - glPopMatrix(); - - if (_overlayVisible) { - if (_overlayNeedsRedraw || !_overlayDirtyRect.isEmpty()) - // Refresh texture if dirty - refreshOverlay(); - - // Draw the overlay - _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight); - } - - if (_cursorVisible) { - if (_cursorNeedsRedraw) - // Refresh texture if dirty - refreshCursor(); - - glPushMatrix(); - - // Adjust mouse shake position, unless the overlay is visible - glTranslatef(0, _overlayVisible ? 0 : _shakePos * scaleFactor, 0); CHECK_GL_ERROR(); - - // Draw the cursor - if (_overlayVisible) - _cursorTexture->drawTexture(_cursorState.x - _cursorState.rHotX, - _cursorState.y - _cursorState.rHotY, _cursorState.rW, _cursorState.rH); - else - _cursorTexture->drawTexture(_cursorState.x - _cursorState.vHotX, - _cursorState.y - _cursorState.vHotY, _cursorState.vW, _cursorState.vH); - - glPopMatrix(); - } +frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const { + const uint width = _currentState.gameWidth; + const uint height = _currentState.gameHeight; -#ifdef USE_OSD - if (_osdAlpha > 0) { - if (_requireOSDUpdate) { - updateOSD(); - _requireOSDUpdate = false; + if (_currentState.aspectRatioCorrection) { + // In case we enable aspect ratio correction we force a 4/3 ratio. + // But just for 320x200 and 640x400 games, since other games do not need + // this. + if ((width == 320 && height == 200) || (width == 640 && height == 400)) { + return intToFrac(4) / 3; } - - // Update alpha value - const int diff = g_system->getMillis() - _osdFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdAlpha = 0; - } else { - // Do a fade out - _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration; - } - } - // Set the osd transparency - glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); CHECK_GL_ERROR(); - - // Draw the osd texture - _osdTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); - - // Reset color - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CHECK_GL_ERROR(); } -#endif -} - -void OpenGLGraphicsManager::initGL() { - // Check available GL Extensions - GLTexture::initGLExtensions(); - - // Disable 3D properties - glDisable(GL_CULL_FACE); CHECK_GL_ERROR(); - glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR(); - glDisable(GL_LIGHTING); CHECK_GL_ERROR(); - glDisable(GL_FOG); CHECK_GL_ERROR(); - glDisable(GL_DITHER); CHECK_GL_ERROR(); - glShadeModel(GL_FLAT); CHECK_GL_ERROR(); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); CHECK_GL_ERROR(); - // Setup alpha blend (For overlay and cursor) - glEnable(GL_BLEND); CHECK_GL_ERROR(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERROR(); - - // Enable rendering with vertex and coord arrays - glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERROR(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_GL_ERROR(); - - glEnable(GL_TEXTURE_2D); CHECK_GL_ERROR(); - - // Setup the GL viewport - glViewport(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); CHECK_GL_ERROR(); - - // Setup coordinates system - glMatrixMode(GL_PROJECTION); CHECK_GL_ERROR(); - glLoadIdentity(); CHECK_GL_ERROR(); -#ifdef USE_GLES - glOrthof(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR(); -#else - glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR(); -#endif - glMatrixMode(GL_MODELVIEW); CHECK_GL_ERROR(); - glLoadIdentity(); CHECK_GL_ERROR(); + return intToFrac(width) / height; } -void OpenGLGraphicsManager::loadTextures() { -#ifdef USE_RGB_COLOR - if (_transactionDetails.formatChanged && _gameTexture) { - delete _gameTexture; - _gameTexture = 0; +void OpenGLGraphicsManager::recalculateDisplayArea() { + if (!_gameScreen || _outputScreenHeight == 0) { + return; } -#endif - - if (!_gameTexture) { - byte bpp; - GLenum intformat; - GLenum format; - GLenum type; -#ifdef USE_RGB_COLOR - getGLPixelFormat(_screenFormat, bpp, intformat, format, type); -#else - getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, intformat, format, type); -#endif - _gameTexture = new GLTexture(bpp, intformat, format, type); - } else - _gameTexture->refresh(); - - _overlayFormat = Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0); - - if (!_overlayTexture) { - byte bpp; - GLenum intformat; - GLenum format; - GLenum type; - getGLPixelFormat(_overlayFormat, bpp, intformat, format, type); - _overlayTexture = new GLTexture(bpp, intformat, format, type); - } else - _overlayTexture->refresh(); - - if (!_cursorTexture) - _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); - _cursorTexture->setFilter(filter); - - // Allocate texture memory and finish refreshing - _gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight); - _overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); - _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); - - if ( -#ifdef USE_RGB_COLOR - _transactionDetails.formatChanged || -#endif - _oldVideoMode.screenWidth != _videoMode.screenWidth || - _oldVideoMode.screenHeight != _videoMode.screenHeight) - _screenData.create(_videoMode.screenWidth, _videoMode.screenHeight, -#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); - _screenNeedsRedraw = true; - _overlayNeedsRedraw = true; - _cursorNeedsRedraw = true; + const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; + const frac_t desiredAspect = getDesiredGameScreenAspect(); - // 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. - // It is noteworthy this assumes the OSD uses the same BPP as the overlay - // and that the cursor works with any alignment setting. - int newAlignment = Common::gcd(_gameTexture->getBytesPerPixel(), _overlayTexture->getBytesPerPixel()); - assert(newAlignment == 1 || newAlignment == 2 || newAlignment == 4); - glPixelStorei(GL_UNPACK_ALIGNMENT, newAlignment); + _displayWidth = _outputScreenWidth; + _displayHeight = _outputScreenHeight; - // 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); - else - _osdTexture->refresh(); - - _osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); + // Adjust one dimension for mantaining the aspect ratio. + if (outputAspect < desiredAspect) { + _displayHeight = intToFrac(_displayWidth) / desiredAspect; + } else if (outputAspect > desiredAspect) { + _displayWidth = fracToInt(_displayHeight * desiredAspect); + } - // Update the OSD in case it is used right now - _requireOSDUpdate = true; -#endif + // We center the screen in the middle for now. + _displayX = (_outputScreenWidth - _displayWidth ) / 2; + _displayY = (_outputScreenHeight - _displayHeight) / 2; } -bool OpenGLGraphicsManager::loadGFXMode() { - // Initialize OpenGL settings - initGL(); - - loadTextures(); - - refreshCursorScale(); - - refreshDisplaySize(); - - internUpdateScreen(); - - return true; -} +void OpenGLGraphicsManager::updateCursorPalette() { + if (!_cursor || !_cursor->hasPalette()) { + return; + } -void OpenGLGraphicsManager::unloadGFXMode() { + if (_cursorPaletteEnabled) { + _cursor->setPalette(0, 256, _cursorPalette); + } else { + _cursor->setPalette(0, 256, _gamePalette); + } + // We remove all alpha bits from the palette entry of the color key. + // This makes sure its properly handled as color key. + const Graphics::PixelFormat &hardwareFormat = _cursor->getHardwareFormat(); + const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift; + + if (hardwareFormat.bytesPerPixel == 2) { + uint16 *palette = (uint16 *)_cursor->getPalette() + _cursorKeyColor; + *palette &= ~aMask; + } else if (hardwareFormat.bytesPerPixel == 4) { + uint32 *palette = (uint32 *)_cursor->getPalette() + _cursorKeyColor; + *palette &= ~aMask; + } else { + warning("OpenGLGraphicsManager::updateCursorPalette: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel); + } } -void OpenGLGraphicsManager::setScale(int newScale) { - assert(_transactionMode == kTransactionActive); - - if (newScale == _videoMode.scaleFactor) +void OpenGLGraphicsManager::recalculateCursorScaling() { + if (!_cursor || !_gameScreen) { return; + } - _videoMode.scaleFactor = newScale; - _transactionDetails.sizeChanged = true; -} + // By default we use the unscaled versions. + _cursorHotspotXScaled = _cursorHotspotX; + _cursorHotspotYScaled = _cursorHotspotY; + _cursorWidthScaled = _cursor->getWidth(); + _cursorHeightScaled = _cursor->getHeight(); -void OpenGLGraphicsManager::toggleAntialiasing() { - assert(_transactionMode == kTransactionActive); + // In case scaling is actually enabled we will scale the cursor according + // to the game screen. + if (!_cursorDontScale) { + const uint screenScaleFactorX = _displayWidth * 10000 / _gameScreen->getWidth(); + const uint screenScaleFactorY = _displayHeight * 10000 / _gameScreen->getHeight(); - _videoMode.antialiasing = !_videoMode.antialiasing; - _transactionDetails.filterChanged = true; -} + _cursorHotspotXScaled = (_cursorHotspotXScaled * screenScaleFactorX) / 10000; + _cursorWidthScaled = (_cursorWidthScaled * screenScaleFactorX) / 10000; -uint OpenGLGraphicsManager::getAspectRatio() const { - // In case we enable aspect ratio correction we force a 4/3 ratio. - // But just for 320x200 and 640x400 games, since other games do not need - // this. - // 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 - && ((_videoMode.screenWidth == 320 && _videoMode.screenHeight == 200) - || (_videoMode.screenWidth == 640 && _videoMode.screenHeight == 400))) - return 13333; - else if (_videoMode.mode == OpenGL::GFX_NORMAL) - return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight; - else - return _videoMode.screenWidth * 10000 / _videoMode.screenHeight; + _cursorHotspotYScaled = (_cursorHotspotYScaled * screenScaleFactorY) / 10000; + _cursorHeightScaled = (_cursorHeightScaled * screenScaleFactorY) / 10000; + } } -void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { - if (_overlayVisible) - return; - - x -= _displayX; - y -= _displayY; - - if (_displayWidth != _videoMode.screenWidth) - x = x * _videoMode.screenWidth / _displayWidth; - if (_displayHeight != _videoMode.screenHeight) - y = y * _videoMode.screenHeight / _displayHeight; +#ifdef USE_OSD +const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { + return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont); } +#endif -bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { - int width = _videoMode.hardwareWidth; - int height = _videoMode.hardwareHeight; +void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const { + const uint width = _outputScreenWidth; + const uint height = _outputScreenHeight; // 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; + const uint linePaddingSize = width % 4; + const uint lineSize = width * 3 + linePaddingSize; // Allocate memory for screenshot uint8 *pixels = new uint8[lineSize * height]; // Get pixel data from OpenGL buffer -#ifdef USE_GLES - glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR(); -#else - if (_formatBGR) { - glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR(); - } else { - glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR(); + GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels)); + + // BMP stores as BGR. Since we can't assume that GL_BGR is supported we + // will swap the components from the RGB we read to BGR on our own. + for (uint y = height; y-- > 0;) { + uint8 *line = pixels + y * lineSize; + + for (uint x = width; x > 0; --x, line += 3) { + SWAP(line[0], line[2]); + } } -#endif // Open file Common::DumpFile out; @@ -1326,73 +1136,6 @@ bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { // Free allocated memory delete[] pixels; - - return true; -} - -const char *OpenGLGraphicsManager::getCurrentModeName() { - const char *modeName = 0; - const OSystem::GraphicsMode *g = getSupportedGraphicsModes(); - while (g->name) { - if (g->id == _videoMode.mode) { - modeName = g->description; - break; - } - g++; - } - return modeName; -} - -#ifdef USE_OSD -const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { - return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont); -} - -void OpenGLGraphicsManager::updateOSD() { - // The font we are going to use: - const Graphics::Font *font = getFontOSD(); - - 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); - - // 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 (R = 40, G = 40, B = 40) - 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 +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 9d8d418d11..d2d0358407 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -8,338 +8,464 @@ * 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_OPENGL_H -#define BACKENDS_GRAPHICS_OPENGL_H +#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H +#define BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H -#include "backends/graphics/opengl/gltexture.h" +#include "backends/graphics/opengl/opengl-sys.h" #include "backends/graphics/graphics.h" -#include "common/array.h" -#include "common/rect.h" -#include "graphics/font.h" -#include "graphics/pixelformat.h" -// Uncomment this to enable the 'on screen display' code. -#define USE_OSD 1 +#include "common/frac.h" +#include "common/mutex.h" + +namespace Graphics { +class Font; +} // End of namespace Graphics namespace OpenGL { -// The OpenGL GFX modes. They have to be inside the OpenGL namespace so they -// do not clash with the SDL GFX modes. + +// HACK: We use glColor in the OSD code. This might not be working on GL ES but +// we still enable it because Tizen already shipped with it. Also, the +// SurfaceSDL backend enables it and disabling it can cause issues in sdl.cpp. +#define USE_OSD 1 + +class Texture; + enum { - GFX_NORMAL = 0, - GFX_CONSERVE = 1, - GFX_ORIGINAL = 2 + GFX_LINEAR = 0, + GFX_NEAREST = 1 }; -} - -/** - * OpenGL graphics manager. This is an abstract class, it does not do the - * window and OpenGL context initialization. - * Derived classes should at least override internUpdateScreen for doing - * the buffers swap, and implement loadGFXMode for handling the window/context if - * needed. If USE_RGB_COLOR is enabled, getSupportedFormats must be implemented. - */ class OpenGLGraphicsManager : public GraphicsManager { public: OpenGLGraphicsManager(); virtual ~OpenGLGraphicsManager(); + // GraphicsManager API virtual bool hasFeature(OSystem::Feature f); virtual void setFeatureState(OSystem::Feature f, bool enable); virtual bool getFeatureState(OSystem::Feature f); - static const OSystem::GraphicsMode *supportedGraphicsModes(); virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; virtual bool setGraphicsMode(int mode); virtual int getGraphicsMode() const; - virtual void resetGraphicsScale(); + + virtual void resetGraphicsScale() {} + #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const; virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; #endif - virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); - virtual int getScreenChangeID() const; virtual void beginGFXTransaction(); virtual OSystem::TransactionError endGFXTransaction(); - virtual int16 getHeight(); + virtual int getScreenChangeID() const; + + virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); + virtual int16 getWidth(); -protected: - // PaletteManager API - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual int16 getHeight(); -public: virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); virtual void fillScreen(uint32 col); - virtual void updateScreen(); + virtual void setShakePos(int shakeOffset); - virtual void setFocusRectangle(const Common::Rect &rect); + + virtual void updateScreen(); + + virtual Graphics::Surface *lockScreen(); + virtual void unlockScreen(); + + virtual void setFocusRectangle(const Common::Rect& rect); virtual void clearFocusRectangle(); + virtual int16 getOverlayWidth(); + virtual int16 getOverlayHeight(); + virtual void showOverlay(); virtual void hideOverlay(); + virtual Graphics::PixelFormat getOverlayFormat() const; + + virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h); virtual void clearOverlay(); virtual void grabOverlay(void *buf, int pitch); - virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h); - virtual int16 getOverlayHeight(); - virtual int16 getOverlayWidth(); virtual bool showMouse(bool visible); virtual void warpMouse(int x, int y); - virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL); + virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format); virtual void setCursorPalette(const byte *colors, uint start, uint num); virtual void displayMessageOnOSD(const char *msg); + + // PaletteManager interface + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + protected: /** - * Setup OpenGL settings + * Set up the actual screen size available for the OpenGL code to do any + * drawing. + * + * @param width The width of the screen. + * @param height The height of the screen. + */ + void setActualScreenSize(uint width, uint height); + + /** + * Notify the manager of a OpenGL context change. This should be the first + * thing to call when you create an OpenGL (ES) context! + * + * @param defaultFormat The new default format for the game screen + * (this is used for the CLUT8 game screens). + * @param defaultFromatAlpha The new default format with an alpha channel + * (this is used for the overlay and cursor). + */ + void notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha); + + /** + * Adjust the physical mouse coordinates according to the currently visible screen. + */ + void adjustMousePosition(int16 &x, int16 &y); + + /** + * Set up the mouse position for graphics output. + * + * @param x X coordinate in physical coordinates. + * @param y Y coordinate in physical coordinates. + */ + void setMousePosition(int x, int y) { _cursorX = x; _cursorY = y; } + + /** + * Query the mouse position in physical coordinates. */ - virtual void initGL(); + void getMousePosition(int16 &x, int16 &y) const { x = _cursorX; y = _cursorY; } /** - * Creates and refreshs OpenGL textures. + * Set up the mouse position for the (event) system. + * + * @param x X coordinate in physical coordinates. + * @param y Y coordinate in physical coordinates. */ - virtual void loadTextures(); + virtual void setInternalMousePosition(int x, int y) = 0; +private: // - // GFX and video + // Transaction support // - enum { - kTransactionNone = 0, - kTransactionActive = 1, - kTransactionRollback = 2 - }; - - struct TransactionDetails { - bool sizeChanged; - bool needRefresh; - bool needUpdatescreen; - bool filterChanged; + struct VideoState { + VideoState() : valid(false), gameWidth(0), gameHeight(0), #ifdef USE_RGB_COLOR - bool formatChanged; + gameFormat(), #endif - }; - TransactionDetails _transactionDetails; - int _transactionMode; - - struct VideoState { - bool setup; + aspectRatioCorrection(false), graphicsMode(GFX_LINEAR) { + } - bool fullscreen; + bool valid; - int mode; - int scaleFactor; - bool antialiasing; + uint gameWidth, gameHeight; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat gameFormat; +#endif bool aspectRatioCorrection; + int graphicsMode; - int screenWidth, screenHeight; - int overlayWidth, overlayHeight; - int hardwareWidth, hardwareHeight; + bool operator==(const VideoState &right) { + return gameWidth == right.gameWidth && gameHeight == right.gameHeight #ifdef USE_RGB_COLOR - Graphics::PixelFormat format; + && gameFormat == right.gameFormat #endif + && aspectRatioCorrection == right.aspectRatioCorrection + && graphicsMode == right.graphicsMode; + } + + bool operator!=(const VideoState &right) { + return !(*this == right); + } }; - VideoState _videoMode, _oldVideoMode; /** - * Sets the OpenGL texture format for the given pixel format. If format is not support will raise an error. + * The currently setup video state. */ - virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &intFormat, GLenum &glFormat, GLenum &type); + VideoState _currentState; - virtual void internUpdateScreen(); - virtual bool loadGFXMode(); - virtual void unloadGFXMode(); + /** + * The old video state used when doing a transaction rollback. + */ + VideoState _oldState; +protected: + enum TransactionMode { + kTransactionNone = 0, + kTransactionActive = 1, + kTransactionRollback = 2 + }; + + TransactionMode getTransactionMode() const { return _transactionMode; } + +private: /** - * Setup the fullscreen mode state. + * The current transaction mode. */ - void setFullscreenMode(bool enable); + TransactionMode _transactionMode; /** - * Query the fullscreen state. + * The current screen change ID. */ - inline bool getFullscreenMode() const { return _videoMode.fullscreen; } + int _screenChangeID; +protected: /** - * Set the scale factor. + * Set up the requested video mode. This takes parameters which describe + * what resolution the game screen requests (this is possibly aspect ratio + * corrected!). * - * This can only be used in a GFX transaction. + * A sub-class should take these parameters as hints. It might very well + * set up a mode which it thinks suites the situation best. * - * @param newScale New scale factor. + * @parma requestedWidth This is the requested actual game screen width. + * @param requestedHeight This is the requested actual game screen height. + * @param format This is the requested pixel format of the virtual game screen. + * @return true on success, false otherwise */ - void setScale(int newScale); + virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0; /** - * Query the scale factor. + * Save a screenshot of the full display as BMP to the given file. This + * uses Common::DumpFile for writing the screenshot. + * + * @param filename The output filename. */ - inline int getScale() const { return _videoMode.scaleFactor; } + void saveScreenshot(const Common::String &filename) const; + +private: + // + // OpenGL utilities + // /** - * Toggle the antialiasing state of the current video mode. + * Try to determine the internal parameters for a given pixel format. * - * This can only be used in a GFX transaction. + * @return true when the format can be used, false otherwise. + */ + bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const; + + // + // Actual hardware screen + // + + /** + * The width of the physical output. + */ + uint _outputScreenWidth; + + /** + * The height of the physical output. + */ + uint _outputScreenHeight; + + /** + * @return The desired aspect of the game screen. + */ + frac_t getDesiredGameScreenAspect() const; + + /** + * Recalculates the area used to display the game screen. */ - void toggleAntialiasing(); + void recalculateDisplayArea(); /** - * Query the antialiasing state. + * The X coordinate of the game screen. */ - inline bool getAntialiasingState() const { return _videoMode.antialiasing; } + uint _displayX; - // Drawing coordinates for the current display mode and scale - int _displayX; - int _displayY; - int _displayWidth; - int _displayHeight; + /** + * The Y coordinate of the game screen. + */ + uint _displayY; - virtual const char *getCurrentModeName(); + /** + * The width of the game screen in physical coordinates. + */ + uint _displayWidth; - virtual void calculateDisplaySize(int &width, int &height); - virtual void refreshDisplaySize(); + /** + * The height of the game screen in physical coordinates. + */ + uint _displayHeight; - uint getAspectRatio() const; + /** + * The default pixel format of the backend. + */ + Graphics::PixelFormat _defaultFormat; - void setFormatIsBGR(bool isBGR) { _formatBGR = isBGR; } - bool _formatBGR; + /** + * The default pixel format with an alpha channel. + */ + Graphics::PixelFormat _defaultFormatAlpha; // // Game screen // - GLTexture *_gameTexture; - Graphics::Surface _screenData; - int _screenChangeCount; - bool _screenNeedsRedraw; - Common::Rect _screenDirtyRect; -#ifdef USE_RGB_COLOR - Graphics::PixelFormat _screenFormat; -#endif - byte *_gamePalette; + /** + * The virtual game screen. + */ + Texture *_gameScreen; - virtual void refreshGameScreen(); + /** + * The game palette if in CLUT8 mode. + */ + byte _gamePalette[3 * 256]; - // Shake mode - int _shakePos; + /** + * The offset by which the screen is moved vertically. + */ + int _gameScreenShakeOffset; // // Overlay // - GLTexture *_overlayTexture; - Graphics::Surface _overlayData; - Graphics::PixelFormat _overlayFormat; - bool _overlayVisible; - bool _overlayNeedsRedraw; - Common::Rect _overlayDirtyRect; - virtual void refreshOverlay(); + /** + * The overlay screen. + */ + Texture *_overlay; + + /** + * Whether the overlay is visible or not. + */ + bool _overlayVisible; // - // Mouse + // Cursor // - struct MousePos { - // The mouse position in hardware screen coordinates. - int16 x, y; - // The size and hotspot of the original cursor image. - int16 w, h; - int16 hotX, hotY; + /** + * Set up the correct cursor palette. + */ + void updateCursorPalette(); - // The size and hotspot of the scaled cursor, in real coordinates. - int16 rW, rH; - int16 rHotX, rHotY; + /** + * The cursor image. + */ + Texture *_cursor; - // The size and hotspot of the scaled cursor, in game coordinates. - int16 vW, vH; - int16 vHotX, vHotY; + /** + * X coordinate of the cursor in phyiscal coordinates. + */ + uint _cursorX; - MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0), - rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0), - vHotX(0), vHotY(0) {} - }; + /** + * Y coordinate of the cursor in physical coordinates. + */ + uint _cursorY; - GLTexture *_cursorTexture; - Graphics::Surface _cursorData; - Graphics::PixelFormat _cursorFormat; - byte *_cursorPalette; - bool _cursorPaletteDisabled; - MousePos _cursorState; - bool _cursorVisible; + /** + * The X offset for the cursor hotspot in unscaled coordinates. + */ + uint _cursorHotspotX; + + /** + * The Y offset for the cursor hotspot in unscaled coordinates. + */ + uint _cursorHotspotY; + + /** + * Recalculate the cursor scaling. Scaling is always done according to + * the game screen. + */ + void recalculateCursorScaling(); + + /** + * The X offset for the cursor hotspot in scaled coordinates. + */ + uint _cursorHotspotXScaled; + + /** + * The Y offset for the cursor hotspot in scaled coordinates. + */ + uint _cursorHotspotYScaled; + + /** + * The width of the cursor scaled coordinates. + */ + uint _cursorWidthScaled; + + /** + * The height of the cursor scaled coordinates. + */ + uint _cursorHeightScaled; + + /** + * The key color. + */ uint32 _cursorKeyColor; - bool _cursorDontScale; - bool _cursorNeedsRedraw; /** - * Set up the mouse position for graphics output. - * - * @param x X coordinate in native coordinates. - * @param y Y coordinate in native coordinates. + * Whether the cursor is actually visible. */ - void setMousePosition(int x, int y) { _cursorState.x = x; _cursorState.y = y; } + bool _cursorVisible; - virtual void refreshCursor(); - virtual void refreshCursorScale(); + /** + * Whether no cursor scaling should be applied. + */ + bool _cursorDontScale; /** - * Set up the mouse position for the (event) system. - * - * @param x X coordinate in native coordinates. - * @param y Y coordinate in native coordinates. + * Whether the special cursor palette is enabled. */ - virtual void setInternalMousePosition(int x, int y) = 0; + bool _cursorPaletteEnabled; /** - * Adjusts hardware screen coordinates to either overlay or game screen - * coordinates depending on whether the overlay is visible or not. - * - * @param x X coordinate of the mouse position. - * @param y Y coordinate of the mouse position. + * The special cursor palette in case enabled. */ - virtual void adjustMousePosition(int16 &x, int16 &y); + byte _cursorPalette[3 * 256]; +#ifdef USE_OSD // - // Misc + // OSD // - virtual bool saveScreenshot(const char *filename); - -#ifdef USE_OSD +protected: /** * Returns the font used for on screen display */ virtual const Graphics::Font *getFontOSD(); +private: /** - * Update the OSD texture / surface. + * The OSD's contents. */ - void updateOSD(); + Texture *_osd; /** - * The OSD contents. + * Current opacity level of the OSD. */ - Common::Array<Common::String> _osdLines; - - GLTexture *_osdTexture; - Graphics::Surface _osdSurface; uint8 _osdAlpha; + + /** + * When fading the OSD has started. + */ uint32 _osdFadeStartTime; - bool _requireOSDUpdate; + + /** + * Mutex to allow displayMessageOnOSD to be used from the audio thread. + */ + Common::Mutex _osdMutex; + enum { kOSDFadeOutDelay = 2 * 1000, kOSDFadeOutDuration = 500, @@ -348,4 +474,6 @@ protected: #endif }; +} // End of namespace OpenGL + #endif diff --git a/backends/graphics/opengl/glerrorcheck.cpp b/backends/graphics/opengl/opengl-sys.h index 439593577d..a3524b28d2 100644 --- a/backends/graphics/opengl/glerrorcheck.cpp +++ b/backends/graphics/opengl/opengl-sys.h @@ -8,25 +8,25 @@ * 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 + * 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. * */ -#include "common/scummsys.h" +#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_H +#define BACKENDS_GRAPHICS_OPENGL_OPENGL_H -#if defined(DEBUG) && defined(USE_OPENGL) +// The purpose of this header is to include the OpenGL headers in an uniform +// fashion. A notable example for a non standard port is the Tizen port. -#include "backends/graphics/opengl/glerrorcheck.h" -#include "common/textconsole.h" -#include "common/str.h" +#include "common/scummsys.h" #ifdef WIN32 #if defined(ARRAYSIZE) && !defined(_WINDOWS_) @@ -37,31 +37,21 @@ #undef ARRAYSIZE #endif -#if defined(USE_GLES) +// HACK: In case common/util.h has been included already we need to make sure +// to define ARRAYSIZE again in case of Windows. +#if !defined(ARRAYSIZE) && defined(COMMON_UTIL_H) +#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0]))) +#endif + +#if defined(TIZEN) +#include <FGraphicsOpengl.h> +using namespace Tizen::Graphics::Opengl; +#elif defined(USE_GLES) #include <GLES/gl.h> -#elif defined(MACOSX) -#include <OpenGL/gl.h> +#elif defined(SDL_BACKEND) +#include <SDL_opengl.h> #else #include <GL/gl.h> #endif -static Common::String getGlErrStr(GLenum error) { - switch (error) { - case GL_NO_ERROR: return "GL_NO_ERROR"; - case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; - case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; - case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; - case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; - case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; - } - - return Common::String::format("(Unknown GL error code 0x%x)", error); -} - -void checkGlError(const char *file, int line) { - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - warning("%s:%d: GL error: %s", file, line, getGlErrStr(error).c_str()); -} - #endif diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp new file mode 100644 index 0000000000..8f17ed7eeb --- /dev/null +++ b/backends/graphics/opengl/texture.cpp @@ -0,0 +1,371 @@ +/* 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. + * + */ + +#include "backends/graphics/opengl/texture.h" +#include "backends/graphics/opengl/extensions.h" +#include "backends/graphics/opengl/debug.h" + +#include "common/rect.h" +#include "common/textconsole.h" + +namespace OpenGL { + +static GLuint nextHigher2(GLuint v) { + if (v == 0) + return 1; + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return ++v; +} + +GLint Texture::_maxTextureSize = 0; + +void Texture::queryTextureInformation() { + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize); + debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); +} + +Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) + : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), _format(format), _glFilter(GL_NEAREST), + _glTexture(0), _textureData(), _userPixelData(), _allDirty(false) { + recreateInternalTexture(); +} + +Texture::~Texture() { + releaseInternalTexture(); + _textureData.free(); +} + +void Texture::releaseInternalTexture() { + GLCALL(glDeleteTextures(1, &_glTexture)); + _glTexture = 0; +} + +void Texture::recreateInternalTexture() { + // Get a new texture name. + GLCALL(glGenTextures(1, &_glTexture)); + + // Set up all texture parameters. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + 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)); + + // In case there is an actual texture setup we reinitialize it. + if (_textureData.getPixels()) { + // Allocate storage for OpenGL texture. + GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, + _textureData.h, 0, _glFormat, _glType, NULL)); + + // Mark dirts such that it will be completely refreshed the next time. + flagDirty(); + } +} + +void Texture::enableLinearFiltering(bool enable) { + if (enable) { + _glFilter = GL_LINEAR; + } else { + _glFilter = GL_NEAREST; + } + + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); +} + +void Texture::allocate(uint width, uint height) { + uint texWidth = width, texHeight = height; + if (!g_extNPOTSupported) { + texWidth = nextHigher2(texWidth); + texHeight = nextHigher2(texHeight); + } + + // In case the needed texture dimension changed we will reinitialize the + // texture. + if (texWidth != _textureData.w || texHeight != _textureData.h) { + // Create a buffer for the texture data. + _textureData.create(texWidth, texHeight, _format); + + // Set the texture. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + // Allocate storage for OpenGL texture. + GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, + _textureData.h, 0, _glFormat, _glType, NULL)); + } + + // Create a sub-buffer for raw access. + _userPixelData = _textureData.getSubArea(Common::Rect(width, height)); +} + +void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcPtr, uint srcPitch) { + Graphics::Surface *dstSurf = getSurface(); + assert(x + w <= dstSurf->w); + assert(y + h <= dstSurf->h); + + // *sigh* Common::Rect::extend behaves unexpected whenever one of the two + // parameters is an empty rect. Thus, we check whether the current dirty + // area is valid. In case it is not we simply use the parameters as new + // dirty area. Otherwise, we simply call extend. + if (_dirtyArea.isEmpty()) { + _dirtyArea = Common::Rect(x, y, x + w, y + h); + } else { + _dirtyArea.extend(Common::Rect(x, y, x + w, y + h)); + } + + const byte *src = (const byte *)srcPtr; + byte *dst = (byte *)dstSurf->getBasePtr(x, y); + const uint pitch = dstSurf->pitch; + const uint bytesPerPixel = dstSurf->format.bytesPerPixel; + + if (srcPitch == pitch && x == 0 && w == dstSurf->w) { + memcpy(dst, src, h * pitch); + } else { + while (h-- > 0) { + memcpy(dst, src, w * bytesPerPixel); + dst += pitch; + src += srcPitch; + } + } +} + +void Texture::fill(uint32 color) { + Graphics::Surface *dst = getSurface(); + dst->fillRect(Common::Rect(dst->w, dst->h), color); + + flagDirty(); +} + +void Texture::draw(GLuint x, GLuint y, GLuint w, GLuint h) { + // Only do any processing when the Texture is initialized. + if (!_textureData.getPixels()) { + return; + } + + // First update any potentional changes. + updateTexture(); + + // Set the texture. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + // Calculate the texture rect that will be drawn. + const GLfloat texWidth = (GLfloat)_userPixelData.w / _textureData.w; + const GLfloat texHeight = (GLfloat)_userPixelData.h / _textureData.h; + const GLfloat texcoords[4*2] = { + 0, 0, + texWidth, 0, + 0, texHeight, + texWidth, texHeight + }; + GLCALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); + + // Calculate the screen rect where the texture will be drawn. + const GLshort vertices[4*2] = { + (GLshort)x, (GLshort)y, + (GLshort)(x + w), (GLshort)y, + (GLshort)x, (GLshort)(y + h), + (GLshort)(x + w), (GLshort)(y + h) + }; + GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices)); + + // Draw the texture to the screen buffer. + GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); +} + +void Texture::updateTexture() { + if (!isDirty()) { + return; + } + + Common::Rect dirtyArea = getDirtyArea(); + + // In case we use linear filtering we might need to duplicate the last + // pixel row/column to avoid glitches with filtering. + if (_glFilter == GL_LINEAR) { + if (dirtyArea.right == _userPixelData.w && _userPixelData.w != _textureData.w) { + uint height = dirtyArea.height(); + + const byte *src = (const byte *)_textureData.getBasePtr(_userPixelData.w - 1, dirtyArea.top); + byte *dst = (byte *)_textureData.getBasePtr(_userPixelData.w, dirtyArea.top); + + while (height-- > 0) { + memcpy(dst, src, _textureData.format.bytesPerPixel); + dst += _textureData.pitch; + src += _textureData.pitch; + } + + // Extend the dirty area. + ++dirtyArea.right; + } + + if (dirtyArea.bottom == _userPixelData.h && _userPixelData.h != _textureData.h) { + const byte *src = (const byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h - 1); + byte *dst = (byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h); + memcpy(dst, src, dirtyArea.width() * _textureData.format.bytesPerPixel); + + // Extend the dirty area. + ++dirtyArea.bottom; + } + } + + // Set the texture. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + // Update the actual texture. + // Although we keep track of the dirty part of the texture buffer we + // cannot take advantage of the left/right boundries here because it is + // not possible to specify a pitch to glTexSubImage2D. To be precise, with + // plain OpenGL we could set GL_UNPACK_ROW_LENGTH to achieve this. However, + // OpenGL ES 1.0 does not support GL_UNPACK_ROW_LENGTH. Thus, we are left + // with the following options: + // + // 1) (As we do right now) Simply always update the whole texture lines of + // rect changed. This is simplest to implement. In case performance is + // really an issue we can think of switching to another method. + // + // 2) Copy the dirty rect to a temporary buffer and upload that by using + // glTexSubImage2D. This is what the Android backend does. It is more + // complicated though. + // + // 3) Use glTexSubImage2D per line changed. This is what the old OpenGL + // graphics manager did but it is much slower! Thus, we do not use it. + GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dirtyArea.top, _textureData.w, dirtyArea.height(), + _glFormat, _glType, _textureData.getBasePtr(0, dirtyArea.top))); + + // We should have handled everything, thus not dirty anymore. + clearDirty(); +} + +Common::Rect Texture::getDirtyArea() const { + if (_allDirty) { + return Common::Rect(_userPixelData.w, _userPixelData.h); + } else { + return _dirtyArea; + } +} + +TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) + : Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) { + memset(_palette, 0, sizeof(byte) * format.bytesPerPixel); +} + +TextureCLUT8::~TextureCLUT8() { + delete[] _palette; + _palette = nullptr; + _clut8Data.free(); +} + +void TextureCLUT8::allocate(uint width, uint height) { + Texture::allocate(width, height); + + // We only need to reinitialize our CLUT8 surface when the output size + // changed. + if (width == _clut8Data.w && height == _clut8Data.h) { + return; + } + + _clut8Data.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); +} + +Graphics::PixelFormat TextureCLUT8::getFormat() const { + return Graphics::PixelFormat::createFormatCLUT8(); +} + +namespace { +template<typename ColorType> +inline void convertPalette(ColorType *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) { + while (colors-- > 0) { + *dst++ = format.RGBToColor(src[0], src[1], src[2]); + src += 3; + } +} +} // End of anonymous namespace + +void TextureCLUT8::setPalette(uint start, uint colors, const byte *palData) { + const Graphics::PixelFormat &hardwareFormat = getHardwareFormat(); + + if (hardwareFormat.bytesPerPixel == 2) { + convertPalette<uint16>((uint16 *)_palette + start, palData, colors, hardwareFormat); + } else if (hardwareFormat.bytesPerPixel == 4) { + convertPalette<uint32>((uint32 *)_palette + start, palData, colors, hardwareFormat); + } else { + warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", hardwareFormat.bytesPerPixel); + } + + // A palette changes means we need to refresh the whole surface. + flagDirty(); +} + +namespace { +template<typename PixelType> +inline void doPaletteLookUp(PixelType *dst, const byte *src, uint width, uint height, uint dstPitch, uint srcPitch, const PixelType *palette) { + uint srcAdd = srcPitch - width; + uint dstAdd = dstPitch - width * sizeof(PixelType); + + while (height-- > 0) { + for (uint x = width; x > 0; --x) { + *dst++ = palette[*src++]; + } + + dst = (PixelType *)((byte *)dst + dstAdd); + src += srcAdd; + } +} +} // End of anonymous namespace + +void TextureCLUT8::updateTexture() { + if (!isDirty()) { + return; + } + + // Do the palette look up + Graphics::Surface *outSurf = Texture::getSurface(); + + Common::Rect dirtyArea = getDirtyArea(); + + if (outSurf->format.bytesPerPixel == 2) { + doPaletteLookUp<uint16>((uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top), + (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top), + dirtyArea.width(), dirtyArea.height(), + outSurf->pitch, _clut8Data.pitch, (const uint16 *)_palette); + } else if (outSurf->format.bytesPerPixel == 4) { + doPaletteLookUp<uint32>((uint32 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top), + (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top), + dirtyArea.width(), dirtyArea.height(), + outSurf->pitch, _clut8Data.pitch, (const uint32 *)_palette); + } else { + warning("TextureCLUT8::updateTexture: Unsupported pixel depth: %d", outSurf->format.bytesPerPixel); + } + + // Do generic handling of updating the texture. + Texture::updateTexture(); +} + +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h new file mode 100644 index 0000000000..e28d980de4 --- /dev/null +++ b/backends/graphics/opengl/texture.h @@ -0,0 +1,175 @@ +/* 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_OPENGL_TEXTURE_H +#define BACKENDS_GRAPHICS_OPENGL_TEXTURE_H + +#include "backends/graphics/opengl/opengl-sys.h" + +#include "graphics/pixelformat.h" +#include "graphics/surface.h" + +#include "common/rect.h" + +namespace OpenGL { + +/** + * An OpenGL texture wrapper. It automatically takes care of all OpenGL + * texture handling issues and also provides access to the texture data. + */ +class Texture { +public: + /** + * Create a new texture with the specific internal format. + * + * @param glIntFormat The internal format to use. + * @param glFormat The input format. + * @param glType The input type. + * @param format The format used for the texture input. + */ + Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format); + virtual ~Texture(); + + /** + * Destroy the OpenGL texture name. + */ + void releaseInternalTexture(); + + /** + * Create the OpenGL texture name and flag the whole texture as dirty. + */ + void recreateInternalTexture(); + + /** + * Enable or disable linear texture filtering. + * + * @param enable true to enable and false to disable. + */ + void enableLinearFiltering(bool enable); + + /** + * Allocate texture space for the desired dimensions. This wraps any + * handling of requirements for POT textures. + * + * @param width The desired logical width. + * @param height The desired logical height. + */ + virtual void allocate(uint width, uint height); + + void copyRectToTexture(uint x, uint y, uint w, uint h, const void *src, uint srcPitch); + + void fill(uint32 color); + + void draw(GLuint x, GLuint y, GLuint w, GLuint h); + + void flagDirty() { _allDirty = true; } + bool isDirty() const { return _allDirty || !_dirtyArea.isEmpty(); } + + uint getWidth() const { return _userPixelData.w; } + uint getHeight() const { return _userPixelData.h; } + + /** + * @return The hardware format of the texture data. + */ + const Graphics::PixelFormat &getHardwareFormat() const { return _format; } + + /** + * @return The logical format of the texture data. + */ + virtual Graphics::PixelFormat getFormat() const { return _format; } + + virtual Graphics::Surface *getSurface() { return &_userPixelData; } + virtual const Graphics::Surface *getSurface() const { return &_userPixelData; } + + /** + * @return Whether the texture data is using a palette. + */ + virtual bool hasPalette() const { return false; } + + virtual void setPalette(uint start, uint colors, const byte *palData) {} + + virtual void *getPalette() { return 0; } + virtual const void *getPalette() const { return 0; } + + /** + * Query texture related OpenGL information from the context. This only + * queries the maximum texture size for now. + */ + static void queryTextureInformation(); + + /** + * @return Return the maximum texture dimensions supported. + */ + static GLint getMaximumTextureSize() { return _maxTextureSize; } +protected: + virtual void updateTexture(); + + Common::Rect getDirtyArea() const; +private: + const GLenum _glIntFormat; + const GLenum _glFormat; + const GLenum _glType; + const Graphics::PixelFormat _format; + + GLint _glFilter; + GLuint _glTexture; + + Graphics::Surface _textureData; + Graphics::Surface _userPixelData; + + bool _allDirty; + Common::Rect _dirtyArea; + void clearDirty() { _allDirty = false; _dirtyArea = Common::Rect(); } + + static GLint _maxTextureSize; +}; + +class TextureCLUT8 : public Texture { +public: + TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format); + virtual ~TextureCLUT8(); + + virtual void allocate(uint width, uint height); + + virtual Graphics::PixelFormat getFormat() const; + + virtual bool hasPalette() const { return true; } + + virtual void setPalette(uint start, uint colors, const byte *palData); + + virtual void *getPalette() { return _palette; } + virtual const void *getPalette() const { return _palette; } + + virtual Graphics::Surface *getSurface() { return &_clut8Data; } + virtual const Graphics::Surface *getSurface() const { return &_clut8Data; } + +protected: + virtual void updateTexture(); + +private: + Graphics::Surface _clut8Data; + byte *_palette; +}; + +} // End of namespace OpenGL + +#endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index c5605cae87..e39cd35870 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -8,496 +8,353 @@ * 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. * */ -#include "common/scummsys.h" - -#if defined(SDL_BACKEND) && defined(USE_OPENGL) - #include "backends/graphics/openglsdl/openglsdl-graphics.h" -#include "backends/platform/sdl/sdl.h" -#include "common/config-manager.h" + #include "common/textconsole.h" +#include "common/config-manager.h" +#ifdef USE_OSD #include "common/translation.h" +#endif -OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource) - : - SdlGraphicsManager(eventSource), - _hwscreen(0), - _screenResized(false), - _activeFullscreenMode(-2), - _lastFullscreenModeWidth(0), - _lastFullscreenModeHeight(0), - _desktopWidth(0), - _desktopHeight(0), - _ignoreResizeFrames(0) { - - // Initialize SDL video subsystem - if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); +OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource) + : SdlGraphicsManager(eventSource), _lastVideoModeLoad(0), _hwScreen(nullptr), _lastRequestedWidth(0), _lastRequestedHeight(0), + _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0), + _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) { + // Setup OpenGL attributes for SDL + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + // Retrieve a list of working fullscreen modes + const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); + if (availableModes != (void *)-1) { + for (;*availableModes; ++availableModes) { + const SDL_Rect *mode = *availableModes; + + _fullscreenVideoModes.push_back(VideoMode(mode->w, mode->h)); + } + + // Sort the modes in ascending order. + Common::sort(_fullscreenVideoModes.begin(), _fullscreenVideoModes.end()); } - // This is also called in initSDL(), but initializing graphics - // may reset it. - SDL_EnableUNICODE(1); - - // Disable OS cursor - SDL_ShowCursor(SDL_DISABLE); - - // Get desktop resolution - // TODO: In case the OpenGL manager is created *after* a plain SDL manager - // has been used, this will return the last setup graphics mode rather - // than the desktop resolution. We should really look into a way to - // properly retrieve the desktop resolution. - const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); - if (videoInfo->current_w > 0 && videoInfo->current_h > 0) { - _desktopWidth = videoInfo->current_w; - _desktopHeight = videoInfo->current_h; + // In case SDL is fine with every mode we will force the desktop mode. + // TODO? We could also try to add some default resolutions here. + if (_fullscreenVideoModes.empty() && desktopWidth && desktopHeight) { + _fullscreenVideoModes.push_back(VideoMode(desktopWidth, desktopHeight)); } - if (ConfMan.hasKey("last_fullscreen_mode_width") && ConfMan.hasKey("last_fullscreen_mode_height")) { - _lastFullscreenModeWidth = ConfMan.getInt("last_fullscreen_mode_width"); - _lastFullscreenModeHeight = ConfMan.getInt("last_fullscreen_mode_height"); + // Get information about display sizes from the previous runs. + if (ConfMan.hasKey("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain) && ConfMan.hasKey("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain)) { + _desiredFullscreenWidth = ConfMan.getInt("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain); + _desiredFullscreenHeight = ConfMan.getInt("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain); + } else { + // Use the desktop resolutions when no previous default has been setup. + _desiredFullscreenWidth = desktopWidth; + _desiredFullscreenHeight = desktopHeight; } } OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { - // Unregister the event observer - if (g_system->getEventManager()->getEventDispatcher() != NULL) - g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); } -void OpenGLSdlGraphicsManager::initEventObserver() { +void OpenGLSdlGraphicsManager::activateManager() { + OpenGLGraphicsManager::activateManager(); + initEventSource(); + // Register the graphics manager as a event observer g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); } +void OpenGLSdlGraphicsManager::deactivateManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher()) { + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + } + + deinitEventSource(); + OpenGLGraphicsManager::deactivateManager(); +} + bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { - return - (f == OSystem::kFeatureFullscreenMode) || - (f == OSystem::kFeatureIconifyWindow) || - OpenGLGraphicsManager::hasFeature(f); + switch (f) { + case OSystem::kFeatureFullscreenMode: + case OSystem::kFeatureIconifyWindow: + return true; + + default: + return OpenGLGraphicsManager::hasFeature(f); + } } void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { switch (f) { + case OSystem::kFeatureFullscreenMode: + assert(getTransactionMode() != kTransactionNone); + _wantsFullScreen = enable; + // When we switch to windowed mode we will ignore resize events. This + // avoids bad resizes to the (former) fullscreen resolution. + if (!enable) { + _ignoreResizeEvents = 10; + } + break; + case OSystem::kFeatureIconifyWindow: - if (enable) + if (enable) { SDL_WM_IconifyWindow(); + } break; + default: OpenGLGraphicsManager::setFeatureState(f, enable); } } -#ifdef USE_RGB_COLOR - -Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const { - assert(!_supportedFormats.empty()); - return _supportedFormats; -} - -void OpenGLSdlGraphicsManager::detectSupportedFormats() { - - // Clear old list - _supportedFormats.clear(); - - // Some tables with standard formats that we always list - // as "supported". If frontend code tries to use one of - // these, we will perform the necessary format - // conversion in the background. Of course this incurs a - // performance hit, but on desktop ports this should not - // matter. We still push the currently active format to - // the front, so if frontend code just uses the first - // available format, it will get one that is "cheap" to - // use. - const Graphics::PixelFormat RGBList[] = { -#if defined(ENABLE_32BIT) - Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), // RGBA8888 -#ifndef USE_GLES - Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), // ARGB8888 -#endif - Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), // RGB888 -#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 -#endif - }; -#ifndef USE_GLES - const Graphics::PixelFormat BGRList[] = { -#ifdef ENABLE_32BIT - Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), // ABGR8888 - Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0), // BGRA8888 - Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), // BGR888 -#endif - Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0), // BGR565 - Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0), // BGRA5551 - Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12), // ABGR4444 - Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0) // BGRA4444 - }; -#endif - - Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); - if (_hwscreen) { - // Get our currently set hardware format - format = Graphics::PixelFormat(_hwscreen->format->BytesPerPixel, - 8 - _hwscreen->format->Rloss, 8 - _hwscreen->format->Gloss, - 8 - _hwscreen->format->Bloss, 8 - _hwscreen->format->Aloss, - _hwscreen->format->Rshift, _hwscreen->format->Gshift, - _hwscreen->format->Bshift, _hwscreen->format->Ashift); - - // Workaround to SDL not providing an accurate Aloss value on Mac OS X. - if (_hwscreen->format->Amask == 0) - format.aLoss = 8; - - // Push it first, as the prefered format if available - for (int i = 0; i < ARRAYSIZE(RGBList); i++) { - if (RGBList[i] == format) { - _supportedFormats.push_back(format); - break; - } - } -#ifndef USE_GLES - for (int i = 0; i < ARRAYSIZE(BGRList); i++) { - if (BGRList[i] == format) { - _supportedFormats.push_back(format); - break; - } +bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + if (_hwScreen) { + return (_hwScreen->flags & SDL_FULLSCREEN) != 0; + } else { + return _wantsFullScreen; } -#endif - } - // Push some RGB formats - for (int i = 0; i < ARRAYSIZE(RGBList); i++) { - if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) - continue; - if (RGBList[i] != format) - _supportedFormats.push_back(RGBList[i]); - } -#ifndef USE_GLES - // Push some BGR formats - for (int i = 0; i < ARRAYSIZE(BGRList); i++) { - if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel)) - continue; - if (BGRList[i] != format) - _supportedFormats.push_back(BGRList[i]); + default: + return OpenGLGraphicsManager::getFeatureState(f); } -#endif - _supportedFormats.push_back(Graphics::PixelFormat::createFormatCLUT8()); } -#endif +bool OpenGLSdlGraphicsManager::setGraphicsMode(int mode) { + // HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This + // assures that the launcher (which requests 320x200) has a reasonable + // size. It also makes small games have a reasonable size (i.e. at least + // 640x400). We follow the same logic here until we have a better way to + // give hints to our backend for that. + _graphicsScale = 2; -void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { - SDL_WarpMouse(x, y); + return OpenGLGraphicsManager::setGraphicsMode(mode); } -void OpenGLSdlGraphicsManager::updateScreen() { - if (_ignoreResizeFrames) - _ignoreResizeFrames -= 1; +void OpenGLSdlGraphicsManager::resetGraphicsScale() { + OpenGLGraphicsManager::resetGraphicsScale(); - OpenGLGraphicsManager::updateScreen(); + // HACK: See OpenGLSdlGraphicsManager::setGraphicsMode. + _graphicsScale = 1; } -// -// Intern -// - -bool OpenGLSdlGraphicsManager::setupFullscreenMode() { - SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL); - - // SDL_ListModes() returns -1 in case any dimension is okay. In that - // case we'll reuse the current desktop resolution for fullscreen. - if (availableModes == (void *)-1) { - _videoMode.hardwareWidth = _desktopWidth; - _videoMode.hardwareHeight = _desktopHeight; - _activeFullscreenMode = -2; - return true; - } - - // If -2, autodetect the fullscreen mode - // 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 (_activeFullscreenMode == -2) { - // Desktop resolution - int desktopModeIndex = -1; - - // Best metric mode - const SDL_Rect *bestMode = availableModes[0]; - int bestModeIndex = 0; - uint bestMetric = (uint)-1; - - // Iterate over all available fullscreen modes - for (int i = 0; const SDL_Rect *mode = availableModes[i]; i++) { - // Try to setup the last used fullscreen mode - if (mode->w == _lastFullscreenModeWidth && mode->h == _lastFullscreenModeHeight) { - _videoMode.hardwareWidth = _lastFullscreenModeWidth; - _videoMode.hardwareHeight = _lastFullscreenModeHeight; - _activeFullscreenMode = i; - return true; - } +#ifdef USE_RGB_COLOR +Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const { + Common::List<Graphics::PixelFormat> formats; - if (mode->w == _desktopWidth && mode->h == _desktopHeight) - desktopModeIndex = i; + // RGBA8888 + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); + // RGB565 + formats.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); + // RGBA5551 + formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); + // RGBA4444 + formats.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)); - if (mode->w < _videoMode.overlayWidth) - continue; - if (mode->h < _videoMode.overlayHeight) - continue; +#ifndef USE_GLES + // ARGB8888, this should not be here, but Sword25 requires it. :-/ + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); - uint metric = mode->w * mode->h - _videoMode.overlayWidth * _videoMode.overlayHeight; - if (metric < bestMetric) { - bestMode = mode; - bestMetric = metric; - bestModeIndex = i; - } - } + // RGB555, this is used by SCUMM HE 16 bit games. + formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); +#endif - if (desktopModeIndex >= 0) { - _videoMode.hardwareWidth = _desktopWidth; - _videoMode.hardwareHeight = _desktopHeight; + formats.push_back(Graphics::PixelFormat::createFormatCLUT8()); - _activeFullscreenMode = desktopModeIndex; - return true; - } else if (bestMode) { - _videoMode.hardwareWidth = bestMode->w; - _videoMode.hardwareHeight = bestMode->h; + return formats; +} +#endif - _activeFullscreenMode = bestModeIndex; - return true; - } - } else { - // Use last fullscreen mode if looping backwards from the first mode - if (_activeFullscreenMode == -1) { - do { - _activeFullscreenMode++; - } while(availableModes[_activeFullscreenMode]); - _activeFullscreenMode--; - } +void OpenGLSdlGraphicsManager::updateScreen() { + if (_ignoreResizeEvents) { + --_ignoreResizeEvents; + } - // Use first fullscreen mode if looping from last mode - if (!availableModes[_activeFullscreenMode]) - _activeFullscreenMode = 0; + OpenGLGraphicsManager::updateScreen(); - // Check if the fullscreen mode is valid - if (availableModes[_activeFullscreenMode]) { - _videoMode.hardwareWidth = availableModes[_activeFullscreenMode]->w; - _videoMode.hardwareHeight = availableModes[_activeFullscreenMode]->h; - return true; - } - } + // Swap OpenGL buffers + SDL_GL_SwapBuffers(); +} - // Could not find any suiting fullscreen mode, return false. - return false; +void OpenGLSdlGraphicsManager::notifyVideoExpose() { } -bool OpenGLSdlGraphicsManager::loadGFXMode() { - // If the screen was resized, do not change its size - if (!_screenResized) { - const int scaleFactor = getScale(); - _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * scaleFactor; - _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * scaleFactor; - - // The only modes where we need to adapt the aspect ratio are 320x200 - // and 640x400. That is since our aspect ratio correction in fact is - // only used to ensure that the original pixel size aspect for these - // modes is used. - // (Non-square pixels on old monitors vs square pixel on new ones). - if (_videoMode.aspectRatioCorrection) { - if (_videoMode.screenWidth == 320 && _videoMode.screenHeight == 200) - _videoMode.overlayHeight = _videoMode.hardwareHeight = 240 * scaleFactor; - else if (_videoMode.screenWidth == 640 && _videoMode.screenHeight == 400) - _videoMode.overlayHeight = _videoMode.hardwareHeight = 480 * scaleFactor; +void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) { + if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) { + // We save that we handled a resize event here. We need to know this + // so we do not overwrite the users requested window size whenever we + // switch aspect ratio or similar. + _gotResize = true; + if (!setupMode(width, height)) { + warning("OpenGLSdlGraphicsManager::notifyResize: Resize failed ('%s')", SDL_GetError()); + g_system->quit(); } } +} - _screenResized = false; +void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { + adjustMousePosition(point.x, point.y); +} - // Setup OpenGL attributes for SDL - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) { + setMousePosition(mouse.x, mouse.y); +} - const bool isFullscreen = getFullscreenMode(); +void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { + SDL_WarpMouse(x, y); +} - // 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; +bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) { + // In some cases we might not want to load the requested video mode. This + // will assure that the window size is not altered. + if (_ignoreLoadVideoMode) { + _ignoreLoadVideoMode = false; + return true; } - _videoMode.overlayWidth = _videoMode.hardwareWidth; - _videoMode.overlayHeight = _videoMode.hardwareHeight; + // This function should never be called from notifyResize thus we know + // that the requested size came from somewhere else. + _gotResize = false; - uint32 flags = SDL_OPENGL; + // Save the requested dimensions. + _lastRequestedWidth = requestedWidth; + _lastRequestedHeight = requestedHeight; - if (isFullscreen) - flags |= SDL_FULLSCREEN; - else - flags |= SDL_RESIZABLE; - - // Create our window - _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 32, flags); -#ifdef USE_RGB_COLOR - detectSupportedFormats(); -#endif + // Apply the currently saved scale setting. + requestedWidth *= _graphicsScale; + requestedHeight *= _graphicsScale; - if (_hwscreen == NULL) { - // DON'T use error(), as this tries to bring up the debug - // console, which WON'T WORK now that _hwscreen is hosed. - - if (!_oldVideoMode.setup) { - warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError()); - g_system->quit(); - } else - // Cancel GFX load, and go back to last mode - return false; - } + // Set up the mode. + return setupMode(requestedWidth, requestedHeight); +} - // Check if the screen is BGR format - setFormatIsBGR(_hwscreen->format->Rshift != 0); +bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { + // In case we request a fullscreen mode we will use the mode the user + // has chosen last time or the biggest mode available. + if (_wantsFullScreen) { + if (_desiredFullscreenWidth && _desiredFullscreenHeight) { + // In case only a distinct set of modes is available we check + // whether the requested mode is actually available. + if (!_fullscreenVideoModes.empty()) { + VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(), + _fullscreenVideoModes.end(), + VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight)); + // It's not available fall back to default. + if (i == _fullscreenVideoModes.end()) { + _desiredFullscreenWidth = 0; + _desiredFullscreenHeight = 0; + } + } + } - if (isFullscreen) { - _lastFullscreenModeWidth = _videoMode.hardwareWidth; - _lastFullscreenModeHeight = _videoMode.hardwareHeight; - ConfMan.setInt("last_fullscreen_mode_width", _lastFullscreenModeWidth); - ConfMan.setInt("last_fullscreen_mode_height", _lastFullscreenModeHeight); - } + // In case no desired mode has been set we default to the biggest mode + // available or the requested mode in case we don't know any + // any fullscreen modes. + if (!_desiredFullscreenWidth || !_desiredFullscreenHeight) { + if (!_fullscreenVideoModes.empty()) { + VideoModeArray::const_iterator i = _fullscreenVideoModes.end(); + --i; + + _desiredFullscreenWidth = i->width; + _desiredFullscreenHeight = i->height; + } else { + _desiredFullscreenWidth = width; + _desiredFullscreenHeight = height; + } + } - // Call and return parent implementation of this method - return OpenGLGraphicsManager::loadGFXMode(); -} + // Remember our choice. + ConfMan.setInt("last_fullscreen_mode_width", _desiredFullscreenWidth, Common::ConfigManager::kApplicationDomain); + ConfMan.setInt("last_fullscreen_mode_height", _desiredFullscreenHeight, Common::ConfigManager::kApplicationDomain); -void OpenGLSdlGraphicsManager::unloadGFXMode() { - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; + // Use our choice. + width = _desiredFullscreenWidth; + height = _desiredFullscreenHeight; } -} - -void OpenGLSdlGraphicsManager::internUpdateScreen() { - // Call to parent implementation of this method - OpenGLGraphicsManager::internUpdateScreen(); - - // Swap OpenGL buffers - SDL_GL_SwapBuffers(); -} -#ifdef USE_OSD -void OpenGLSdlGraphicsManager::displayModeChangedMsg() { - const char *newModeName = getCurrentModeName(); - if (newModeName) { - const int scaleFactor = getScale(); - - Common::String osdMessage = Common::String::format( - "%s: %s\n%d x %d -> %d x %d", - _("Current display mode"), - newModeName, - _videoMode.screenWidth * scaleFactor, - _videoMode.screenHeight * scaleFactor, - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(osdMessage.c_str()); + // WORKAROUND: Working around infamous SDL bugs when switching + // resolutions too fast. This might cause the event system to supply + // incorrect mouse position events otherwise. + // Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=665779 + const uint32 curTime = SDL_GetTicks(); + if (_hwScreen && (curTime < _lastVideoModeLoad || curTime - _lastVideoModeLoad < 100)) { + for (int i = 10; i > 0; --i) { + SDL_PumpEvents(); + SDL_Delay(10); + } } -} -void OpenGLSdlGraphicsManager::displayScaleChangedMsg() { - const int scaleFactor = getScale(); - Common::String osdMessage = Common::String::format( - "%s: x%d\n%d x %d -> %d x %d", - _("Current scale"), - scaleFactor, - _videoMode.screenWidth, _videoMode.screenHeight, - _videoMode.overlayWidth, _videoMode.overlayHeight - ); - displayMessageOnOSD(osdMessage.c_str()); -} -#endif + _lastVideoModeLoad = curTime; -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 || - event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS || - event.kbd.keycode == 'a' || event.kbd.keycode == 'f') - return true; - } else if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_SHIFT)) == (Common::KBD_CTRL|Common::KBD_SHIFT)) { - if (event.kbd.keycode == 'a' || event.kbd.keycode == 'f') - return true; - } else if ((event.kbd.flags & (Common::KBD_ALT)) == (Common::KBD_ALT) && event.kbd.keycode == 's') { - return true; + uint32 flags = SDL_OPENGL; + if (_wantsFullScreen) { + flags |= SDL_FULLSCREEN; + } else { + flags |= SDL_RESIZABLE; } - return false; -} -void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) { - beginGFXTransaction(); - const bool isFullscreen = getFullscreenMode(); + _hwScreen = SDL_SetVideoMode(width, height, 32, flags); - if (isFullscreen && loop) { - _activeFullscreenMode += loop; - setFullscreenMode(true); - } else { - _activeFullscreenMode = -2; - setFullscreenMode(!isFullscreen); + if (!_hwScreen) { + // We treat fullscreen requests as a "hint" for now. This means in + // case it is not available we simply ignore it. + if (_wantsFullScreen) { + _hwScreen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE); } + } - // HACK: We need to force a refresh here, since we change the - // fullscreen mode. - _transactionDetails.needRefresh = true; - endGFXTransaction(); - - // Ignore resize events for the next 10 frames - _ignoreResizeFrames = 10; + if (_hwScreen) { + const Graphics::PixelFormat rgba8888 = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); + notifyContextChange(rgba8888, rgba8888); + setActualScreenSize(_hwScreen->w, _hwScreen->h); + } -#ifdef USE_OSD - Common::String osdMessage; - if (getFullscreenMode()) - osdMessage = Common::String::format("%s\n%d x %d", - _("Fullscreen mode"), - _hwscreen->w, _hwscreen->h - ); - else - osdMessage = Common::String::format("%s\n%d x %d", - _("Windowed mode"), - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(osdMessage.c_str()); -#endif + return _hwScreen != nullptr; } bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { switch (event.type) { + case Common::EVENT_KEYUP: + return isHotkey(event); + case Common::EVENT_KEYDOWN: if (event.kbd.hasFlags(Common::KBD_ALT)) { - // Alt-Return and Alt-Enter toggle full screen mode - if (event.kbd.keycode == Common::KEYCODE_RETURN || - event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { - toggleFullScreen(0); + if ( event.kbd.keycode == Common::KEYCODE_RETURN + || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { + // Alt-Return and Alt-Enter toggle full screen mode + beginGFXTransaction(); + setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode)); + endGFXTransaction(); + +#ifdef USE_OSD + if (getFeatureState(OSystem::kFeatureFullscreenMode)) { + displayMessageOnOSD("Fullscreen mode"); + } else { + displayMessageOnOSD("Windowed mode"); + } +#endif return true; } - // Alt-S create a screenshot - if (event.kbd.keycode == 's') { + if (event.kbd.keycode == Common::KEYCODE_s) { + // Alt-s creates a screenshot Common::String filename; for (int n = 0;; n++) { @@ -509,169 +366,167 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { break; SDL_RWclose(file); } - if (saveScreenshot(filename.c_str())) - debug("Saved screenshot '%s'", filename.c_str()); - else - warning("Could not save screenshot"); - return true; - } - } - if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) { - // Ctrl-Alt-Return and Ctrl-Alt-Enter switch between full screen modes - if (event.kbd.keycode == Common::KEYCODE_RETURN || - event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { - toggleFullScreen(1); + saveScreenshot(filename.c_str()); + debug("Saved screenshot '%s'", filename.c_str()); + return true; } + } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { + if ( event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS + || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS) { + // Ctrl+Alt+Plus/Minus Increase/decrease the size + const int direction = (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_KP_PLUS) ? +1 : -1; + + if (getFeatureState(OSystem::kFeatureFullscreenMode)) { + // In case we are in fullscreen we will choose the previous + // or next mode. + + // In case no modes are available we do nothing. + if (_fullscreenVideoModes.empty()) { + return true; + } + + // Look for the current mode. + VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(), + _fullscreenVideoModes.end(), + VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight)); + if (i == _fullscreenVideoModes.end()) { + return true; + } + + // Cycle through the modes in the specified direction. + if (direction > 0) { + ++i; + if (i == _fullscreenVideoModes.end()) { + i = _fullscreenVideoModes.begin(); + } + } else { + if (i == _fullscreenVideoModes.begin()) { + i = _fullscreenVideoModes.end(); + } + --i; + } + + _desiredFullscreenWidth = i->width; + _desiredFullscreenHeight = i->height; + + // Try to setup the mode. + if (!setupMode(_lastRequestedWidth, _lastRequestedHeight)) { + warning("OpenGLSdlGraphicsManager::notifyEvent: Fullscreen resize failed ('%s')", SDL_GetError()); + g_system->quit(); + } + } else { + // Calculate the next scaling setting. We approximate the + // current scale setting in case the user resized the + // window. Then we apply the direction change. + _graphicsScale = MAX<int>(_hwScreen->w / _lastRequestedWidth, _hwScreen->h / _lastRequestedHeight); + _graphicsScale = MAX<int>(_graphicsScale + direction, 1); + + // Since we overwrite a user resize here we reset its + // flag here. This makes enabling AR smoother because it + // will change the window size like in surface SDL. + _gotResize = false; + + // Try to setup the mode. + if (!setupMode(_lastRequestedWidth * _graphicsScale, _lastRequestedHeight * _graphicsScale)) { + warning("OpenGLSdlGraphicsManager::notifyEvent: Window resize failed ('%s')", SDL_GetError()); + g_system->quit(); + } + } - // Ctrl-Alt-a switch between display modes - if (event.kbd.keycode == 'a') { - beginGFXTransaction(); - setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection)); - endGFXTransaction(); #ifdef USE_OSD - Common::String osdMessage; - if (getFeatureState(OSystem::kFeatureAspectRatioCorrection)) - osdMessage = Common::String::format("%s\n%d x %d -> %d x %d", - _("Enabled aspect ratio correction"), - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h); - else - osdMessage = Common::String::format("%s\n%d x %d -> %d x %d", - _("Disabled aspect ratio correction"), - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h); - displayMessageOnOSD(osdMessage.c_str()); + const Common::String osdMsg = Common::String::format("Resolution: %dx%d", _hwScreen->w, _hwScreen->h); + displayMessageOnOSD(osdMsg.c_str()); #endif - internUpdateScreen(); + return true; - } + } else if (event.kbd.keycode == Common::KEYCODE_a) { + // In case the user changed the window size manually we will + // not change the window size again here. + _ignoreLoadVideoMode = _gotResize; - // Ctrl-Alt-f toggles antialiasing - if (event.kbd.keycode == 'f') { + // Ctrl+Alt+a toggles the aspect ratio correction state. beginGFXTransaction(); - toggleAntialiasing(); + setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection)); endGFXTransaction(); + // Make sure we do not ignore the next resize. This + // effectively checks whether loadVideoMode has been called. + assert(!_ignoreLoadVideoMode); + #ifdef USE_OSD - // 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")); + Common::String osdMsg = "Aspect ratio correction: "; + osdMsg += getFeatureState(OSystem::kFeatureAspectRatioCorrection) ? "enabled" : "disabled"; + displayMessageOnOSD(osdMsg.c_str()); #endif + return true; - } + } else if (event.kbd.keycode == Common::KEYCODE_f) { + // Ctrl+Alt+f toggles the graphics modes. + + // We are crazy we will allow the OpenGL base class to + // introduce new graphics modes like shaders for special + // filtering. If some other OpenGL subclass needs this, + // we can think of refactoring this. + int mode = getGraphicsMode(); + const OSystem::GraphicsMode *supportedModes = getSupportedGraphicsModes(); + const OSystem::GraphicsMode *modeDesc = nullptr; + + // Search the current mode. + for (; supportedModes->name; ++supportedModes) { + if (supportedModes->id == mode) { + modeDesc = supportedModes; + break; + } + } + assert(modeDesc); - SDLKey sdlKey = (SDLKey)event.kbd.keycode; - - // 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 = getScale(); - factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1; - if (0 < factor && factor < 4) { - // Check if the desktop resolution has been detected - if (_desktopWidth > 0 && _desktopHeight > 0) - // If the new scale factor is too big, do not scale - if (_videoMode.screenWidth * factor > _desktopWidth || - _videoMode.screenHeight * factor > _desktopHeight) - return false; - - beginGFXTransaction(); - setScale(factor); - endGFXTransaction(); -#ifdef USE_OSD - displayScaleChangedMsg(); -#endif - return true; + // Try to use the next mode in the list. + ++modeDesc; + if (!modeDesc->name) { + modeDesc = getSupportedGraphicsModes(); } - } - const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_3); - const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP3); + // Never ever try to resize the window when we simply want to + // switch the graphics mode. This assures that the window size + // does not change. + _ignoreLoadVideoMode = true; + + beginGFXTransaction(); + setGraphicsMode(modeDesc->id); + endGFXTransaction(); + + // Make sure we do not ignore the next resize. This + // effectively checks whether loadVideoMode has been called. + assert(!_ignoreLoadVideoMode); - // Ctrl-Alt-<number key> will change the GFX mode - if (isNormalNumber || isKeypadNumber) { - 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(); - setGraphicsMode(sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1)); - setScale(oldScale); - endGFXTransaction(); #ifdef USE_OSD - if (lastMode != _videoMode.mode) - displayModeChangedMsg(); + const Common::String osdMsg = Common::String::format("Graphics mode: %s", _(modeDesc->description)); + displayMessageOnOSD(osdMsg.c_str()); #endif - internUpdateScreen(); - } - } - } - if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_SHIFT)) { - // Ctrl-Shift-Return and Ctrl-Shift-Enter switch backwards between full screen modes - if (event.kbd.keycode == Common::KEYCODE_RETURN || - event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { - toggleFullScreen(-1); return true; } } - break; - - case Common::EVENT_KEYUP: - return isHotkey(event); + // Fall through default: - break; + return false; } - - return false; -} - -void OpenGLSdlGraphicsManager::notifyVideoExpose() { } -void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) { - // Do not resize if ignoring resize events. - if (!_ignoreResizeFrames && !getFullscreenMode()) { - bool scaleChanged = false; - beginGFXTransaction(); - _videoMode.hardwareWidth = width; - _videoMode.hardwareHeight = height; - - _screenResized = true; - - int scale = MIN(_videoMode.hardwareWidth / _videoMode.screenWidth, - _videoMode.hardwareHeight / _videoMode.screenHeight); - - if (getScale() != scale) { - scaleChanged = true; - setScale(MAX(MIN(scale, 3), 1)); - } - - _transactionDetails.sizeChanged = true; - endGFXTransaction(); -#ifdef USE_OSD - if (scaleChanged) - displayScaleChangedMsg(); -#endif +bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { + if (event.kbd.hasFlags(Common::KBD_ALT)) { + return event.kbd.keycode == Common::KEYCODE_RETURN + || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER + || event.kbd.keycode == Common::KEYCODE_s; + } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { + return event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS + || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS + || event.kbd.keycode == Common::KEYCODE_a + || event.kbd.keycode == Common::KEYCODE_f; } -} - -void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { - adjustMousePosition(point.x, point.y); -} -void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) { - setMousePosition(mouse.x, mouse.y); + return false; } - -#endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index 1587183328..9934ca79e2 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -8,117 +8,109 @@ * 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_OPENGLSDL_H -#define BACKENDS_GRAPHICS_OPENGLSDL_H +#ifndef BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H +#define BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H -#include "backends/platform/sdl/sdl-sys.h" -#if defined(ARRAYSIZE) && !defined(_WINDOWS_) -#undef ARRAYSIZE -#endif -#include "backends/graphics/sdl/sdl-graphics.h" #include "backends/graphics/opengl/opengl-graphics.h" +#include "backends/graphics/sdl/sdl-graphics.h" +#include "backends/platform/sdl/sdl-sys.h" +#include "common/array.h" #include "common/events.h" -/** - * SDL OpenGL graphics manager - */ -class OpenGLSdlGraphicsManager : public OpenGLGraphicsManager, public SdlGraphicsManager, public Common::EventObserver { +class OpenGLSdlGraphicsManager : public OpenGL::OpenGLGraphicsManager, public SdlGraphicsManager, public Common::EventObserver { public: - OpenGLSdlGraphicsManager(SdlEventSource *eventSource); + OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource); virtual ~OpenGLSdlGraphicsManager(); + // GraphicsManager API + virtual void activateManager(); + virtual void deactivateManager(); + virtual bool hasFeature(OSystem::Feature f); virtual void setFeatureState(OSystem::Feature f, bool enable); + virtual bool getFeatureState(OSystem::Feature f); + + virtual bool setGraphicsMode(int mode); + virtual void resetGraphicsScale(); #ifdef USE_RGB_COLOR virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif - virtual void initEventObserver(); - virtual bool notifyEvent(const Common::Event &event); - virtual void updateScreen(); - // SdlGraphicsManager interface + // EventObserver API + virtual bool notifyEvent(const Common::Event &event); + + // SdlGraphicsManager API virtual void notifyVideoExpose(); virtual void notifyResize(const uint width, const uint height); virtual void transformMouseCoordinates(Common::Point &point); virtual void notifyMousePos(Common::Point mouse); protected: - virtual void internUpdateScreen(); + virtual void setInternalMousePosition(int x, int y); - virtual bool loadGFXMode(); - virtual void unloadGFXMode(); - virtual bool isHotkey(const Common::Event &event); + virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format); +private: + bool setupMode(uint width, uint height); -#ifdef USE_RGB_COLOR - Common::List<Graphics::PixelFormat> _supportedFormats; + uint32 _lastVideoModeLoad; + SDL_Surface *_hwScreen; - /** - * Update the list of supported pixel formats. - * This method is invoked by loadGFXMode(). - */ - void detectSupportedFormats(); -#endif + uint _lastRequestedWidth; + uint _lastRequestedHeight; + uint _graphicsScale; + bool _ignoreLoadVideoMode; + bool _gotResize; - /** - * Toggles fullscreen. - * @loop loop direction for switching fullscreen mode, if 0 toggles it. - */ - virtual void toggleFullScreen(int loop); + bool _wantsFullScreen; + uint _ignoreResizeEvents; - int _activeFullscreenMode; + struct VideoMode { + VideoMode() : width(0), height(0) {} + VideoMode(uint w, uint h) : width(w), height(h) {} - /** - * Setup the fullscreen mode. - * @return false if failed finding a mode, true otherwise. - */ - virtual bool setupFullscreenMode(); + bool operator<(const VideoMode &right) const { + if (width < right.width) { + return true; + } else if (width == right.width && height < right.height) { + return true; + } else { + return false; + } + } - virtual void setInternalMousePosition(int x, int y); + bool operator==(const VideoMode &right) const { + return width == right.width && height == right.height; + } - int _lastFullscreenModeWidth; - int _lastFullscreenModeHeight; - int _desktopWidth; - int _desktopHeight; - - // Hardware screen - SDL_Surface *_hwscreen; - - // If screen was resized by the user - bool _screenResized; - - // Ignore resize events for the number of updateScreen() calls. - // Normaly resize events are user generated when resizing the window - // from its borders, but in some cases a resize event can be generated - // after a fullscreen change. - int _ignoreResizeFrames; - -#ifdef USE_OSD - /** - * Displays a mode change message in OSD - */ - void displayModeChangedMsg(); - - /** - * Displays a scale change message in OSD - */ - void displayScaleChangedMsg(); -#endif + bool operator!=(const VideoMode &right) const { + return !(*this == right); + } + + uint width, height; + }; + typedef Common::Array<VideoMode> VideoModeArray; + VideoModeArray _fullscreenVideoModes; + + uint _desiredFullscreenWidth; + uint _desiredFullscreenHeight; + + virtual bool isHotkey(const Common::Event &event); }; #endif diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 2eca4b8aab..417f4faf54 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -26,10 +26,15 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source) : _eventSource(source) { - _eventSource->setGraphicsManager(this); } SdlGraphicsManager::~SdlGraphicsManager() { - _eventSource->setGraphicsManager(0); } +void SdlGraphicsManager::initEventSource() { + _eventSource->setGraphicsManager(this); +} + +void SdlGraphicsManager::deinitEventSource() { + _eventSource->setGraphicsManager(0); +} diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index ea9149fccb..4d4338af16 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -80,6 +80,9 @@ public: virtual void notifyMousePos(Common::Point mouse) = 0; protected: + void initEventSource(); + void deinitEventSource(); + SdlEventSource *_eventSource; }; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 02e58ab319..c946b8e747 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -40,6 +40,7 @@ #include "graphics/scaler.h" #include "graphics/scaler/aspect.h" #include "graphics/surface.h" +#include "gui/EventRecorder.h" static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, @@ -135,19 +136,12 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _paletteDirtyStart(0), _paletteDirtyEnd(0), _screenIsLocked(false), _graphicsMutex(0), + _displayDisabled(false), #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()); - } - - // This is also called in initSDL(), but initializing graphics - // may reset it. - SDL_EnableUNICODE(1); - // allocate palette storage _currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); _cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); @@ -163,8 +157,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect"); #endif - SDL_ShowCursor(SDL_DISABLE); - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); memset(&_videoMode, 0, sizeof(_videoMode)); memset(&_transactionDetails, 0, sizeof(_transactionDetails)); @@ -191,10 +183,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou } SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { - // Unregister the event observer - if (g_system->getEventManager()->getEventDispatcher() != NULL) - g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); - unloadGFXMode(); if (_mouseSurface) SDL_FreeSurface(_mouseSurface); @@ -209,11 +197,24 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { free(_mouseData); } -void SurfaceSdlGraphicsManager::initEventObserver() { +void SurfaceSdlGraphicsManager::activateManager() { + GraphicsManager::activateManager(); + initEventSource(); + // Register the graphics manager as a event observer g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); } +void SurfaceSdlGraphicsManager::deactivateManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher()) { + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + } + + deinitEventSource(); + GraphicsManager::deactivateManager(); +} + bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) { return (f == OSystem::kFeatureFullscreenMode) || @@ -261,10 +262,6 @@ bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) { } } -const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::supportedGraphicsModes() { - return s_supportedGraphicsModes; -} - const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } @@ -765,9 +762,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { fixupResolutionForAspectRatio(_videoMode.desiredAspectRatio, _videoMode.hardwareWidth, _videoMode.hardwareHeight); } - _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, - _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE - ); + +#ifdef ENABLE_EVENTRECORDER + _displayDisabled = ConfMan.getBool("disable_display"); + + if (_displayDisabled) { + _hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight); + } else +#endif + { + _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, + _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE + ); + } + #ifdef USE_RGB_COLOR detectSupportedFormats(); #endif @@ -1188,7 +1196,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { #endif // Finally, blit all our changes to the screen - SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); + if (!_displayDisabled) { + SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); + } } _numDirtyRects = 0; @@ -1293,15 +1303,13 @@ Graphics::Surface *SurfaceSdlGraphicsManager::lockScreen() { if (SDL_LockSurface(_screen) == -1) error("SDL_LockSurface failed: %s", SDL_GetError()); - _framebuffer.pixels = _screen->pixels; - _framebuffer.w = _screen->w; - _framebuffer.h = _screen->h; - _framebuffer.pitch = _screen->pitch; + _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels, #ifdef USE_RGB_COLOR - _framebuffer.format = _screenFormat; + _screenFormat #else - _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); + Graphics::PixelFormat::createFormatCLUT8() #endif + ); return &_framebuffer; } @@ -1325,8 +1333,8 @@ void SurfaceSdlGraphicsManager::unlockScreen() { void SurfaceSdlGraphicsManager::fillScreen(uint32 col) { Graphics::Surface *screen = lockScreen(); - if (screen && screen->pixels) - memset(screen->pixels, col, screen->h * screen->pitch); + if (screen && screen->getPixels()) + memset(screen->getPixels(), col, screen->h * screen->pitch); unlockScreen(); } @@ -2047,15 +2055,12 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) { error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError()); Graphics::Surface dst; - dst.pixels = _osdSurface->pixels; - dst.w = _osdSurface->w; - dst.h = _osdSurface->h; - dst.pitch = _osdSurface->pitch; - 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); + dst.init(_osdSurface->w, _osdSurface->h, _osdSurface->pitch, _osdSurface->pixels, + 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::kLocalizedFont); diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 21444cc25d..00c05ff2bf 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -80,13 +80,13 @@ public: SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource); virtual ~SurfaceSdlGraphicsManager(); - virtual void initEventObserver(); + virtual void activateManager(); + virtual void deactivateManager(); virtual bool hasFeature(OSystem::Feature f); virtual void setFeatureState(OSystem::Feature f, bool enable); virtual bool getFeatureState(OSystem::Feature f); - static const OSystem::GraphicsMode *supportedGraphicsModes(); virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; virtual bool setGraphicsMode(int mode); @@ -232,6 +232,9 @@ protected: int _scalerType; int _transactionMode; + // Indicates whether it is needed to free _hwsurface in destructor + bool _displayDisabled; + bool _screenIsLocked; Graphics::Surface _framebuffer; diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h index 1e8d1c08c3..a54a2acbdc 100644 --- a/backends/keymapper/keymapper.h +++ b/backends/keymapper/keymapper.h @@ -128,7 +128,7 @@ public: * @param name name of the keymap to push * @param transparent if true keymapper will iterate down the * stack if it cannot find a key in the new map - * @return true if succesful + * @return true if successful */ bool pushKeymap(const String& name, bool transparent = false); diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp index 5cefe668cd..d2c60bec9d 100644 --- a/backends/midi/timidity.cpp +++ b/backends/midi/timidity.cpp @@ -148,7 +148,7 @@ MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() { int MidiDriver_TIMIDITY::open() { char *res; - char timidity_host[MAXHOSTNAMELEN]; + char timidity_host[NI_MAXHOST]; int timidity_port, data_port, i; /* count ourselves open */ diff --git a/backends/mixer/nullmixer/nullsdl-mixer.cpp b/backends/mixer/nullmixer/nullsdl-mixer.cpp new file mode 100644 index 0000000000..2fd652e19f --- /dev/null +++ b/backends/mixer/nullmixer/nullsdl-mixer.cpp @@ -0,0 +1,75 @@ +/* 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. + * + */ + +#include "backends/mixer/nullmixer/nullsdl-mixer.h" +#include "common/savefile.h" + +NullSdlMixerManager::NullSdlMixerManager() : SdlMixerManager() { + _outputRate = 22050; + _callsCounter = 0; + _callbackPeriod = 10; + _samples = 8192; + while (_samples * 16 > _outputRate * 2) + _samples >>= 1; + _samplesBuf = new uint8[_samples * 4]; +} + +NullSdlMixerManager::~NullSdlMixerManager() { + delete _samplesBuf; +} + +void NullSdlMixerManager::init() { + _mixer = new Audio::MixerImpl(g_system, _outputRate); + assert(_mixer); + _mixer->setReady(true); +} + +void NullSdlMixerManager::suspendAudio() { + _audioSuspended = true; +} + +int NullSdlMixerManager::resumeAudio() { + if (!_audioSuspended) { + return -2; + } + _audioSuspended = false; + return 0; +} + + +void NullSdlMixerManager::startAudio() { +} + +void NullSdlMixerManager::callbackHandler(byte *samples, int len) { + assert(_mixer); + _mixer->mixCallback(samples, len); +} + +void NullSdlMixerManager::update() { + if (_audioSuspended) { + return; + } + _callsCounter++; + if ((_callsCounter % _callbackPeriod) == 0) { + callbackHandler(_samplesBuf, _samples); + } +} diff --git a/backends/mixer/nullmixer/nullsdl-mixer.h b/backends/mixer/nullmixer/nullsdl-mixer.h new file mode 100644 index 0000000000..94248ced66 --- /dev/null +++ b/backends/mixer/nullmixer/nullsdl-mixer.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_MIXER_NULLSDL_H +#define BACKENDS_MIXER_NULLSDL_H + +#include "backends/mixer/sdl/sdl-mixer.h" +#include "common/str.h" + +/** Audio mixer which in fact does not output audio. + * + * It is used by events recorder since the recorder is intentionally + * turning sound off to avoid stuttering. + * + * It returns correct output and shoots callbacks, so all OSystem + * users could work without modifications. + */ + +class NullSdlMixerManager : public SdlMixerManager { +public: + NullSdlMixerManager(); + virtual ~NullSdlMixerManager(); + + virtual void init(); + void update(); + + virtual void suspendAudio(); + virtual int resumeAudio(); + +protected: + + virtual void startAudio(); + virtual void callbackHandler(byte *samples, int len); + +private: + uint32 _outputRate; + uint32 _callsCounter; + uint8 _callbackPeriod; + uint32 _samples; + uint8 *_samplesBuf; +}; + +#endif diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index b46f33a2bc..6afe06aeca 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -26,6 +26,7 @@ #include "backends/graphics/graphics.h" #include "backends/mutex/mutex.h" +#include "gui/EventRecorder.h" #include "audio/mixer.h" #include "graphics/pixelformat.h" @@ -52,7 +53,7 @@ bool ModularBackend::hasFeature(Feature f) { } void ModularBackend::setFeatureState(Feature f, bool enable) { - return _graphicsManager->setFeatureState(f, enable); + _graphicsManager->setFeatureState(f, enable); } bool ModularBackend::getFeatureState(Feature f) { @@ -141,7 +142,15 @@ void ModularBackend::fillScreen(uint32 col) { } void ModularBackend::updateScreen() { +#ifdef ENABLE_EVENTRECORDER + g_eventRec.preDrawOverlayGui(); +#endif + _graphicsManager->updateScreen(); + +#ifdef ENABLE_EVENTRECORDER + g_eventRec.postDrawOverlayGui(); +#endif } void ModularBackend::setShakePos(int shakeOffset) { diff --git a/backends/module.mk b/backends/module.mk index a4f525d21d..1222d9a363 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -40,14 +40,6 @@ MODULE_OBJS += \ keymapper/remap-dialog.o endif -ifdef USE_OPENGL -MODULE_OBJS += \ - graphics/opengl/glerrorcheck.o \ - graphics/opengl/gltexture.o \ - graphics/opengl/opengl-graphics.o \ - graphics/openglsdl/openglsdl-graphics.o -endif - ifdef ENABLE_VKEYBD MODULE_OBJS += \ vkeybd/image-map.o \ @@ -57,6 +49,15 @@ MODULE_OBJS += \ vkeybd/virtual-keyboard-parser.o endif +# OpenGL specific source files. +ifdef USE_OPENGL +MODULE_OBJS += \ + graphics/opengl/debug.o \ + graphics/opengl/extensions.o \ + graphics/opengl/opengl-graphics.o \ + graphics/opengl/texture.o +endif + # SDL specific source files. # We cannot just check $BACKEND = sdl, as various other backends # derive from the SDL backend, and they all need the following files. @@ -70,12 +71,17 @@ MODULE_OBJS += \ mutex/sdl/sdl-mutex.o \ plugins/sdl/sdl-provider.o \ timer/sdl/sdl-timer.o - + # SDL 1.3 removed audio CD support ifndef USE_SDL13 MODULE_OBJS += \ audiocd/sdl/sdl-audiocd.o endif + +ifdef USE_OPENGL +MODULE_OBJS += \ + graphics/openglsdl/openglsdl-graphics.o +endif endif ifdef POSIX @@ -120,9 +126,9 @@ MODULE_OBJS += \ mixer/sdl13/sdl13-mixer.o endif -ifeq ($(BACKEND),bada) +ifeq ($(BACKEND),tizen) MODULE_OBJS += \ - timer/bada/timer.o + timer/tizen/timer.o endif ifeq ($(BACKEND),ds) @@ -214,5 +220,11 @@ MODULE_OBJS += \ plugins/wii/wii-provider.o endif +ifdef ENABLE_EVENTRECORDER +MODULE_OBJS += \ + mixer/nullmixer/nullsdl-mixer.o \ + saves/recorder/recorder-saves.o +endif + # Include common rules include $(srcdir)/rules.mk diff --git a/backends/mutex/sdl/sdl-mutex.cpp b/backends/mutex/sdl/sdl-mutex.cpp index 8491ae468c..a51e6f0e38 100644 --- a/backends/mutex/sdl/sdl-mutex.cpp +++ b/backends/mutex/sdl/sdl-mutex.cpp @@ -33,15 +33,15 @@ OSystem::MutexRef SdlMutexManager::createMutex() { } void SdlMutexManager::lockMutex(OSystem::MutexRef mutex) { - SDL_mutexP((SDL_mutex *) mutex); + SDL_mutexP((SDL_mutex *)mutex); } void SdlMutexManager::unlockMutex(OSystem::MutexRef mutex) { - SDL_mutexV((SDL_mutex *) mutex); + SDL_mutexV((SDL_mutex *)mutex); } void SdlMutexManager::deleteMutex(OSystem::MutexRef mutex) { - SDL_DestroyMutex((SDL_mutex *) mutex); + SDL_DestroyMutex((SDL_mutex *)mutex); } #endif diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index f06e4be19e..5e3d1d0db6 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -146,7 +146,8 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) : _touchpad_scale(66), _dpad_scale(4), _fingersDown(0), - _trackball_scale(2) { + _trackball_scale(2), + _joystick_scale(10) { _fsFactory = new POSIXFilesystemFactory(); @@ -450,7 +451,7 @@ bool OSystem_Android::getFeatureState(Feature f) { } } -uint32 OSystem_Android::getMillis() { +uint32 OSystem_Android::getMillis(bool skipRecord) { timeval curTime; gettimeofday(&curTime, 0); diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index 5f2f40b726..704ce12f60 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -231,6 +231,7 @@ private: int _touchpad_scale; int _trackball_scale; int _dpad_scale; + int _joystick_scale; int _fingersDown; void clipMouse(Common::Point &p); @@ -274,7 +275,7 @@ public: virtual void setCursorPalette(const byte *colors, uint start, uint num); virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual MutexRef createMutex(void); diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index f498c671de..915bf8ac60 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -25,13 +25,19 @@ PATH_RESOURCES = $(PATH_DIST)/res PORT_DISTFILES = $(PATH_DIST)/README.Android +# FIXME: OUYA specific. +# "values-television" not present in vanilla Android. +# $(PATH_RESOURCES)/../res-ouya/values-television/margins.xml \ + RESOURCES = \ $(PATH_RESOURCES)/values/strings.xml \ + $(PATH_RESOURCES)/values/margins.xml \ $(PATH_RESOURCES)/layout/main.xml \ $(PATH_RESOURCES)/layout/splash.xml \ $(PATH_RESOURCES)/drawable/gradient.xml \ $(PATH_RESOURCES)/drawable/scummvm.png \ - $(PATH_RESOURCES)/drawable/scummvm_big.png + $(PATH_RESOURCES)/drawable/scummvm_big.png \ + $(PATH_RESOURCES)/drawable-xhdpi/ouya_icon.png PLUGIN_RESOURCES = \ $(PATH_RESOURCES)/values/strings.xml \ diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp index db1261e432..5c42db9347 100644 --- a/backends/platform/android/events.cpp +++ b/backends/platform/android/events.cpp @@ -64,6 +64,10 @@ enum { JE_RMB_DOWN = 11, JE_RMB_UP = 12, JE_MOUSE_MOVE = 13, + JE_GAMEPAD = 14, + JE_JOYSTICK = 15, + JE_MMB_DOWN = 16, + JE_MMB_UP = 17, JE_QUIT = 0x1000 }; @@ -109,6 +113,25 @@ enum { JKEYCODE_DPAD_CENTER = 23 }; +// gamepad +enum { + JKEYCODE_BUTTON_A = 96, + JKEYCODE_BUTTON_B = 97, + JKEYCODE_BUTTON_C = 98, + JKEYCODE_BUTTON_X = 99, + JKEYCODE_BUTTON_Y = 100, + JKEYCODE_BUTTON_Z = 101, + JKEYCODE_BUTTON_L1 = 102, + JKEYCODE_BUTTON_R1 = 103, + JKEYCODE_BUTTON_L2 = 104, + JKEYCODE_BUTTON_R2 = 105, + JKEYCODE_BUTTON_THUMBL = 106, + JKEYCODE_BUTTON_THUMBR = 107, + JKEYCODE_BUTTON_START = 108, + JKEYCODE_BUTTON_SELECT = 109, + JKEYCODE_BUTTON_MODE = 110, +}; + // meta modifier enum { JMETA_SHIFT = 0x01, @@ -827,6 +850,94 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3, return; + case JE_GAMEPAD: + 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 gamepad key: %d", arg1); + return; + } + + switch (arg2) { + case JKEYCODE_BUTTON_A: + case JKEYCODE_BUTTON_B: + switch (arg1) { + case JACTION_DOWN: + e.type = (arg2 == JKEYCODE_BUTTON_A? + Common::EVENT_LBUTTONDOWN : + Common::EVENT_RBUTTONDOWN); + break; + case JACTION_UP: + e.type = (arg2 == JKEYCODE_BUTTON_A? + Common::EVENT_LBUTTONUP : + Common::EVENT_RBUTTONUP); + break; + } + + e.mouse = getEventManager()->getMousePos(); + + break; + + case JKEYCODE_BUTTON_X: + e.kbd.keycode = Common::KEYCODE_ESCAPE; + e.kbd.ascii = Common::ASCII_ESCAPE; + break; + + default: + LOGW("unmapped gamepad key: %d", arg2); + return; + } + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + break; + + case JE_JOYSTICK: + e.mouse = getEventManager()->getMousePos(); + + switch (arg1) { + case JACTION_MULTIPLE: + e.type = Common::EVENT_MOUSEMOVE; + + // already multiplied by 100 + e.mouse.x += arg2 * _joystick_scale / _eventScaleX; + e.mouse.y += arg3 * _joystick_scale / _eventScaleY; + + clipMouse(e.mouse); + + break; + default: + LOGE("unhandled jaction on joystick: %d", arg1); + return; + } + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_MMB_DOWN: + e.type = Common::EVENT_MAINMENU; + + lockMutex(_event_queue_lock); + _event_queue.push(e); + unlockMutex(_event_queue_lock); + + return; + + case JE_MMB_UP: + // No action + + return; + case JE_QUIT: e.type = Common::EVENT_QUIT; diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index cd0fd88484..882dcff9a4 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -552,7 +552,7 @@ Graphics::Surface *OSystem_Android::lockScreen() { GLTHREADCHECK; Graphics::Surface *surface = _game_texture->surface(); - assert(surface->pixels); + assert(surface->getPixels()); return surface; } @@ -645,7 +645,7 @@ void OSystem_Android::grabOverlay(void *buf, int pitch) { assert(surface->format.bytesPerPixel == sizeof(uint16)); byte *dst = (byte *)buf; - const byte *src = (const byte *)surface->pixels; + const byte *src = (const byte *)surface->getPixels(); uint h = surface->h; do { diff --git a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java index 999815593f..8990515b84 100644 --- a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java +++ b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java @@ -14,6 +14,7 @@ public class MouseHelper { private long _rmbGuardTime; private boolean _rmbPressed; private boolean _lmbPressed; + private boolean _mmbPressed; /** * Class initialization fails when this throws an exception. @@ -114,6 +115,23 @@ public class MouseHelper { _rmbPressed = false; } + boolean mmbDown = (buttonState & MotionEvent.BUTTON_TERTIARY) == MotionEvent.BUTTON_TERTIARY; + if (mmbDown) { + if (!_mmbPressed) { + // middle mouse button was pressed just now + _scummvm.pushEvent(ScummVMEvents.JE_MMB_DOWN, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0); + } + + _mmbPressed = true; + } else { + if (_mmbPressed) { + // middle mouse button was released just now + _scummvm.pushEvent(ScummVMEvents.JE_MMB_UP, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0); + } + + _mmbPressed = false; + } + return true; } diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java index 829a948435..5d041dafd2 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java @@ -240,6 +240,14 @@ public class ScummVMActivity extends Activity { return false; } + @Override + public boolean onGenericMotionEvent(final MotionEvent e) { + if (_events != null) + return _events.onGenericMotionEvent(e); + + return false; + } + private void showKeyboard(boolean show) { SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface); InputMethodManager imm = (InputMethodManager) diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java index 5f51ffac6c..702215341b 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java @@ -9,6 +9,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.GestureDetector; +import android.view.InputDevice; import android.view.inputmethod.InputMethodManager; public class ScummVMEvents implements @@ -31,6 +32,10 @@ public class ScummVMEvents implements public static final int JE_RMB_DOWN = 11; public static final int JE_RMB_UP = 12; public static final int JE_MOUSE_MOVE = 13; + public static final int JE_GAMEPAD = 14; + public static final int JE_JOYSTICK = 15; + public static final int JE_MMB_DOWN = 16; + public static final int JE_MMB_UP = 17; public static final int JE_QUIT = 0x1000; final protected Context _context; @@ -63,6 +68,18 @@ public class ScummVMEvents implements return true; } + public boolean onGenericMotionEvent(final MotionEvent e) { + if((e.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { + _scummvm.pushEvent(JE_JOYSTICK, e.getAction(), + (int)(e.getAxisValue(MotionEvent.AXIS_X)*100), + (int)(e.getAxisValue(MotionEvent.AXIS_Y)*100), + 0, 0); + return true; + } + + return false; + } + final static int MSG_MENU_LONG_PRESS = 1; final private Handler keyHandler = new Handler() { @@ -177,6 +194,25 @@ public class ScummVMEvents implements (int)(e.getEventTime() - e.getDownTime()), e.getRepeatCount(), 0); return true; + case KeyEvent.KEYCODE_BUTTON_A: + case KeyEvent.KEYCODE_BUTTON_B: + case KeyEvent.KEYCODE_BUTTON_C: + case KeyEvent.KEYCODE_BUTTON_X: + case KeyEvent.KEYCODE_BUTTON_Y: + case KeyEvent.KEYCODE_BUTTON_Z: + case KeyEvent.KEYCODE_BUTTON_L1: + case KeyEvent.KEYCODE_BUTTON_R1: + case KeyEvent.KEYCODE_BUTTON_L2: + case KeyEvent.KEYCODE_BUTTON_R2: + case KeyEvent.KEYCODE_BUTTON_THUMBL: + case KeyEvent.KEYCODE_BUTTON_THUMBR: + case KeyEvent.KEYCODE_BUTTON_START: + case KeyEvent.KEYCODE_BUTTON_SELECT: + case KeyEvent.KEYCODE_BUTTON_MODE: + _scummvm.pushEvent(JE_GAMEPAD, action, keyCode, + (int)(e.getEventTime() - e.getDownTime()), + e.getRepeatCount(), 0); + return true; } _scummvm.pushEvent(JE_KEY, action, keyCode, diff --git a/backends/platform/android/texture.cpp b/backends/platform/android/texture.cpp index b174e93191..cc41c0d8a6 100644 --- a/backends/platform/android/texture.cpp +++ b/backends/platform/android/texture.cpp @@ -233,7 +233,7 @@ void GLESTexture::allocBuffer(GLuint w, GLuint h) { _pixels = new byte[w * h * _surface.format.bytesPerPixel]; assert(_pixels); - _surface.pixels = _pixels; + _surface.setPixels(_pixels); fillBuffer(0); @@ -256,7 +256,7 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, } void GLESTexture::fillBuffer(uint32 color) { - assert(_surface.pixels); + assert(_surface.getPixels()); if (_pixelFormat.bytesPerPixel == 1 || ((color & 0xff) == ((color >> 8) & 0xff))) @@ -377,7 +377,7 @@ void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) { assert(_pixels); // fixup surface, for the outside this is a CLUT8 surface - _surface.pixels = _pixels; + _surface.setPixels(_pixels); fillBuffer(0); @@ -386,8 +386,8 @@ void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) { } void GLESFakePaletteTexture::fillBuffer(uint32 color) { - assert(_surface.pixels); - memset(_surface.pixels, color & 0xff, _surface.pitch * _surface.h); + assert(_surface.getPixels()); + memset(_surface.getPixels(), color & 0xff, _surface.pitch * _surface.h); setDirty(); } diff --git a/backends/platform/bada/application.cpp b/backends/platform/bada/application.cpp deleted file mode 100644 index e761649245..0000000000 --- a/backends/platform/bada/application.cpp +++ /dev/null @@ -1,111 +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. - * - */ - -#include "engines/engine.h" - -#include "backends/platform/bada/form.h" -#include "backends/platform/bada/system.h" -#include "backends/platform/bada/application.h" - -using namespace Osp::System; -using namespace Osp::Ui::Controls; - -Application *BadaScummVM::createInstance() { - return new BadaScummVM(); -} - -BadaScummVM::BadaScummVM() : _appForm(0) { -} - -BadaScummVM::~BadaScummVM() { - logEntered(); - if (g_system) { - BadaSystem *system = (BadaSystem *)g_system; - system->destroyBackend(); - delete system; - g_system = 0; - } -} - -bool BadaScummVM::OnAppInitializing(AppRegistry &appRegistry) { - _appForm = systemStart(this); - return (_appForm != NULL); -} - -bool BadaScummVM::OnAppTerminating(AppRegistry &appRegistry, - bool forcedTermination) { - logEntered(); - return true; -} - -void BadaScummVM::OnUserEventReceivedN(RequestId requestId, - Osp::Base::Collection::IList *args) { - logEntered(); - - if (requestId == USER_MESSAGE_EXIT) { - // normal program termination - Terminate(); - } else if (requestId == USER_MESSAGE_EXIT_ERR) { - // assertion failure termination - String *message = NULL; - if (args) { - message = (String *)args->GetAt(0); - } - if (!message) { - message = new String("Unknown error"); - } - - MessageBox messageBox; - messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK); - int modalResult; - messageBox.ShowAndWait(modalResult); - Terminate(); - } -} - -void BadaScummVM::OnForeground(void) { - logEntered(); - pauseGame(false); -} - -void BadaScummVM::OnBackground(void) { - logEntered(); - pauseGame(true); -} - -void BadaScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) { -} - -void BadaScummVM::OnLowMemory(void) { -} - -void BadaScummVM::pauseGame(bool pause) { - if (_appForm) { - if (pause && g_engine && !g_engine->isPaused()) { - _appForm->pushKey(Common::KEYCODE_SPACE); - } - - if (g_system) { - ((BadaSystem *)g_system)->setMute(pause); - } - } -} diff --git a/backends/platform/bada/bada.mk b/backends/platform/bada/bada.mk deleted file mode 100644 index 7c72d7752b..0000000000 --- a/backends/platform/bada/bada.mk +++ /dev/null @@ -1,5 +0,0 @@ -# Bada specific modules are built under eclipse - -$(EXECUTABLE): $(OBJS) - rm -f $@ - ar Tru $@ $(OBJS) diff --git a/backends/platform/bada/form.cpp b/backends/platform/bada/form.cpp deleted file mode 100644 index dfa72bce08..0000000000 --- a/backends/platform/bada/form.cpp +++ /dev/null @@ -1,464 +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. - * - */ - -#include <FAppApplication.h> - -#include "common/translation.h" -#include "base/main.h" - -#include "backends/platform/bada/form.h" -#include "backends/platform/bada/system.h" - -using namespace Osp::Base::Runtime; -using namespace Osp::Ui; -using namespace Osp::Ui::Controls; - -// number of volume levels -#define LEVEL_RANGE 5 - -// round down small Y touch values to 1 to allow the -// cursor to be positioned at the top of the screen -#define MIN_TOUCH_Y 10 - -// block for up to 2.5 seconds during shutdown to -// allow the game thread to exit gracefully. -#define EXIT_SLEEP_STEP 10 -#define EXIT_SLEEP 250 - -// -// BadaAppForm -// -BadaAppForm::BadaAppForm() : - _gameThread(0), - _state(kInitState), - _buttonState(kLeftButton), - _shortcut(kSetVolume) { - _eventQueueLock = new Mutex(); - _eventQueueLock->Create(); -} - -result BadaAppForm::Construct() { - result r = Form::Construct(Controls::FORM_STYLE_NORMAL); - if (IsFailed(r)) { - return r; - } - - BadaSystem *badaSystem = NULL; - _gameThread = NULL; - - badaSystem = new BadaSystem(this); - r = badaSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY; - - if (!IsFailed(r)) { - r = badaSystem->Construct(); - } - - if (!IsFailed(r)) { - _gameThread = new Thread(); - r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY; - } - - if (!IsFailed(r)) { - r = _gameThread->Construct(*this); - } - - if (IsFailed(r)) { - if (badaSystem != NULL) { - delete badaSystem; - } - if (_gameThread != NULL) { - delete _gameThread; - _gameThread = NULL; - } - } else { - g_system = badaSystem; - } - - return r; -} - -BadaAppForm::~BadaAppForm() { - logEntered(); - - if (_gameThread && _state != kErrorState) { - terminate(); - - _gameThread->Stop(); - if (_state != kErrorState) { - _gameThread->Join(); - } - - delete _gameThread; - _gameThread = NULL; - } - - if (_eventQueueLock) { - delete _eventQueueLock; - _eventQueueLock = NULL; - } - - logLeaving(); -} - -// -// abort the game thread -// -void BadaAppForm::terminate() { - if (_state == kActiveState) { - ((BadaSystem *)g_system)->setMute(true); - - _eventQueueLock->Acquire(); - - Common::Event e; - e.type = Common::EVENT_QUIT; - _eventQueue.push(e); - _state = kClosingState; - - _eventQueueLock->Release(); - - // block while thread ends - AppLog("waiting for shutdown"); - for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) { - Thread::Sleep(EXIT_SLEEP); - } - - if (_state == kClosingState) { - // failed to terminate - Join() will freeze - _state = kErrorState; - } - } -} - -void BadaAppForm::exitSystem() { - _state = kErrorState; - - if (_gameThread) { - _gameThread->Stop(); - delete _gameThread; - _gameThread = NULL; - } -} - -result BadaAppForm::OnInitializing(void) { - logEntered(); - - SetOrientation(ORIENTATION_LANDSCAPE); - AddOrientationEventListener(*this); - AddTouchEventListener(*this); - AddKeyEventListener(*this); - - // set focus to enable receiving key events - SetFocusable(true); - SetFocus(); - - return E_SUCCESS; -} - -result BadaAppForm::OnDraw(void) { - logEntered(); - - if (g_system) { - BadaSystem *system = (BadaSystem *)g_system; - BadaGraphicsManager *graphics = system->getGraphics(); - if (graphics && graphics->isReady()) { - g_system->updateScreen(); - } - } - - return E_SUCCESS; -} - -bool BadaAppForm::pollEvent(Common::Event &event) { - bool result = false; - - _eventQueueLock->Acquire(); - if (!_eventQueue.empty()) { - event = _eventQueue.pop(); - result = true; - } - _eventQueueLock->Release(); - - return result; -} - -void BadaAppForm::pushEvent(Common::EventType type, const Point ¤tPosition) { - BadaSystem *system = (BadaSystem *)g_system; - BadaGraphicsManager *graphics = system->getGraphics(); - if (graphics) { - // graphics could be NULL at startup or when - // displaying the system error screen - Common::Event e; - e.type = type; - e.mouse.x = currentPosition.x; - e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1; - - bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y); - - _eventQueueLock->Acquire(); - - if (moved && type != Common::EVENT_MOUSEMOVE) { - Common::Event moveEvent; - moveEvent.type = Common::EVENT_MOUSEMOVE; - moveEvent.mouse = e.mouse; - _eventQueue.push(moveEvent); - } - - _eventQueue.push(e); - _eventQueueLock->Release(); - } -} - -void BadaAppForm::pushKey(Common::KeyCode keycode) { - Common::Event e; - e.synthetic = false; - e.kbd.keycode = keycode; - e.kbd.ascii = keycode; - e.kbd.flags = 0; - - _eventQueueLock->Acquire(); - - e.type = Common::EVENT_KEYDOWN; - _eventQueue.push(e); - e.type = Common::EVENT_KEYUP; - _eventQueue.push(e); - - _eventQueueLock->Release(); -} - -void BadaAppForm::OnOrientationChanged(const Control &source, - OrientationStatus orientationStatus) { - logEntered(); - if (_state == kInitState) { - _state = kActiveState; - _gameThread->Start(); - } -} - -Object *BadaAppForm::Run(void) { - scummvm_main(0, 0); - - if (_state == kActiveState) { - Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL); - } - _state = kDoneState; - return NULL; -} - -void BadaAppForm::setButtonShortcut() { - switch (_buttonState) { - case kLeftButton: - g_system->displayMessageOnOSD(_("Right Click Once")); - _buttonState = kRightButtonOnce; - break; - case kRightButtonOnce: - g_system->displayMessageOnOSD(_("Right Click")); - _buttonState = kRightButton; - break; - case kRightButton: - g_system->displayMessageOnOSD(_("Move Only")); - _buttonState = kMoveOnly; - break; - case kMoveOnly: - g_system->displayMessageOnOSD(_("Left Click")); - _buttonState = kLeftButton; - break; - } -} - -void BadaAppForm::setShortcut() { - // cycle to the next shortcut - switch (_shortcut) { - case kControlMouse: - g_system->displayMessageOnOSD(_("Escape Key")); - _shortcut = kEscapeKey; - break; - - case kEscapeKey: - g_system->displayMessageOnOSD(_("Game Menu")); - _shortcut = kGameMenu; - break; - - case kGameMenu: - g_system->displayMessageOnOSD(_("Show Keypad")); - _shortcut = kShowKeypad; - break; - - case kSetVolume: - // fallthru - - case kShowKeypad: - g_system->displayMessageOnOSD(_("Control Mouse")); - _shortcut = kControlMouse; - break; - } -} - -void BadaAppForm::setVolume(bool up, bool minMax) { - int level = ((BadaSystem *)g_system)->setVolume(up, minMax); - if (level != -1) { - char message[32]; - char ind[LEVEL_RANGE]; // 1..5 (0=off) - int j = LEVEL_RANGE - 1; // 0..4 - for (int i = 1; i <= LEVEL_RANGE; i++) { - ind[j--] = level >= i ? '|' : ' '; - } - snprintf(message, sizeof(message), "Volume: [ %c%c%c%c%c ]", - ind[0], ind[1], ind[2], ind[3], ind[4]); - g_system->displayMessageOnOSD(message); - } -} - -void BadaAppForm::showKeypad() { - // display the soft keyboard - _buttonState = kLeftButton; - pushKey(Common::KEYCODE_F7); -} - -void BadaAppForm::OnTouchDoublePressed(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { - if (_buttonState != kMoveOnly) { - pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, - currentPosition); - pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, - currentPosition); - } -} - -void BadaAppForm::OnTouchFocusIn(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { -} - -void BadaAppForm::OnTouchFocusOut(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { -} - -void BadaAppForm::OnTouchLongPressed(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { - if (_buttonState != kLeftButton) { - pushKey(Common::KEYCODE_RETURN); - } -} - -void BadaAppForm::OnTouchMoved(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { - pushEvent(Common::EVENT_MOUSEMOVE, currentPosition); -} - -void BadaAppForm::OnTouchPressed(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { - if (_buttonState != kMoveOnly) { - pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, - currentPosition); - } -} - -void BadaAppForm::OnTouchReleased(const Control &source, - const Point ¤tPosition, - const TouchEventInfo &touchInfo) { - if (_buttonState != kMoveOnly) { - pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP, - currentPosition); - if (_buttonState == kRightButtonOnce) { - _buttonState = kLeftButton; - } - // flick to skip dialog - if (touchInfo.IsFlicked()) { - pushKey(Common::KEYCODE_PERIOD); - } - } -} - -void BadaAppForm::OnKeyLongPressed(const Control &source, KeyCode keyCode) { - logEntered(); - switch (keyCode) { - case KEY_SIDE_UP: - _shortcut = kSetVolume; - setVolume(true, true); - return; - - case KEY_SIDE_DOWN: - _shortcut = kSetVolume; - setVolume(false, true); - return; - - case KEY_CAMERA: - _shortcut = kShowKeypad; - showKeypad(); - return; - - default: - break; - } -} - -void BadaAppForm::OnKeyPressed(const Control &source, KeyCode keyCode) { - switch (keyCode) { - case KEY_SIDE_UP: - if (_shortcut != kSetVolume) { - _shortcut = kSetVolume; - } else { - setVolume(true, false); - } - return; - - case KEY_SIDE_DOWN: - switch (_shortcut) { - case kControlMouse: - setButtonShortcut(); - break; - - case kEscapeKey: - pushKey(Common::KEYCODE_ESCAPE); - break; - - case kGameMenu: - _buttonState = kLeftButton; - pushKey(Common::KEYCODE_F5); - break; - - case kShowKeypad: - showKeypad(); - break; - - default: - setVolume(false, false); - break; - } - break; - - case KEY_CAMERA: - setShortcut(); - break; - - default: - break; - } -} - -void BadaAppForm::OnKeyReleased(const Control &source, KeyCode keyCode) { -} diff --git a/backends/platform/bada/form.h b/backends/platform/bada/form.h deleted file mode 100644 index 3340e2216b..0000000000 --- a/backends/platform/bada/form.h +++ /dev/null @@ -1,108 +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. - * - */ - -#ifndef BADA_FORM_H -#define BADA_FORM_H - -#include <FApp.h> -#include <FUi.h> -#include <FSystem.h> -#include <FBase.h> -#include <FUiITouchEventListener.h> -#include <FUiITextEventListener.h> - -#include "config.h" -#include "common/scummsys.h" -#include "common/events.h" -#include "common/queue.h" -#include "common/mutex.h" - -// -// BadaAppForm -// -class BadaAppForm : public Osp::Ui::Controls::Form, - public Osp::Ui::IOrientationEventListener, - public Osp::Ui::ITouchEventListener, - public Osp::Ui::IKeyEventListener, - public Osp::Base::Runtime::IRunnable { -public: - BadaAppForm(); - ~BadaAppForm(); - - result Construct(); - bool pollEvent(Common::Event &event); - bool isClosing() { return _state == kClosingState; } - void pushKey(Common::KeyCode keycode); - void exitSystem(); - -private: - Object *Run(); - result OnInitializing(void); - result OnDraw(void); - void OnOrientationChanged(const Osp::Ui::Control &source, - Osp::Ui::OrientationStatus orientationStatus); - void OnTouchDoublePressed(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnTouchFocusIn(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnTouchFocusOut(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnTouchLongPressed(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnTouchMoved(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnTouchPressed(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnTouchReleased(const Osp::Ui::Control &source, - const Osp::Graphics::Point ¤tPosition, - const Osp::Ui::TouchEventInfo &touchInfo); - void OnKeyLongPressed(const Osp::Ui::Control &source, - Osp::Ui::KeyCode keyCode); - void OnKeyPressed(const Osp::Ui::Control &source, - Osp::Ui::KeyCode keyCode); - void OnKeyReleased(const Osp::Ui::Control &source, - Osp::Ui::KeyCode keyCode); - - void pushEvent(Common::EventType type, - const Osp::Graphics::Point ¤tPosition); - void terminate(); - void setButtonShortcut(); - void setShortcut(); - void setVolume(bool up, bool minMax); - void showKeypad(); - - // event handling - Osp::Base::Runtime::Thread *_gameThread; - Osp::Base::Runtime::Mutex *_eventQueueLock; - Common::Queue<Common::Event> _eventQueue; - enum { kInitState, kActiveState, kClosingState, kDoneState, kErrorState } _state; - enum { kLeftButton, kRightButtonOnce, kRightButton, kMoveOnly } _buttonState; - enum { kControlMouse, kEscapeKey, kGameMenu, kShowKeypad, kSetVolume } _shortcut; -}; - -#endif diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index d41839d961..d62ced02e1 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -151,7 +151,7 @@ public: void setShakePos(int shake_pos); // Get the number of milliseconds since the program was started. - uint32 getMillis(); + uint32 getMillis(bool skipRecord = false); // Delay for a specified amount of milliseconds void delayMillis(uint msecs); diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp index cc5798fc10..54ee6000ed 100644 --- a/backends/platform/dc/display.cpp +++ b/backends/platform/dc/display.cpp @@ -711,11 +711,7 @@ Graphics::Surface *OSystem_Dreamcast::lockScreen() if (!screen) return 0; - _framebuffer.pixels = screen; - _framebuffer.w = _screen_w; - _framebuffer.h = _screen_h; - _framebuffer.pitch = SCREEN_W*2; - _framebuffer.format = screenFormats[_screenFormat]; + _framebuffer.init(_screen_w, _screen_h, SCREEN_W*2, screen, screenFormats[_screenFormat]); return &_framebuffer; } diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 339e5df62d..4026c7dde6 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -219,7 +219,7 @@ static int findGames(Game *games, int max, bool use_ini) if (use_ini) { ConfMan.loadDefaultConfigFile(); - Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains(); + const Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains(); for(Common::ConfigManager::DomainMap::const_iterator i = game_domains.begin(); curr_game < max && i != game_domains.end(); i++) { Common::String path = (*i)._value["path"]; diff --git a/backends/platform/dc/time.cpp b/backends/platform/dc/time.cpp index 8cc3a71e8d..1e5f44ec85 100644 --- a/backends/platform/dc/time.cpp +++ b/backends/platform/dc/time.cpp @@ -26,7 +26,7 @@ #include "dc.h" -uint32 OSystem_Dreamcast::getMillis() +uint32 OSystem_Dreamcast::getMillis(bool skipRecord) { static uint32 msecs=0; static unsigned int t0=0; diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index 830c782b90..9dc66e80d7 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -2280,7 +2280,7 @@ void VBlankHandler(void) { //REG_IF = IRQ_VBLANK; } -int getMillis() { +int getMillis(bool skipRecord) { return currentTimeMillis; // return frameCount * FRAME_TIME; } diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h index ad49ae276d..5e91fae13a 100644 --- a/backends/platform/ds/arm9/source/dsmain.h +++ b/backends/platform/ds/arm9/source/dsmain.h @@ -88,7 +88,7 @@ void setGamma(int gamma); // Timers void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a callback function at a regular interval -int getMillis(); // Return the current runtime in milliseconds +int getMillis(bool skipRecord = false); // Return the current runtime in milliseconds void doTimerCallback(); // Call callback function if required // Sound diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index a4b9c842fc..f109983fbc 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -296,7 +296,7 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int // to save a few pennies/euro cents on the hardware. if (_frameBufferExists) { - bg = (u16 *)_framebuffer.pixels; + bg = (u16 *)_framebuffer.getPixels(); stride = _framebuffer.pitch; } else { bg = (u16 *)DS::get8BitBackBuffer(); @@ -455,7 +455,7 @@ void OSystem_DS::copyRectToScreen(const void *buf, int pitch, int x, int y, int dmaCopyHalfWords(3, src, dest1, w); - if ((!_frameBufferExists) || (buf == _framebuffer.pixels)) { + if ((!_frameBufferExists) || (buf == _framebuffer.getPixels())) { dmaCopyHalfWords(2, src, dest2, w); } @@ -476,7 +476,7 @@ void OSystem_DS::updateScreen() { _frameBufferExists = false; // Copy temp framebuffer back to screen - copyRectToScreen((byte *)_framebuffer.pixels, _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h); + copyRectToScreen((byte *)_framebuffer.getPixels(), _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h); } DS::displayMode16BitFlipBuffer(); @@ -656,7 +656,7 @@ bool OSystem_DS::pollEvent(Common::Event &event) { return false; } -uint32 OSystem_DS::getMillis() { +uint32 OSystem_DS::getMillis(bool skipRecord) { return DS::getMillis(); } @@ -755,11 +755,8 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() { if (DS::isCpuScalerEnabled()) { - _framebuffer.pixels = DS::getScalerBuffer(); - _framebuffer.w = DS::getGameWidth(); - _framebuffer.h = DS::getGameHeight(); - _framebuffer.pitch = DS::getGameWidth(); - _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); + _framebuffer.init(DS::getGameWidth(), DS::getGameHeight(), DS::getGameWidth(), + DS::getScalerBuffer(), Graphics::PixelFormat::createFormatCLUT8()); } else { @@ -780,11 +777,7 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() { dmaCopyHalfWords(3, srcLine, destLine, width); } - _framebuffer.pixels = dest; - _framebuffer.w = width; - _framebuffer.h = height; - _framebuffer.pitch = width; - _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); + _framebuffer.init(width, height, width, dest, Graphics::PixelFormat::createFormatCLUT8()); } @@ -798,8 +791,8 @@ Graphics::Surface *OSystem_DS::createTempFrameBuffer() { for (int y = 0; y < DS::getGameHeight(); y++) { DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth()); for (int x = 0; x < DS::getGameWidth() >> 1; x++) { - *(((u16 *) (_framebuffer.pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[(y * imageStrideInWords) + x]; -// *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x]; + *(((u16 *) (_framebuffer.getPixels())) + y * (DS::getGameWidth() >> 1) + x) = image[(y * imageStrideInWords) + x]; +// *(((u16 *) (surf->getPixels())) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x]; } }*/ diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index a6001da764..4550e22b2c 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -117,7 +117,7 @@ public: virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format); virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual void getTimeAndDate(TimeDate &t) const; diff --git a/backends/platform/gph/gph-backend.cpp b/backends/platform/gph/gph-backend.cpp index 485780b472..e51d7d0781 100644 --- a/backends/platform/gph/gph-backend.cpp +++ b/backends/platform/gph/gph-backend.cpp @@ -172,7 +172,7 @@ void OSystem_GPH::initSDL() { // Check if SDL has not been initialized if (!_initedSDL) { - uint32 sdlFlags = SDL_INIT_EVENTTHREAD; + uint32 sdlFlags = SDL_INIT_EVENTTHREAD | SDL_INIT_VIDEO; if (ConfMan.hasKey("disable_sdl_parachute")) sdlFlags |= SDL_INIT_NOPARACHUTE; diff --git a/backends/platform/iphone/iphone_video.mm b/backends/platform/iphone/iphone_video.mm index 0bfae30fc7..f2c1527658 100644 --- a/backends/platform/iphone/iphone_video.mm +++ b/backends/platform/iphone/iphone_video.mm @@ -365,7 +365,7 @@ const char *iPhone_getDocumentsDir() { _mouseTexCoords[5] = _mouseTexCoords[7] = _videoContext.mouseHeight / (GLfloat)_videoContext.mouseTexture.h; glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.mouseTexture.w, _videoContext.mouseTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.mouseTexture.pixels); printOpenGLError(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.mouseTexture.w, _videoContext.mouseTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.mouseTexture.getPixels()); printOpenGLError(); } - (void)updateMainSurface { @@ -377,7 +377,7 @@ const char *iPhone_getDocumentsDir() { // Unfortunately we have to update the whole texture every frame, since glTexSubImage2D is actually slower in all cases // due to the iPhone internals having to convert the whole texture back from its internal format when used. // In the future we could use several tiled textures instead. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.pixels); printOpenGLError(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.getPixels()); printOpenGLError(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } @@ -386,7 +386,7 @@ const char *iPhone_getDocumentsDir() { glTexCoordPointer(2, GL_FLOAT, 0, _overlayTexCoords); printOpenGLError(); glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.overlayTexture.w, _videoContext.overlayTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.overlayTexture.pixels); printOpenGLError(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.overlayTexture.w, _videoContext.overlayTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.overlayTexture.getPixels()); printOpenGLError(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp index ed2c886213..a814495b80 100644 --- a/backends/platform/iphone/osys_main.cpp +++ b/backends/platform/iphone/osys_main.cpp @@ -77,8 +77,8 @@ OSystem_IPHONE::~OSystem_IPHONE() { delete _mixer; // Prevent accidental freeing of the screen texture here. This needs to be // checked since we might use the screen texture as framebuffer in the case - // of hi-color games for example. - if (_framebuffer.pixels == _videoContext->screenTexture.pixels) + // of hi-color games for example. Otherwise this can lead to a double free. + if (_framebuffer.getPixels() != _videoContext->screenTexture.getPixels()) _framebuffer.free(); _mouseBuffer.free(); } @@ -166,7 +166,7 @@ void OSystem_IPHONE::suspendLoop() { _timeSuspended += getMillis() - startTime; } -uint32 OSystem_IPHONE::getMillis() { +uint32 OSystem_IPHONE::getMillis(bool skipRecord) { //printf("getMillis()\n"); struct timeval currentTime; diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h index 037125490d..811a8ddb2e 100644 --- a/backends/platform/iphone/osys_main.h +++ b/backends/platform/iphone/osys_main.h @@ -165,7 +165,7 @@ public: virtual void setCursorPalette(const byte *colors, uint start, uint num); virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual MutexRef createMutex(void); diff --git a/backends/platform/iphone/osys_video.mm b/backends/platform/iphone/osys_video.mm index a11bf32c54..ce7f94f5bd 100644 --- a/backends/platform/iphone/osys_video.mm +++ b/backends/platform/iphone/osys_video.mm @@ -76,8 +76,8 @@ void OSystem_IPHONE::initSize(uint width, uint height, const Graphics::PixelForm // In case we use the screen texture as frame buffer we reset the pixels // pointer here to avoid freeing the screen texture. - if (_framebuffer.pixels == _videoContext->screenTexture.pixels) - _framebuffer.pixels = 0; + if (_framebuffer.getPixels() == _videoContext->screenTexture.getPixels()) + _framebuffer.setPixels(0); // Create the screen texture right here. We need to do this here, since // when a game requests hi-color mode, we actually set the framebuffer @@ -310,7 +310,7 @@ void OSystem_IPHONE::hideOverlay() { void OSystem_IPHONE::clearOverlay() { //printf("clearOverlay()\n"); - bzero(_videoContext->overlayTexture.getBasePtr(0, 0), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch); + bzero(_videoContext->overlayTexture.getPixels(), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch); dirtyFullOverlayScreen(); } @@ -319,7 +319,7 @@ void OSystem_IPHONE::grabOverlay(void *buf, int pitch) { int h = _videoContext->overlayHeight; byte *dst = (byte *)buf; - const byte *src = (const byte *)_videoContext->overlayTexture.getBasePtr(0, 0); + const byte *src = (const byte *)_videoContext->overlayTexture.getPixels(); do { memcpy(dst, src, _videoContext->overlayWidth * sizeof(uint16)); src += _videoContext->overlayTexture.pitch; @@ -417,7 +417,7 @@ void OSystem_IPHONE::setMouseCursor(const void *buf, uint w, uint h, int hotspot #endif assert(pixelFormat.bytesPerPixel == 1 || pixelFormat.bytesPerPixel == 2); - if (_mouseBuffer.w != w || _mouseBuffer.h != h || _mouseBuffer.format != pixelFormat || !_mouseBuffer.pixels) + if (_mouseBuffer.w != w || _mouseBuffer.h != h || _mouseBuffer.format != pixelFormat || !_mouseBuffer.getPixels()) _mouseBuffer.create(w, h, pixelFormat); _videoContext->mouseWidth = w; @@ -428,7 +428,7 @@ void OSystem_IPHONE::setMouseCursor(const void *buf, uint w, uint h, int hotspot _mouseKeyColor = keycolor; - memcpy(_mouseBuffer.getBasePtr(0, 0), buf, h * _mouseBuffer.pitch); + memcpy(_mouseBuffer.getPixels(), buf, h * _mouseBuffer.pitch); _mouseDirty = true; _mouseNeedTextureUpdate = true; @@ -464,7 +464,7 @@ void OSystem_IPHONE::updateMouseTexture() { else palette = _gamePaletteRGBA5551; - uint16 *mouseBuf = (uint16 *)mouseTexture.getBasePtr(0, 0); + uint16 *mouseBuf = (uint16 *)mouseTexture.getPixels(); for (uint x = 0; x < _videoContext->mouseWidth; ++x) { for (uint y = 0; y < _videoContext->mouseHeight; ++y) { const byte color = *(const byte *)_mouseBuffer.getBasePtr(x, y); @@ -475,12 +475,12 @@ void OSystem_IPHONE::updateMouseTexture() { } } } else { - if (crossBlit((byte *)mouseTexture.getBasePtr(0, 0), (const byte *)_mouseBuffer.getBasePtr(0, 0), mouseTexture.pitch, + if (crossBlit((byte *)mouseTexture.getPixels(), (const byte *)_mouseBuffer.getPixels(), mouseTexture.pitch, _mouseBuffer.pitch, _mouseBuffer.w, _mouseBuffer.h, mouseTexture.format, _mouseBuffer.format)) { if (!_mouseBuffer.format.aBits()) { // Apply color keying since the original cursor had no alpha channel. - const uint16 *src = (const uint16 *)_mouseBuffer.getBasePtr(0, 0); - uint8 *dstRaw = (uint8 *)mouseTexture.getBasePtr(0, 0); + const uint16 *src = (const uint16 *)_mouseBuffer.getPixels(); + uint8 *dstRaw = (uint8 *)mouseTexture.getPixels(); for (uint y = 0; y < _mouseBuffer.h; ++y, dstRaw += mouseTexture.pitch) { uint16 *dst = (uint16 *)dstRaw; @@ -495,7 +495,7 @@ void OSystem_IPHONE::updateMouseTexture() { } else { // TODO: Log this! // Make the cursor all transparent... we really need a better fallback ;-). - memset(mouseTexture.getBasePtr(0, 0), 0, mouseTexture.h * mouseTexture.pitch); + memset(mouseTexture.getPixels(), 0, mouseTexture.h * mouseTexture.pitch); } } diff --git a/backends/platform/maemo/debian/changelog b/backends/platform/maemo/debian/changelog index ea44574e96..568edd0282 100644 --- a/backends/platform/maemo/debian/changelog +++ b/backends/platform/maemo/debian/changelog @@ -1,8 +1,14 @@ -scummvm (1.6.0~git) unstable; urgency=low +scummvm (1.7.0~git) unstable; urgency=low * Development snapshot - -- Tarek Soliman <tsoliman@scummvm.org> Tue, 10 Jul 2012 23:02:00 -0500 + -- Tarek Soliman <tsoliman@scummvm.org> Sat, 01 Jun 2013 21:03:52 -0500 + +scummvm (1.6.0) unstable; urgency=low + + * 1.6.0 release + + -- Tarek Soliman <tsoliman@scummvm.org> Fri, 31 May 2013 23:02:00 -0500 scummvm (1.5.0) unstable; urgency=low diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h index bc6b3cb1a5..10138b230a 100644 --- a/backends/platform/n64/osys_n64.h +++ b/backends/platform/n64/osys_n64.h @@ -184,7 +184,7 @@ public: virtual void setCursorPalette(const byte *colors, uint start, uint num); virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual MutexRef createMutex(void); diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp index 1e2aca9e51..36e5085764 100644 --- a/backends/platform/n64/osys_n64_base.cpp +++ b/backends/platform/n64/osys_n64_base.cpp @@ -605,11 +605,7 @@ void OSystem_N64::updateScreen() { } Graphics::Surface *OSystem_N64::lockScreen() { - _framebuffer.pixels = _offscreen_pal; - _framebuffer.w = _gameWidth; - _framebuffer.h = _gameHeight; - _framebuffer.pitch = _screenWidth; - _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); + _framebuffer.init(_gameWidth, _gameHeight, _screenWidth, _offscreen_pal, Graphics::PixelFormat::createFormatCLUT8()); return &_framebuffer; } @@ -810,7 +806,7 @@ void OSystem_N64::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, return; } -uint32 OSystem_N64::getMillis() { +uint32 OSystem_N64::getMillis(bool skipRecord) { return getMilliTick(); } diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp index 4690a67c55..9e05539799 100644 --- a/backends/platform/null/null.cpp +++ b/backends/platform/null/null.cpp @@ -49,7 +49,7 @@ public: virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual void getTimeAndDate(TimeDate &t) const {} diff --git a/backends/platform/openpandora/op-backend.cpp b/backends/platform/openpandora/op-backend.cpp index 354aa24b24..60c3cc7191 100644 --- a/backends/platform/openpandora/op-backend.cpp +++ b/backends/platform/openpandora/op-backend.cpp @@ -160,7 +160,7 @@ void OSystem_OP::initSDL() { // Check if SDL has not been initialized if (!_initedSDL) { - uint32 sdlFlags = SDL_INIT_EVENTTHREAD; + uint32 sdlFlags = SDL_INIT_EVENTTHREAD | SDL_INIT_VIDEO; if (ConfMan.hasKey("disable_sdl_parachute")) sdlFlags |= SDL_INIT_NOPARACHUTE; diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp index e818305c29..58667c0230 100644 --- a/backends/platform/ps2/Gs2dScreen.cpp +++ b/backends/platform/ps2/Gs2dScreen.cpp @@ -392,12 +392,8 @@ void Gs2dScreen::copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w Graphics::Surface *Gs2dScreen::lockScreen() { WaitSema(g_DmacSema); - _framebuffer.pixels = _screenBuf; - _framebuffer.w = _width; - _framebuffer.h = _height; - _framebuffer.pitch = _width; // -not- _pitch; ! It's EE mem, not Tex - _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); - + // -not- _pitch; ! It's EE mem, not Tex + _framebuffer.init(_width, _height, _width, _screenBuf, Graphics::PixelFormat::createFormatCLUT8()); return &_framebuffer; } diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 5628658381..a7d782b07c 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -571,7 +571,7 @@ void OSystem_PS2::displayMessageOnOSD(const char *msg) { printf("displayMessageOnOSD: %s\n", msg); } -uint32 OSystem_PS2::getMillis(void) { +uint32 OSystem_PS2::getMillis(bool skipRecord) { return msecCount; } diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index 99482d4da4..3ba40a70f9 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -82,7 +82,7 @@ public: virtual void warpMouse(int x, int y); virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = 0); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual bool pollEvent(Common::Event &event); diff --git a/backends/platform/psp/audio.cpp b/backends/platform/psp/audio.cpp index 4fab9fdd3f..dcbf0b2239 100644 --- a/backends/platform/psp/audio.cpp +++ b/backends/platform/psp/audio.cpp @@ -100,8 +100,6 @@ void PspAudio::threadFunction() { PSP_DEBUG_PRINT("audio thread unpaused\n"); } - PSP_DEBUG_PRINT("remaining samples[%d]\n", _remainingSamples); - PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill); _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data nextBuffer(_bufferToFill); diff --git a/backends/platform/psp/default_display_client.cpp b/backends/platform/psp/default_display_client.cpp index bc252144fa..6d6eb641f7 100644 --- a/backends/platform/psp/default_display_client.cpp +++ b/backends/platform/psp/default_display_client.cpp @@ -192,11 +192,8 @@ void Screen::setScummvmPixelFormat(const Graphics::PixelFormat *format) { Graphics::Surface *Screen::lockAndGetForEditing() { DEBUG_ENTER_FUNC(); - _frameBuffer.pixels = _buffer.getPixels(); - _frameBuffer.w = _buffer.getSourceWidth(); - _frameBuffer.h = _buffer.getSourceHeight(); - _frameBuffer.pitch = _buffer.getBytesPerPixel() * _buffer.getWidth(); - _frameBuffer.format = _pixelFormat; + _frameBuffer.init(_buffer.getSourceWidth(), _buffer.getSourceHeight(), _buffer.getBytesPerPixel() * _buffer.getWidth(), + _buffer.getPixels(), _pixelFormat); // We'll set to dirty once we unlock the screen return &_frameBuffer; diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index fb8c1c60bf..8559066e53 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -349,7 +349,7 @@ bool OSystem_PSP::pollEvent(Common::Event &event) { return _inputHandler.getAllInputs(event); } -uint32 OSystem_PSP::getMillis() { +uint32 OSystem_PSP::getMillis(bool skipRecord) { return PspRtc::instance().getMillis(); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 2afdabd0fc..f4591e476d 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -125,7 +125,7 @@ public: bool processInput(Common::Event &event); // Time - uint32 getMillis(); + uint32 getMillis(bool skipRecord = false); void delayMillis(uint msecs); // Timer diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp index cbbb7d3f80..4f15e45535 100644 --- a/backends/platform/psp/rtc.cpp +++ b/backends/platform/psp/rtc.cpp @@ -52,7 +52,7 @@ void PspRtc::init() { // init our starting ticks // Note that after we fill up 32 bits ie 50 days we'll loop back to 0, which may cause // unpredictable results -uint32 PspRtc::getMillis() { +uint32 PspRtc::getMillis(bool skipRecord) { uint32 ticks[2]; sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays diff --git a/backends/platform/psp/rtc.h b/backends/platform/psp/rtc.h index 45885c3e66..d2689681dd 100644 --- a/backends/platform/psp/rtc.h +++ b/backends/platform/psp/rtc.h @@ -40,7 +40,7 @@ public: init(); } void init(); - uint32 getMillis(); + uint32 getMillis(bool skipRecord = false); uint32 getMicros(); }; diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp index 7a8b1e7b70..954f404ac6 100644 --- a/backends/platform/sdl/posix/posix.cpp +++ b/backends/platform/sdl/posix/posix.cpp @@ -80,15 +80,16 @@ bool OSystem_POSIX::hasFeature(Feature f) { } Common::String OSystem_POSIX::getDefaultConfigFileName() { - char configFile[MAXPATHLEN]; + Common::String configFile; // On POSIX type systems, by default we store the config file inside // to the HOME directory of the user. const char *home = getenv("HOME"); - if (home != NULL && strlen(home) < MAXPATHLEN) - snprintf(configFile, MAXPATHLEN, "%s/%s", home, _baseConfigName.c_str()); - else - strcpy(configFile, _baseConfigName.c_str()); + if (home != NULL && (strlen(home) + 1 + _baseConfigName.size()) < MAXPATHLEN) { + configFile = Common::String::format("%s/%s", home, _baseConfigName.c_str()); + } else { + configFile = _baseConfigName; + } return configFile; } diff --git a/backends/platform/sdl/sdl-sys.h b/backends/platform/sdl/sdl-sys.h index ca3c586e03..eccf73815d 100644 --- a/backends/platform/sdl/sdl-sys.h +++ b/backends/platform/sdl/sdl-sys.h @@ -35,8 +35,11 @@ // it with an alternate slightly less unfriendly override. #if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE) #undef FILE +// Solaris has typedef __FILE FILE in several places already +#if !defined(__sun) typedef struct { int FAKE; } FAKE_FILE; #define FILE FAKE_FILE +#endif // (__sun) #endif #if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp) diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index d54854352d..178eeb96af 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -30,7 +30,7 @@ #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" -#include "common/EventRecorder.h" +#include "gui/EventRecorder.h" #include "common/taskbar.h" #include "common/textconsole.h" @@ -65,10 +65,13 @@ OSystem_SDL::OSystem_SDL() : #ifdef USE_OPENGL - _graphicsModes(0), + _desktopWidth(0), + _desktopHeight(0), + _graphicsModes(), _graphicsMode(0), - _sdlModesCount(0), - _glModesCount(0), + _firstGLMode(0), + _defaultSDLMode(0), + _defaultGLMode(0), #endif _inited(false), _initedSDL(false), @@ -87,6 +90,9 @@ OSystem_SDL::~OSystem_SDL() { // Hence, we perform the destruction on our own. delete _savefileManager; _savefileManager = 0; + if (_graphicsManager) { + _graphicsManager->deactivateManager(); + } delete _graphicsManager; _graphicsManager = 0; delete _eventManager; @@ -97,15 +103,19 @@ OSystem_SDL::~OSystem_SDL() { _audiocdManager = 0; delete _mixerManager; _mixerManager = 0; + +#ifdef ENABLE_EVENTRECORDER + // HACK HACK HACK + // This is nasty. + delete g_eventRec.getTimerManager(); +#else delete _timerManager; +#endif + _timerManager = 0; delete _mutexManager; _mutexManager = 0; -#ifdef USE_OPENGL - delete[] _graphicsModes; -#endif - delete _logger; _logger = 0; @@ -116,6 +126,12 @@ void OSystem_SDL::init() { // Initialize SDL initSDL(); + // Enable unicode support if possible + SDL_EnableUNICODE(1); + + // Disable OS cursor + SDL_ShowCursor(SDL_DISABLE); + if (!_logger) _logger = new Backends::Log::Log(this); @@ -131,18 +147,11 @@ void OSystem_SDL::init() { if (_mutexManager == 0) _mutexManager = new SdlMutexManager(); - if (_timerManager == 0) - _timerManager = new SdlTimerManager(); - #if defined(USE_TASKBAR) if (_taskbarManager == 0) _taskbarManager = new Common::TaskbarManager(); #endif -#ifdef USE_OPENGL - // Setup a list with both SDL and OpenGL graphics modes - setupGraphicsModes(); -#endif } void OSystem_SDL::initBackend() { @@ -154,35 +163,41 @@ void OSystem_SDL::initBackend() { if (_eventSource == 0) _eventSource = new SdlEventSource(); - int graphicsManagerType = 0; +#ifdef USE_OPENGL + // Query the desktop resolution. We simply hope nothing tried to change + // the resolution so far. + const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); + if (videoInfo && videoInfo->current_w > 0 && videoInfo->current_h > 0) { + _desktopWidth = videoInfo->current_w; + _desktopHeight = videoInfo->current_h; + } +#endif if (_graphicsManager == 0) { #ifdef USE_OPENGL + // Setup a list with both SDL and OpenGL graphics modes. We only do + // this whenever the subclass did not already set up an graphics + // manager yet. This is because we don't know the type of the graphics + // manager of the subclass, thus we cannot easily switch between the + // OpenGL one and the set up one. It also is to be expected that the + // subclass does not want any switching of graphics managers anyway. + setupGraphicsModes(); + if (ConfMan.hasKey("gfx_mode")) { + // If the gfx_mode is from OpenGL, create the OpenGL graphics manager 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) { - _graphicsMode = i + _sdlModesCount; - use_opengl = true; + for (uint i = _firstGLMode; i < _graphicsModeIds.size(); ++i) { + if (!scumm_stricmp(_graphicsModes[i].name, gfxMode.c_str())) { + _graphicsManager = new OpenGLSdlGraphicsManager(_desktopWidth, _desktopHeight, _eventSource); + _graphicsMode = i; + break; } - - mode++; - ++i; - } - - // If the gfx_mode is from OpenGL, create the OpenGL graphics manager - if (use_opengl) { - _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource); - graphicsManagerType = 1; } } #endif + if (_graphicsManager == 0) { _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource); - graphicsManagerType = 0; } } @@ -191,11 +206,19 @@ void OSystem_SDL::initBackend() { if (_mixerManager == 0) { _mixerManager = new SdlMixerManager(); - // Setup and start mixer _mixerManager->init(); } +#ifdef ENABLE_EVENTRECORDER + g_eventRec.registerMixerManager(_mixerManager); + + g_eventRec.registerTimerManager(new SdlTimerManager()); +#else + if (_timerManager == 0) + _timerManager = new SdlTimerManager(); +#endif + if (_audiocdManager == 0) { // Audio CD support was removed with SDL 1.3 #if SDL_VERSION_ATLEAST(1, 3, 0) @@ -217,13 +240,7 @@ void OSystem_SDL::initBackend() { // so the virtual keyboard can be initialized, but we have to add the // graphics manager as an event observer after initializing the event // manager. - if (graphicsManagerType == 0) - ((SurfaceSdlGraphicsManager *)_graphicsManager)->initEventObserver(); -#ifdef USE_OPENGL - else if (graphicsManagerType == 1) - ((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver(); -#endif - + _graphicsManager->activateManager(); } #if defined(USE_TASKBAR) @@ -244,22 +261,19 @@ void OSystem_SDL::engineDone() { void OSystem_SDL::initSDL() { // Check if SDL has not been initialized if (!_initedSDL) { - uint32 sdlFlags = 0; + // We always initialize the video subsystem because we will need it to + // be initialized before the graphics managers to retrieve the desktop + // resolution, for example. WebOS also requires this initialization + // or otherwise the application won't start. + uint32 sdlFlags = SDL_INIT_VIDEO; + 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()); - // Enable unicode support if possible - SDL_EnableUNICODE(1); - _initedSDL = true; } } @@ -355,17 +369,6 @@ Common::String OSystem_SDL::getSystemLanguage() const { const LCID languageIdentifier = GetThreadLocale(); - // GetLocalInfo is only supported starting from Windows 2000, according to this: - // http://msdn.microsoft.com/en-us/library/dd318101%28VS.85%29.aspx - // On the other hand the locale constants used, seem to exist on Windows 98 too, - // check this for that: http://msdn.microsoft.com/en-us/library/dd464799%28v=VS.85%29.aspx - // - // I am not exactly sure what is the truth now, it might be very well that this breaks - // support for systems older than Windows 2000.... - // - // TODO: Check whether this (or ScummVM at all ;-) works on a system with Windows 98 for - // example and if it does not and we still want Windows 9x support, we should definitly - // think of another solution. if (GetLocaleInfo(languageIdentifier, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 && GetLocaleInfo(languageIdentifier, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) { Common::String localeName = langName; @@ -378,10 +381,15 @@ Common::String OSystem_SDL::getSystemLanguage() const { } #else // WIN32 // Activating current locale settings - const char *locale = setlocale(LC_ALL, ""); + const Common::String locale = setlocale(LC_ALL, ""); + + // Restore default C locale to prevent issues with + // portability of sscanf(), atof(), etc. + // See bug #3615148 + setlocale(LC_ALL, "C"); // Detect the language from the locale - if (!locale) { + if (locale.empty()) { return ModularBackend::getSystemLanguage(); } else { int length = 0; @@ -390,14 +398,14 @@ Common::String OSystem_SDL::getSystemLanguage() const { // ".UTF-8" or the like. We do this, since // our translation languages are usually // specified without any charset information. - for (int i = 0; locale[i]; ++i, ++length) { + for (int size = locale.size(); length < size; ++length) { // TODO: Check whether "@" should really be checked // here. - if (locale[i] == '.' || locale[i] == ' ' || locale[i] == '@') + if (locale[length] == '.' || locale[length] == ' ' || locale[length] == '@') break; } - return Common::String(locale, length); + return Common::String(locale.c_str(), length); } #endif // WIN32 #else // USE_DETECTLANG @@ -466,14 +474,21 @@ void OSystem_SDL::setupIcon() { free(icon); } -uint32 OSystem_SDL::getMillis() { + +uint32 OSystem_SDL::getMillis(bool skipRecord) { uint32 millis = SDL_GetTicks(); - g_eventRec.processMillis(millis); + +#ifdef ENABLE_EVENTRECORDER + g_eventRec.processMillis(millis, skipRecord); +#endif + return millis; } void OSystem_SDL::delayMillis(uint msecs) { - if (!g_eventRec.processDelayMillis(msecs)) +#ifdef ENABLE_EVENTRECORDER + if (!g_eventRec.processDelayMillis()) +#endif SDL_Delay(msecs); } @@ -491,39 +506,57 @@ void OSystem_SDL::getTimeAndDate(TimeDate &td) const { Audio::Mixer *OSystem_SDL::getMixer() { assert(_mixerManager); - return _mixerManager->getMixer(); + return getMixerManager()->getMixer(); } SdlMixerManager *OSystem_SDL::getMixerManager() { assert(_mixerManager); + +#ifdef ENABLE_EVENTRECORDER + return g_eventRec.getMixerManager(); +#else return _mixerManager; +#endif +} + +Common::TimerManager *OSystem_SDL::getTimerManager() { +#ifdef ENABLE_EVENTRECORDER + return g_eventRec.getTimerManager(); +#else + return _timerManager; +#endif } #ifdef USE_OPENGL const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const { - return _graphicsModes; + if (_graphicsModes.empty()) { + return _graphicsManager->getSupportedGraphicsModes(); + } else { + return _graphicsModes.begin(); + } } int OSystem_SDL::getDefaultGraphicsMode() const { - // Return the default graphics mode from the current graphics manager - if (_graphicsMode < _sdlModesCount) + if (_graphicsModes.empty()) { return _graphicsManager->getDefaultGraphicsMode(); - else - return _graphicsManager->getDefaultGraphicsMode() + _sdlModesCount; + } else { + // Return the default graphics mode from the current graphics manager + if (_graphicsMode < _firstGLMode) + return _defaultSDLMode; + else + return _defaultGLMode; + } } bool OSystem_SDL::setGraphicsMode(int mode) { - const OSystem::GraphicsMode *srcMode; - int i; + if (_graphicsModes.empty()) { + return _graphicsManager->setGraphicsMode(mode); + } - // Check if mode is from SDL or OpenGL - if (mode < _sdlModesCount) { - srcMode = SurfaceSdlGraphicsManager::supportedGraphicsModes(); - i = 0; - } else { - srcMode = OpenGLSdlGraphicsManager::supportedGraphicsModes(); - i = _sdlModesCount; + // Check whether a invalid mode is requested. + if (mode < 0 || (uint)mode >= _graphicsModeIds.size()) { + return false; } // Very hacky way to set up the old graphics manager state, in case we @@ -542,113 +575,121 @@ bool OSystem_SDL::setGraphicsMode(int mode) { bool switchedManager = false; - // 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 SurfaceSdlGraphicsManager(_eventSource); - ((SurfaceSdlGraphicsManager *)_graphicsManager)->initEventObserver(); - _graphicsManager->beginGFXTransaction(); - - switchedManager = true; - } else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) { - debug(1, "switching to OpenGL graphics"); - delete _graphicsManager; - _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource); - ((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver(); - _graphicsManager->beginGFXTransaction(); - - switchedManager = true; - } + // 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 >= _firstGLMode && mode < _firstGLMode) { + debug(1, "switching to plain SDL graphics"); + _graphicsManager->deactivateManager(); + delete _graphicsManager; + _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource); + + switchedManager = true; + } else if (_graphicsMode < _firstGLMode && mode >= _firstGLMode) { + debug(1, "switching to OpenGL graphics"); + _graphicsManager->deactivateManager(); + delete _graphicsManager; + _graphicsManager = new OpenGLSdlGraphicsManager(_desktopWidth, _desktopHeight, _eventSource); + + switchedManager = true; + } + + _graphicsMode = mode; - _graphicsMode = mode; + if (switchedManager) { + _graphicsManager->activateManager(); - if (switchedManager) { + _graphicsManager->beginGFXTransaction(); #ifdef USE_RGB_COLOR - _graphicsManager->initSize(screenWidth, screenHeight, &pixelFormat); + _graphicsManager->initSize(screenWidth, screenHeight, &pixelFormat); #else - _graphicsManager->initSize(screenWidth, screenHeight, 0); + _graphicsManager->initSize(screenWidth, screenHeight, 0); #endif - _graphicsManager->setFeatureState(kFeatureAspectRatioCorrection, arState); - _graphicsManager->setFeatureState(kFeatureFullscreenMode, fullscreen); - _graphicsManager->setFeatureState(kFeatureCursorPalette, cursorPalette); + _graphicsManager->setFeatureState(kFeatureAspectRatioCorrection, arState); + _graphicsManager->setFeatureState(kFeatureFullscreenMode, fullscreen); + _graphicsManager->setFeatureState(kFeatureCursorPalette, cursorPalette); - // Worst part about this right now, tell the cursor manager to - // resetup the cursor + cursor palette if necessarily + // Worst part about this right now, tell the cursor manager to + // resetup the cursor + cursor palette if necessarily - // First we need to try to setup the old state on the new manager... - if (_graphicsManager->endGFXTransaction() != kTransactionSuccess) { - // Oh my god if this failed the client code might just explode. - return false; - } - - // Next setup the cursor again - CursorMan.pushCursor(0, 0, 0, 0, 0, 0); - CursorMan.popCursor(); + // First we need to try to setup the old state on the new manager... + if (_graphicsManager->endGFXTransaction() != kTransactionSuccess) { + // Oh my god if this failed the client code might just explode. + return false; + } - // Next setup cursor palette if needed - if (cursorPalette) { - CursorMan.pushCursorPalette(0, 0, 0); - CursorMan.popCursorPalette(); - } + // Next setup the cursor again + CursorMan.pushCursor(0, 0, 0, 0, 0, 0); + CursorMan.popCursor(); - _graphicsManager->beginGFXTransaction(); - // Oh my god if this failed the client code might just explode. - return _graphicsManager->setGraphicsMode(srcMode->id); - } else { - return _graphicsManager->setGraphicsMode(srcMode->id); - } + // Next setup cursor palette if needed + if (cursorPalette) { + CursorMan.pushCursorPalette(0, 0, 0); + CursorMan.popCursorPalette(); } - i++; - srcMode++; + _graphicsManager->beginGFXTransaction(); + // Oh my god if this failed the client code might just explode. + return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]); + } else { + return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]); } - - return false; } int OSystem_SDL::getGraphicsMode() const { - return _graphicsMode; + if (_graphicsModes.empty()) { + return _graphicsManager->getGraphicsMode(); + } else { + return _graphicsMode; + } } void OSystem_SDL::setupGraphicsModes() { - const OSystem::GraphicsMode *sdlGraphicsModes = SurfaceSdlGraphicsManager::supportedGraphicsModes(); - const OSystem::GraphicsMode *openglGraphicsModes = OpenGLSdlGraphicsManager::supportedGraphicsModes(); - _sdlModesCount = 0; - _glModesCount = 0; + _graphicsModes.clear(); + _graphicsModeIds.clear(); + _defaultSDLMode = _defaultGLMode = -1; // Count the number of graphics modes - const OSystem::GraphicsMode *srcMode = sdlGraphicsModes; + const OSystem::GraphicsMode *srcMode; + int defaultMode; + + GraphicsManager *manager = new SurfaceSdlGraphicsManager(_eventSource); + srcMode = manager->getSupportedGraphicsModes(); + defaultMode = manager->getDefaultGraphicsMode(); while (srcMode->name) { - _sdlModesCount++; + if (defaultMode == srcMode->id) { + _defaultSDLMode = _graphicsModes.size(); + } + _graphicsModes.push_back(*srcMode); srcMode++; } - srcMode = openglGraphicsModes; + delete manager; + assert(_defaultSDLMode != -1); + + _firstGLMode = _graphicsModes.size(); + manager = new OpenGLSdlGraphicsManager(_desktopWidth, _desktopHeight, _eventSource); + srcMode = manager->getSupportedGraphicsModes(); + defaultMode = manager->getDefaultGraphicsMode(); while (srcMode->name) { - _glModesCount++; + if (defaultMode == srcMode->id) { + _defaultGLMode = _graphicsModes.size(); + } + _graphicsModes.push_back(*srcMode); srcMode++; } - - // Allocate enough space for merged array of modes - _graphicsModes = new OSystem::GraphicsMode[_glModesCount + _sdlModesCount + 1]; - - // Copy SDL graphics modes - memcpy((void *)_graphicsModes, sdlGraphicsModes, _sdlModesCount * sizeof(OSystem::GraphicsMode)); - - // Copy OpenGL graphics modes - memcpy((void *)(_graphicsModes + _sdlModesCount), openglGraphicsModes, _glModesCount * sizeof(OSystem::GraphicsMode)); + delete manager; + manager = nullptr; + assert(_defaultGLMode != -1); // Set a null mode at the end - memset((void *)(_graphicsModes + _sdlModesCount + _glModesCount), 0, sizeof(OSystem::GraphicsMode)); + GraphicsMode nullMode; + memset(&nullMode, 0, sizeof(nullMode)); + _graphicsModes.push_back(nullMode); // Set new internal ids for all modes int i = 0; - OSystem::GraphicsMode *mode = _graphicsModes; + OSystem::GraphicsMode *mode = _graphicsModes.begin(); while (mode->name) { + _graphicsModeIds.push_back(mode->id); mode->id = i++; mode++; } diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index f05207b482..814cdd7c1b 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -30,6 +30,8 @@ #include "backends/events/sdl/sdl-events.h" #include "backends/log/log.h" +#include "common/array.h" + /** * Base OSystem class for all SDL ports. */ @@ -68,10 +70,11 @@ public: virtual void setWindowCaption(const char *caption); virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual void getTimeAndDate(TimeDate &td) const; virtual Audio::Mixer *getMixer(); + virtual Common::TimerManager *getTimerManager(); protected: bool _inited; @@ -105,15 +108,20 @@ protected: Backends::Log::Log *_logger; #ifdef USE_OPENGL - OSystem::GraphicsMode *_graphicsModes; + int _desktopWidth, _desktopHeight; + + typedef Common::Array<GraphicsMode> GraphicsModeArray; + GraphicsModeArray _graphicsModes; + Common::Array<int> _graphicsModeIds; int _graphicsMode; - int _sdlModesCount; - int _glModesCount; + int _firstGLMode; + int _defaultSDLMode; + int _defaultGLMode; /** * Creates the merged graphics modes list */ - virtual void setupGraphicsModes(); + void setupGraphicsModes(); virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl index ffc4e88aff..2f76acf012 100644 --- a/backends/platform/symbian/AdaptAllMMPs.pl +++ b/backends/platform/symbian/AdaptAllMMPs.pl @@ -44,6 +44,15 @@ chdir("../../../"); "mmp/scummvm_toltecs.mmp", "mmp/scummvm_pegasus.mmp", "mmp/scummvm_wintermute.mmp", + # New engines + "mmp/scummvm_avalanche.mmp", + "mmp/scummvm_dreamweb.mmp", + "mmp/scummvm_fullpipe.mmp", + "mmp/scummvm_mortevielle.mmp", + "mmp/scummvm_neverhood.mmp", + "mmp/scummvm_sword25.mmp", + "mmp/scummvm_testbed.mmp", + "mmp/scummvm_zvision.mmp", # Target Platform Project Files "S60/ScummVM_S60.mmp", "S60v3/ScummVM_S60v3.mmp", @@ -79,10 +88,14 @@ Preparing to update all the Symbian MMP project files with objects from module.m # some modules.mk files have #ifndef ENABLE_XXXX blocks: my @section_empty = (""); # section standard: no #ifdef's in module.mk files -my @sections_scumm = ("", "ENABLE_SCUMM_7_8", "ENABLE_HE"); # special sections for engine SCUMM -my @sections_saga = ("", "ENABLE_IHNM", "ENABLE_SAGA2"); # special sections for engine SAGA -my @sections_kyra = ("", "ENABLE_LOL","ENABLE_EOB"); # special sections for engine KYRA my @sections_agos = ("", "ENABLE_AGOS2"); # special sections for engine AGOS +my @section_video = ("", "USE_BINK", "USE_MPEG2"); # special sections for engine VIDEO ###, "USE_THEORADEC" +my @sections_groovie = ("", "ENABLE_GROOVIE2"); # special sections for engine GROOVIE +my @sections_kyra = ("", "ENABLE_LOL","ENABLE_EOB"); # special sections for engine KYRA +my @sections_mohawk = ("", "ENABLE_CSTIME", "ENABLE_MYST", "ENABLE_RIVEN"); # special sections for engine MOHAWK +my @sections_saga = ("", "ENABLE_IHNM", "ENABLE_SAGA2"); # special sections for engine SAGA +my @sections_sci = ("", "ENABLE_SCI32"); # special sections for engine SCI +my @sections_scumm = ("", "ENABLE_SCUMM_7_8", "ENABLE_HE"); # special sections for engine SCUMM # files excluded from build, case insensitive, will be matched in filename string only my @excludes_snd = ( @@ -126,13 +139,13 @@ my @excludes_scumm = ( ); -#arseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray]) +#ParseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray]) ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, these never change anyways... ParseModule("_base", "common", \@section_empty); ParseModule("_base", "gui", \@section_empty, \@excludes_gui); ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics); ParseModule("_base", "audio", \@section_empty, \@excludes_snd); -ParseModule("_base", "video", \@section_empty); +ParseModule("_base", "video", \@section_video); # chdir("engines/"); ParseModule("_scumm", "scumm", \@sections_scumm, \@excludes_scumm ); @@ -156,21 +169,30 @@ ParseModule("_drascula","drascula", \@section_empty); ParseModule("_made", "made", \@section_empty); ParseModule("_m4", "m4", \@section_empty); ParseModule("_tinsel", "tinsel", \@section_empty); -ParseModule("_groovie", "groovie", \@section_empty); +ParseModule("_groovie", "groovie", \@sections_groovie); ParseModule("_tucker", "tucker", \@section_empty); -ParseModule("_sci", "sci", \@section_empty); +ParseModule("_sci", "sci", \@sections_sci); ParseModule("_draci", "draci", \@section_empty); ParseModule("_teenagent","teenagent", \@section_empty); -ParseModule("_mohawk" ,"mohawk", \@section_empty); +ParseModule("_mohawk" ,"mohawk", \@sections_mohawk); ParseModule("_hugo" ,"hugo", \@section_empty); ParseModule("_toon" ,"toon", \@section_empty); ParseModule("_lastexpress","lastexpress", \@section_empty); ParseModule("_tsage","tsage", \@section_empty); -ParseModule("_tony","tony", \@section_empty); +ParseModule("_tony", "tony", \@section_empty); ParseModule("_toltecs","toltecs", \@section_empty); ParseModule("_hopkins","hopkins", \@section_empty); ParseModule("_pegasus","pegasus", \@section_empty); ParseModule("_wintermute","wintermute", \@section_empty); +##### new engines +ParseModule("_avalanche" ,"avalanche", \@section_empty); +ParseModule("_dreamweb" ,"dreamweb", \@section_empty); +ParseModule("_fullpipe" ,"fullpipe", \@section_empty); +ParseModule("_mortevielle" ,"mortevielle", \@section_empty); +ParseModule("_neverhood" ,"neverhood", \@section_empty); +ParseModule("_sword25" ,"sword25", \@section_empty); +ParseModule("_testbed" ,"testbed", \@section_empty); +ParseModule("_zvision" ,"zvision", \@section_empty); print " ======================================================================================= Done. Enjoy :P diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl index 3062068852..560439f4e1 100644 --- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl +++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl @@ -1,6 +1,7 @@ use Cwd; use Switch; +#use feature "switch"; system("cls"); require "BuildPackageUpload_LocalSettings.pl"; @@ -59,9 +60,13 @@ $ftp_url = "FTP://$FTP_User\@$FTP_Host/$FTP_Dir/"; # these macros are always defined: $ExtraMacros = "MACRO NONSTANDARD_PORT\n"; -$ExtraMacros .= "MACRO ENABLE_VKEYBD\n"; +$ExtraMacros .= "MACRO ENABLE_VKEYBD\n"; $ExtraMacros .= "MACRO DISABLE_FANCY_THEMES\n"; $ExtraMacros .= "MACRO USE_TRANSLATION\n"; +$ExtraMacros .= "MACRO USE_BINK\n"; +$ExtraMacros .= "MACRO USE_MPEG2\n"; +# $ExtraMacros .= "MACRO \n"; +# candidates are : , USE_TIMIDITY, # prep nice list of SDKs #while( ($SDK, $RootDir) = each(%SDK_RootDirs) ) diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl index ded4ef198f..4ff485b3e3 100644 --- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl +++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl @@ -2,24 +2,33 @@ ################################################################################################################## @WorkingEngines = qw( - scumm agos sky queen gob groovie saga drascula - kyra lure agi touche parallaction cine - cruise made tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo toon lastexpress tsage cge - composer toltecs tony wintermute pegasus + agos agi cine cge composer cruise draci + drascula hugo gob groovie kyra lastexpress + lure made mohawk parallaction pegasus queen + saga sci scumm sky sword1 sword2 teenagent tinsel + toltecs tony toon touche tsage tucker wintermute + dreamweb fullpipe hopkins mortevielle + neverhood testbed avalanche zvision ); +#### New engines +#### sword25 @WorkingEngines_1st = qw( - scumm queen groovie saga drascula - touche parallaction cine -? cruise made tucker lastexpress composer wintermute + cine composer cruise drascula groovie + lastexpress made parallaction queen + saga scumm touche tucker wintermute + avalanche zvision ); @WorkingEngines_2nd = qw( - agos sky gob kyra lure - agi tinsel sword1 sword2 - draci sci teenagent hugo toon - tsage cge toltecs tony pegasus + agi agos cge draci gob hopkins + hugo kyra lure mohawk pegasus sci + sky sword1 sword2 teenagent + tinsel tsage toltecs tony toon + dreamweb fullpipe mortevielle + neverhood testbed ); +#### sword25 @TestingEngines = qw( @@ -34,20 +43,32 @@ lol agos2 eob + cstime + myst + riven + saga2 + sci32 + groovie2 ); #disabled subengines lol saga2 personal nightmare + # see configure.engines %UseableFeatures = ( 'zlib' => 'zlib.lib', 'mad' => 'libmad.lib', 'tremor' => 'libtremor.lib', - 'flac' => 'libflac.lib' + 'flac' => 'libflacdec.lib', + 'freetype2' => 'freetype.lib', + 'faad' => 'libFAAD2.lib', + 'mpeg2' => 'libmpeg2.lib' ); + # 'mpeg2' => 'libmpeg2.lib' # these are normally enabled for each variation #$DefaultFeatures = qw(zlib,mad); - $DefaultFeatures = qw(zlib,mad,tremor,flac); + #$DefaultFeatures = qw(zlib,mad,tremor,); + $DefaultFeatures = qw(mad,tremor,faad,flac,freetype2,mpeg2,zlib,); ################################################################################################################## ## @@ -64,7 +85,8 @@ $HaltOnError = 0; $SkipExistingPackages = 0; $ReallyQuiet = 0; - $DevBase = "C:\\S"; + $DevBase = "D:\\Symbian"; + $Compiler = "D:\\Program/ Files\\CodeSourcery\\Sourcery/ G++ Lite"; # specify an optional FTP server to upload to after each Build+Package (can leave empty) #$FTP_Host = "host.com"; @@ -77,14 +99,14 @@ # Note1: the \epoc32 directory needs to be in these rootdirs # Note2: these paths do NOT end in a backslash! # $SDK_RootDirs{'UIQ2'} = "$DevBase\\UIQ_21"; - $SDK_RootDirs{'UIQ3'} = "$DevBase\\UIQ3"; + # $SDK_RootDirs{'UIQ3'} = "$DevBase\\UIQ3"; # $SDK_RootDirs{'S60v1'} = "$DevBase\\S60v1"; # $SDK_RootDirs{'S60v2'} = "$DevBase\\S60v2"; $SDK_RootDirs{'S60v3'} = "$DevBase\\S60v3"; # $SDK_RootDirs{'S80'} = "$DevBase\\S80"; # $SDK_RootDirs{'S90'} = "$DevBase\\S90"; - $SDK_ToolchainDirs{'S60v3'} = "$DevBase\\arm-symbianelf\\bin"; + $SDK_ToolchainDirs{'S60v3'} = "$Compiler\\arm-symbianelf\\bin"; $SDK_ToolchainDirs{'UIQ2'} = "$DevBase\\ECompXL\\bin"; # only needed for UIQ2/UIQ3 $SDK_ToolchainDirs{'UIQ3'} = "$DevBase\\ECompXL\\bin"; # only needed for UIQ2/UIQ3 @@ -94,7 +116,7 @@ { ## Standard libraries $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "$DevBase\\zlib-1.2.2\\epoc"; - #$SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "$DevBase\\libmad-0.15.1b\\group"; + $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "$DevBase\\libmad-0.15.1b\\group"; $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "$DevBase\\tremor\\epoc"; ## SDL 1.2.12 / AnotherGuest / Symbian version @@ -186,7 +208,7 @@ # now you can add $VariationSets only built on this PC below this line :) } - elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-LAPE") ################################################################# + elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-VAIO2") ################################################################# { $Producer = "AnotherGuest"; $RedirectSTDERR = 1; @@ -206,7 +228,7 @@ $SDK_RootDirs{'S60v3'}= "G:\\S60v3"; #$SDK_RootDirs{'S80'}= "D:\\S80"; #$SDK_RootDirs{'S90'}= "D:\\S90"; - $ECompXL_BinDir= "D:\\ECompXL\\"; + #$ECompXL_BinDir= "D:\\ECompXL\\"; if (0) # so we can turn them on/off easily { # $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc"; @@ -223,38 +245,42 @@ # now you can add $VariationSets only built on this PC below this line :) } - elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV_VAIO1") ################################################################# + elsif ($ENV{'COMPUTERNAME'} eq "PC-FOREVER1111") ################################################################# { - $Producer = "AnotherGuest"; + $Producer = "Fedor"; $RedirectSTDERR = 1; $HaltOnError = 0; - $SkipExistingPackages = 1; - $ReallyQuiet = 1; + $SkipExistingPackages = 0; + $ReallyQuiet = 0; + $Compiler = "D:\\Program/ Files\\CodeSourcery\\Sourcery/ G++ Lite"; #$FTP_Host = "host.com"; #$FTP_User = "ag@host.com"; #$FTP_Pass = "password"; #$FTP_Dir = "cvsbuilds"; - #$SDK_RootDirs{'UIQ2'}= "D:\\UIQ2"; - $SDK_RootDirs{'UIQ3'}= "G:\\UIQ3"; - #$SDK_RootDirs{'S60v1'}= "D:\\S60v1"; - #$SDK_RootDirs{'S60v2'}= "D:\\S60v2"; - $SDK_RootDirs{'S60v3'}= "G:\\S60v3"; - #$SDK_RootDirs{'S80'}= "D:\\S80"; - #$SDK_RootDirs{'S90'}= "D:\\S90"; - #$ECompXL_BinDir= "D:\\ECompXL\\"; + #$SDK_RootDirs{'UIQ2'}= "C:\\UIQ2"; + #$SDK_RootDirs{'UIQ3'}= "C:\\UIQ3"; + #$SDK_RootDirs{'S60v1'}= "C:\\S60v1"; + #$SDK_RootDirs{'S60v2'}= "C:\\S60v2"; + #$SDK_RootDirs{'S80'}= "C:\\S80"; + #$SDK_RootDirs{'S90'}= "C:\\S90"; + #$ECompXL_BinDir= "C:\\ECompXL\\"; + + $SDK_RootDirs{'S60v3'}= "D:\\Symbian\\S60_5th_Edition_SDK_v1.0"; + $SDK_ToolchainDirs{'S60v3'} = "$Compiler\\arm-symbianelf\\bin"; + + # these supporting libraries get built first, then all the Variations + # Note: the string {'xxx.lib'} is used in checking in build success: so needs to be accurate! if (0) # so we can turn them on/off easily { # $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc"; -# $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "C:\\S\\libmad-0.15.1b\\group"; -# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "C:\\tremor\\epoc"; - $SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ"; - $SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60"; - $SDK_LibraryDirs{'S80'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S80"; - $SDK_LibraryDirs{'S90'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S90"; - $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60\\S60V3"; - $SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ\\UIQ3"; + $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "D:\\Symbian\\Projects\\SDL\\libs\\libmad-0.15.1b\\epoc"; +# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "D:\\Symbian\\Projects\\SDL\\libs\\Tremor\\epoc"; +# $SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = $SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\UIQ"; +# $SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\S60"; +# $SDK_LibraryDirs{'S80'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\S80"; +# $SDK_LibraryDirs{'S90'}{'esdl.lib'} = "C:\\S\\ESDL\\epoc\\S90"; } # now you can add $VariationSets only built on this PC below this line :) @@ -298,8 +324,8 @@ # the first one includes all SDKs & release-ready engines $VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines"; -# $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines"; -# $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines"; + # $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines"; + # $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines"; # now one for each ready-for-release engine if (0) { diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README index 58cbc7814a..3c4fbb9d7d 100644 --- a/backends/platform/symbian/README +++ b/backends/platform/symbian/README @@ -2,7 +2,8 @@ ScummVM - ScummVM ported to EPOC/SymbianOS Copyright (C) 2008-2013 ScummVM Team - Copyright (C) 2003-2008 Lars 'AnotherGuest' Persson + Copyright (C) 2013-2013 Fedor Strizniou aka zanac + Copyright (C) 2003-2013 Lars 'AnotherGuest' Persson Copyright (C) 2002-2008 Jurgen 'SumthinWicked' Braam Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson @@ -24,6 +25,15 @@ About ScummVM Jurgen and Lars have successfully transfered all needed changes into CVS/SVN, with additional helpful tools for Symbian OS Release History: +Release version: 1.7.0 + * Nothing significant in the Symbian port, except SDL improvements (new SDL version used) + +Release version: 1.6.0 + * Nothing significant in the Symbian port, except SDL improvements (new SDL version used) + + Release version: 1.5.0 + * Nothing significant in the Symbian port, except SDL improvements (new SDL version used) + Release version: 1.4.0 * Nothing significant in the Symbian port, except SDL improvements (new SDL version used) * See main readme for general ScummVM improvements, major update diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg index 4c6b1b05f8..a5920ae823 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg @@ -33,7 +33,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM S60v3"},(0xA0000657),1,60,0 +#{"ScummVM S60v3"},(0xA0000657),1,70,0 ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} @@ -58,18 +58,46 @@ "..\..\..\..\NEWS"-"!:\resource\apps\scummvm\NEWS" ; Common datafiles needed for some games -"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat" -"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt" +"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat" "..\..\..\..\dists\engine-data\hugo.dat"-"c:\data\scummvm\hugo.dat" +"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat" "..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat" -"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat" +"..\..\..\..\dists\engine-data\mort.dat"-"c:\data\scummvm\mort.dat" +"..\..\..\..\dists\engine-data\neverhood.dat"-"c:\data\scummvm\neverhood.dat" +"..\..\..\..\dists\engine-data\queen.tbl"-"c:\data\scummvm\queen.tbl" +"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt" "..\..\..\..\dists\engine-data\teenagent.dat"-"c:\data\scummvm\teenagent.dat" +"..\..\..\..\dists\engine-data\tony.dat"-"c:\data\scummvm\tony.dat" "..\..\..\..\dists\engine-data\toon.dat"-"c:\data\scummvm\toon.dat" "..\..\..\..\dists\engine-data\wintermute.zip"-"c:\data\scummvm\wintermute.zip" -"..\..\..\..\dists\engine-data\tony.dat"-"c:\data\scummvm\tony.dat" "..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip" "..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat" "..\..\..\..\gui\themes\scummmodern.zip"-"c:\data\scummvm\scummmodern.zip" +"..\..\..\..\gui\themes\fonts\Arial.bdf"-"c:\data\scummvm\Arial.bdf" +"..\..\..\..\gui\themes\fonts\Arial12.bdf"-"c:\data\scummvm\Arial12.bdf" +"..\..\..\..\gui\themes\fonts\ArialBold.bdf"-"c:\data\scummvm\ArialBold.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-1.bdf"-"c:\data\scummvm\clR6x12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-2.bdf"-"c:\data\scummvm\clR6x12-iso-8859-2.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-5.bdf"-"c:\data\scummvm\clR6x12-iso-8859-5.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-7.bdf"-"c:\data\scummvm\clR6x12-iso-8859-7.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12.bdf"-"c:\data\scummvm\clR6x12.bdf" +"..\..\..\..\gui\themes\fonts\courr12-iso-8859-1.bdf"-"c:\data\scummvm\courr12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-1.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-5.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-5.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-7.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-7.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8.bdf"-"c:\data\scummvm\fixed5x8.bdf" +"..\..\..\..\gui\themes\fonts\FreeMonoBold.ttf"-"c:\data\scummvm\FreeMonoBold.ttf" +"..\..\..\..\gui\themes\fonts\FreeSans.ttf"-"c:\data\scummvm\FreeSans.ttf" +"..\..\..\..\gui\themes\fonts\FreeSansBold.ttf"-"c:\data\scummvm\FreeSansBold.ttf" +"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-1.bdf"-"c:\data\scummvm\helvB12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-2.bdf"-"c:\data\scummvm\helvB12-iso-8859-2.bdf" +"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-5.bdf"-"c:\data\scummvm\helvB12-iso-8859-5.bdf" +"..\..\..\..\gui\themes\fonts\helvB12.bdf"-"c:\data\scummvm\helvB12.bdf" +"..\..\..\..\gui\themes\fonts\helvBO12-iso-8859-1.bdf"-"c:\data\scummvm\helvBO12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\helvBO12.bdf"-"c:\data\scummvm\helvBO12.bdf" +"..\..\..\..\gui\themes\fonts\helvR12-iso-8859-1.bdf"-"c:\data\scummvm\helvR12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\helvR12.bdf"-"c:\data\scummvm\helvR12.bdf" +;"..\..\..\..\gui\themes\"-"c:\data\scummvm\" ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\data\scummvm\scummvm.ini",FILENULL diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg index d3fd0450fa..c71805fb9f 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3_split.pkg @@ -36,7 +36,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM S60v3"},(0xA0000657),1,60,0 +#{"ScummVM S60v3"},(0xA0000657),1,70,0 ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} @@ -66,18 +66,45 @@ "..\..\..\..\NEWS"-"!:\resource\apps\scummvm\NEWS" ; Common datafiles needed for some games -"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat" -"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt" +"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat" "..\..\..\..\dists\engine-data\hugo.dat"-"c:\data\scummvm\hugo.dat" +"..\..\..\..\dists\engine-data\kyra.dat"-"c:\data\scummvm\kyra.dat" "..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat" -"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat" +"..\..\..\..\dists\engine-data\mort.dat"-"c:\data\scummvm\mort.dat" +"..\..\..\..\dists\engine-data\neverhood.dat"-"c:\data\scummvm\neverhood.dat" +"..\..\..\..\dists\engine-data\queen.tbl"-"c:\data\scummvm\queen.tbl" +"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt" "..\..\..\..\dists\engine-data\teenagent.dat"-"c:\data\scummvm\teenagent.dat" +"..\..\..\..\dists\engine-data\tony.dat"-"c:\data\scummvm\tony.dat" "..\..\..\..\dists\engine-data\toon.dat"-"c:\data\scummvm\toon.dat" -"..\..\..\..\dists\engine-data\wintermute.zip-"c:\data\scummvm\wintermute.zip" -"..\..\..\..\dists\engine-data\tony.dat-"c:\data\scummvm\tony.dat" +"..\..\..\..\dists\engine-data\wintermute.zip"-"c:\data\scummvm\wintermute.zip" "..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip" "..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat" "..\..\..\..\gui\themes\scummmodern.zip"-"c:\data\scummvm\scummmodern.zip" +"..\..\..\..\gui\themes\fonts\Arial.bdf"-"c:\data\scummvm\Arial.bdf" +"..\..\..\..\gui\themes\fonts\Arial12.bdf"-"c:\data\scummvm\Arial12.bdf" +"..\..\..\..\gui\themes\fonts\ArialBold.bdf"-"c:\data\scummvm\ArialBold.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-1.bdf"-"c:\data\scummvm\clR6x12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-2.bdf"-"c:\data\scummvm\clR6x12-iso-8859-2.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-5.bdf"-"c:\data\scummvm\clR6x12-iso-8859-5.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12-iso-8859-7.bdf"-"c:\data\scummvm\clR6x12-iso-8859-7.bdf" +"..\..\..\..\gui\themes\fonts\clR6x12.bdf"-"c:\data\scummvm\clR6x12.bdf" +"..\..\..\..\gui\themes\fonts\courr12-iso-8859-1.bdf"-"c:\data\scummvm\courr12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-1.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-5.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-5.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8-iso-8859-7.bdf"-"c:\data\scummvm\fixed5x8-iso-8859-7.bdf" +"..\..\..\..\gui\themes\fonts\fixed5x8.bdf"-"c:\data\scummvm\fixed5x8.bdf" +"..\..\..\..\gui\themes\fonts\FreeMonoBold.ttf"-"c:\data\scummvm\FreeMonoBold.ttf" +"..\..\..\..\gui\themes\fonts\FreeSans.ttf"-"c:\data\scummvm\FreeSans.ttf" +"..\..\..\..\gui\themes\fonts\FreeSansBold.ttf"-"c:\data\scummvm\FreeSansBold.ttf" +"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-1.bdf"-"c:\data\scummvm\helvB12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-2.bdf"-"c:\data\scummvm\helvB12-iso-8859-2.bdf" +"..\..\..\..\gui\themes\fonts\helvB12-iso-8859-5.bdf"-"c:\data\scummvm\helvB12-iso-8859-5.bdf" +"..\..\..\..\gui\themes\fonts\helvB12.bdf"-"c:\data\scummvm\helvB12.bdf" +"..\..\..\..\gui\themes\fonts\helvBO12-iso-8859-1.bdf"-"c:\data\scummvm\helvBO12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\helvBO12.bdf"-"c:\data\scummvm\helvBO12.bdf" +"..\..\..\..\gui\themes\fonts\helvR12-iso-8859-1.bdf"-"c:\data\scummvm\helvR12-iso-8859-1.bdf" +"..\..\..\..\gui\themes\fonts\helvR12.bdf"-"c:\data\scummvm\helvR12.bdf" ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\data\scummvm\scummvm.ini",FILENULL diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg index c62d25dafa..b4f1cfdd5c 100644 --- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg +++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg @@ -32,7 +32,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM UIQ3"},(0xA0000657),1,60,0 +#{"ScummVM UIQ3"},(0xA0000657),1,70,0 ; ProductID for UIQ 3.0 ; Product/platform version UID, Major, Minor, Build, Product ID diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg index a37e0b0533..722e23a1b8 100644 --- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg +++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3_split.pkg @@ -35,7 +35,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM UIQ3"},(0xA0000657),1,60,0 +#{"ScummVM UIQ3"},(0xA0000657),1,70,0 ; ProductID for UIQ 3.0 ; Product/platform version UID, Major, Minor, Build, Product ID diff --git a/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in new file mode 100644 index 0000000000..12f157f1e7 --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in @@ -0,0 +1,62 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_avalanche.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\avalanche + +//START_AUTO_OBJECTS_AVALANCHE_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_AVALANCHE_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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 d6dfafd014..bf12bffb41 100644 --- a/backends/platform/symbian/mmp/scummvm_base.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in @@ -50,15 +50,15 @@ ALWAYS_BUILD_AS_ARM USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio USERINCLUDE ..\..\..\..\backends\fs ..\src ..\..\..\..\backends\platform\sdl +USERINCLUDE \epoc32\include\mpeg2dec //\epoc32\include\theora +SYSTEMINCLUDE \epoc32\include\freetype +SYSTEMINCLUDE \epoc32\include\mpeg2dec SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc SYSTEMINCLUDE \epoc32\include\tremor SYSTEMINCLUDE \epoc32\include -SYSTEMINCLUDE \epoc32\include\mw -SYSTEMINCLUDE \epoc32\include\platform -SYSTEMINCLUDE \epoc32\include\platform\mw SYSTEMINCLUDE ..\src // for portdefs.h // *** SOURCE files @@ -115,6 +115,9 @@ SOURCEPATH ..\..\..\..\video //STOP_AUTO_OBJECTS_VIDEO_// // add a few files manually, since they are not parsed from modules.mk files +SOURCE bink_decoder.cpp +SOURCE codecs\mpeg.cpp + SOURCEPATH ..\..\..\.. SOURCE backends\events\default\default-events.cpp SOURCE backends\timer\default\default-timer.cpp diff --git a/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in b/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in new file mode 100644 index 0000000000..b6369b7d2b --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_dreamweb.mmp.in @@ -0,0 +1,62 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_dreamweb.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\dreamweb + +//START_AUTO_OBJECTS_DREAMWEB_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_DREAMWEB_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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_fullpipe.mmp.in b/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in new file mode 100644 index 0000000000..4a8f69f709 --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_fullpipe.mmp.in @@ -0,0 +1,62 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_fullpipe.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\fullpipe + +//START_AUTO_OBJECTS_FULLPIPE_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_FULLPIPE_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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 5772bfaad0..124f7c0dc3 100644 --- a/backends/platform/symbian/mmp/scummvm_kyra.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_kyra.mmp.in @@ -59,6 +59,13 @@ SOURCEPATH ..\..\..\..\engines\kyra //STOP_AUTO_OBJECTS_KYRA_ENABLE_LOL// + +//START_AUTO_OBJECTS_KYRA_ENABLE_EOB// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_KYRA_ENABLE_EOB// + // *** Include paths USERINCLUDE ..\..\..\..\engines diff --git a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in index 5f7bd4e144..3fe9af68f6 100644 --- a/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_mohawk.mmp.in @@ -53,6 +53,25 @@ SOURCEPATH ..\..\..\..\engines\mohawk //STOP_AUTO_OBJECTS_MOHAWK_// + +//START_AUTO_OBJECTS_MOHAWK_ENABLE_MYST// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_MOHAWK_ENABLE_MYST// + +//START_AUTO_OBJECTS_MOHAWK_ENABLE_RIVEN// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_MOHAWK_ENABLE_RIVEN// + +//START_AUTO_OBJECTS_MOHAWK_ENABLE_CSTIME// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_MOHAWK_ENABLE_CSTIME// + // *** Include paths USERINCLUDE ..\..\..\..\engines diff --git a/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in b/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in new file mode 100644 index 0000000000..3969a3af9c --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_mortevielle.mmp.in @@ -0,0 +1,62 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_mortevielle.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\mortevielle + +//START_AUTO_OBJECTS_MORTEVIELLE_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_MORTEVIELLE_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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_neverhood.mmp.in b/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in new file mode 100644 index 0000000000..3a49093c43 --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_neverhood.mmp.in @@ -0,0 +1,61 @@ +/* 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-2013 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_neverhood.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\neverhood + +//START_AUTO_OBJECTS_NEVERHOOD_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_NEVERHOOD_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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_sci.mmp.in b/backends/platform/symbian/mmp/scummvm_sci.mmp.in index 5749c66e10..333a6d43c2 100644 --- a/backends/platform/symbian/mmp/scummvm_sci.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_sci.mmp.in @@ -53,6 +53,14 @@ SOURCEPATH ..\..\..\..\engines\sci //STOP_AUTO_OBJECTS_SCI_// + +//START_AUTO_OBJECTS_SCI_ENABLE_SCI32// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_SCI_ENABLE_SCI32// + + // *** Include paths USERINCLUDE ..\..\..\..\engines diff --git a/backends/platform/symbian/mmp/scummvm_sword25.mmp.in b/backends/platform/symbian/mmp/scummvm_sword25.mmp.in new file mode 100644 index 0000000000..e14501e42d --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_sword25.mmp.in @@ -0,0 +1,63 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_sword25.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\sword25 + +//START_AUTO_OBJECTS_SWORD25_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_SWORD25_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\gui ..\..\..\..\audio ..\src +USERINCLUDE ..\..\..\..\engines\sword25\util\lua ..\..\..\..\engines\sword25\util\pluto +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_testbed.mmp.in b/backends/platform/symbian/mmp/scummvm_testbed.mmp.in new file mode 100644 index 0000000000..ce6a18508d --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_testbed.mmp.in @@ -0,0 +1,62 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_testbed.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\testbed + +//START_AUTO_OBJECTS_TESTBED_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_TESTBED_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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_zvision.mmp.in b/backends/platform/symbian/mmp/scummvm_zvision.mmp.in new file mode 100644 index 0000000000..3687b10fec --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_zvision.mmp.in @@ -0,0 +1,62 @@ +/* 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-2013 The ScummVM project + * Copyright (C) 2013 Strizniou Fedor + * + * 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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_zvision.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\zvision + +//START_AUTO_OBJECTS_ZVISION_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_ZVISION_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\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/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index b1bd976f9e..ead85a933e 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -197,3 +197,8 @@ void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size return NULL; } + +int remove(const char *path) +{ + return unlink(path); +} diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h index 1f9128a54f..f69a90e009 100644 --- a/backends/platform/symbian/src/portdefs.h +++ b/backends/platform/symbian/src/portdefs.h @@ -60,6 +60,8 @@ typedef signed long int int32; #define SMALL_SCREEN_DEVICE #define DISABLE_COMMAND_LINE +#define USE_RGB_COLOR +int remove(const char *path); #if defined(USE_TREMOR) && !defined(USE_VORBIS) #define USE_VORBIS // make sure this one is defined together with USE_TREMOR! diff --git a/backends/platform/bada/README.TXT b/backends/platform/tizen/README.TXT index c4a04d5450..def3da2cce 100644 --- a/backends/platform/bada/README.TXT +++ b/backends/platform/tizen/README.TXT @@ -1,77 +1,58 @@ -Build instructions: +Build instructions (using linux) -1. Install BADA SDK (requires free registration): - - http://developer.bada.com/apis/index.do - -2. Install Cygwin: - - http://www.cygwin.com/ +1. Install the Tizen SDK - Add the following to your cygwin .bash_profile: +http://www.tizen.org - alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe - export BADA_SDK=/cygdrive/c/bada/1.2.1 - export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin - export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \ - -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \ - -fno-strict-aliasing -fno-short-enums" - export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target" - #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH} - export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH} - alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe - alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe +To use an alternative Java SDK to run the Tizen IDE (eclipse), edit ~/.profile - The following were added to ~/utils for zlib: +export JAVA_HOME=/opt/jdk1.6.0_45 +export PATH=${PATH}:${JAVA_HOME}/bin - ar: - #!/bin/sh - ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $* +2. Add the following to your ~/.bashrc file - gcc: - #!/bin/sh - ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $* +export TIZEN_SDK=${HOME}/tizen-sdk +export TIZEN_ROOTSTRAP=${TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-device-2.1.native +export TIZEN_BIN=${TIZEN_SDK}/tools/arm-linux-gnueabi-gcc-4.5/bin +export TIZEN_LIBS=${HOME}/tizen-lib +export PATH=${PATH}:${TIZEN_BIN}:~/bin +export CHOST=arm-linux-gnueabi +export LDFLAGS="--sysroot=${TIZEN_ROOTSTRAP} -L${TIZEN_LIBS}/lib" +export CPPFLAGS="--sysroot=${TIZEN_ROOTSTRAP} -fmessage-length=0 -fPIC\ + -I${TIZEN_ROOTSTRAP}/usr/include -I${TIZEN_LIBS}/include" +export CFLAGS=${CPPFLAGS} 3. Build dependencies - zlib, libogg, libvorbis, libmad, FLAC - - see: "Building the libraries" under: + See: "Building the libraries" under: http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW#Building_the_libraries for instructions on how to obtain these modules - 3.1 For Target-Release configure ogg and mad with: - - ./configure --host=arm-samsung-nucleuseabi --disable-shared + 3.1 zlib - when building vorbis and flac: + $ ./configure --static --prefix=${TIZEN_LIBS} + $ make && make install - ./configure --host=arm-samsung-nucleuseabi --disable-shared --with-ogg=c:/cygwin/usr/local + 3.2 freetype, libtheora, libogg, libvorbis, libmad, FLAC - 3.2 for each module, after a successful configure, add the following - to the generated config.h (gzguts.h for zlib) + $ ./configure --host=arm-linux-gnueabi --prefix=${TIZEN_LIBS} --disable-shared + $ make && make install - #undef __MINGW32__ - #undef _WIN32 - #include "c:/src/scummvm/backends/platform/bada/portdefs.h" - - 3.3 Additional post configure edits: + Note: you can ignore the ranlib errors when doing make install. - - removed -fforce-mem from the libMAD Makefile - - in libvorbis/lib/Makefile comment lines with vorbis_selftests - - edit libFLAC/Makefile ... CFLAGS = $(OGG_CFLAGS) + Modify the resulting ~/tizen-lib/bin/freetype-config file to include -lz when printing libs - Note: you can ignore the ranlib errors when doing make install. + 3.3 Linker ordering: scummvm, freetype, theoradec, vorbis, vorbisfile, mad, FLAC, ogg, z 4. Build the ScummVM base library: - ./configure --host=bada --enable-release + ./configure --host=tizen --enable-release --with-freetype2-prefix=${TIZEN_LIBS}/bin - To target the Win32 simulator: + For development: - ./configure --host=bada --enable-debug + ./configure --host=tizen --enable-verbose-build --enable-debug -5. Build the front end application using BADA-Ide: +5. Build the front end application using Tizen IDE Copy the scummvm/dists/bada folder into a clean directory outside of the scummvm package. Start the BADA IDE then @@ -90,3 +71,38 @@ HelvB14 font files: Then run the following command: $ ./ucs2any.pl 100dpi/helvB14.bdf MAPPINGS/8859-1.TXT iso8859-1 \ MAPPINGS/8859-2.TXT iso8859-2 MAPPINGS/8859-3.TXT iso8859-3 + +===================================================================== +Archived build instruction for BADA/cygwin + +1. Install BADA SDK (requires free registration): + + http://developer.bada.com/apis/index.do + +2. Install Cygwin: + + http://www.cygwin.com/ + + Add the following to your cygwin .bash_profile: + + alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe + export BADA_SDK=/cygdrive/c/bada/1.2.1 + export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin + export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \ + -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \ + -fno-strict-aliasing -fno-short-enums" + export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target" + #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH} + export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH} + alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe + alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe + + The following were added to ~/utils for zlib: + + ar: + #!/bin/sh + ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $* + + gcc: + #!/bin/sh + ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $* diff --git a/backends/platform/tizen/application.cpp b/backends/platform/tizen/application.cpp new file mode 100644 index 0000000000..a73efacf58 --- /dev/null +++ b/backends/platform/tizen/application.cpp @@ -0,0 +1,144 @@ +/* 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. + * + */ + +#include "engines/engine.h" + +#include "backends/platform/tizen/form.h" +#include "backends/platform/tizen/system.h" +#include "backends/platform/tizen/application.h" + +Application *TizenScummVM::createInstance() { + logEntered(); + return new TizenScummVM(); +} + +TizenScummVM::TizenScummVM() : _appForm(NULL) { + logEntered(); +} + +TizenScummVM::~TizenScummVM() { + logEntered(); + if (g_system) { + TizenSystem *system = (TizenSystem *)g_system; + system->destroyBackend(); + delete system; + g_system = NULL; + } +} + +bool TizenScummVM::OnAppInitialized(void) { + logEntered(); + _appForm->SetOrientation(Tizen::Ui::ORIENTATION_LANDSCAPE); + return true; +} + +bool TizenScummVM::OnAppWillTerminate(void) { + logEntered(); + return true; +} + +bool TizenScummVM::OnAppInitializing(AppRegistry &appRegistry) { + logEntered(); + _appForm = systemStart(this); + return (_appForm != NULL); +} + +bool TizenScummVM::OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination) { + logEntered(); + return true; +} + +void TizenScummVM::OnUserEventReceivedN(RequestId requestId, IList *args) { + logEntered(); + MessageBox messageBox; + int modalResult; + String *message; + + switch (requestId) { + case USER_MESSAGE_EXIT: + // normal program termination + Terminate(); + break; + + case USER_MESSAGE_EXIT_ERR: + // assertion failure termination + if (args) { + message = (String *)args->GetAt(0); + } + if (!message) { + message = new String("Unknown error"); + } + messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK); + messageBox.ShowAndWait(modalResult); + Terminate(); + break; + + case USER_MESSAGE_EXIT_ERR_CONFIG: + // the config file was corrupted + messageBox.Construct(L"Config file corrupted", + L"Settings have been reverted, please restart.", MSGBOX_STYLE_OK); + messageBox.ShowAndWait(modalResult); + Terminate(); + break; + } +} + +void TizenScummVM::OnForeground(void) { + logEntered(); + pauseGame(false); +} + +void TizenScummVM::OnBackground(void) { + logEntered(); + pauseGame(true); +} + +void TizenScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) { + logEntered(); +} + +void TizenScummVM::OnLowMemory(void) { + logEntered(); +} + +void TizenScummVM::OnScreenOn(void) { + logEntered(); +} + +void TizenScummVM::OnScreenOff(void) { + logEntered(); +} + +void TizenScummVM::OnScreenBrightnessChanged(int brightness) { + logEntered(); +} + +void TizenScummVM::pauseGame(bool pause) { + if (_appForm) { + if (pause && g_engine && !g_engine->isPaused()) { + _appForm->pushKey(Common::KEYCODE_SPACE); + } + if (g_system) { + ((TizenSystem *)g_system)->setMute(pause); + } + } +} diff --git a/backends/platform/tizen/application.h b/backends/platform/tizen/application.h new file mode 100644 index 0000000000..f18ccb175b --- /dev/null +++ b/backends/platform/tizen/application.h @@ -0,0 +1,69 @@ +/* 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 TIZEN_APPLICATION_H +#define TIZEN_APPLICATION_H + +#include <FBase.h> +#include <FApp.h> +#include <FGraphics.h> +#include <FUi.h> +#include <FSystem.h> + +#include "backends/platform/tizen/system.h" +#include "backends/platform/tizen/form.h" + +using namespace Tizen::App; +using namespace Tizen::System; +using namespace Tizen::Ui; +using namespace Tizen::Ui::Controls; +using namespace Tizen::Base::Collection; + +class TizenScummVM : + public UiApp, + public IScreenEventListener { + +public: + TizenScummVM(); + virtual ~TizenScummVM(); + + static UiApp *createInstance(void); + + virtual bool OnAppInitializing(AppRegistry &appRegistry); + virtual bool OnAppInitialized(void); + virtual bool OnAppWillTerminate(void); + virtual bool OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination = false); + virtual void OnLowMemory(void); + virtual void OnBatteryLevelChanged(BatteryLevel batteryLevel); + virtual void OnUserEventReceivedN(RequestId requestId, IList *pArgs); + virtual void OnForeground(void); + virtual void OnBackground(void); + virtual void OnScreenOn(void); + virtual void OnScreenOff(void); + virtual void OnScreenBrightnessChanged(int brightness); + +private: + void pauseGame(bool pause); + TizenAppForm *_appForm; +}; + +#endif diff --git a/backends/platform/bada/audio.cpp b/backends/platform/tizen/audio.cpp index 65a5a80fa5..f9ac80a583 100644 --- a/backends/platform/bada/audio.cpp +++ b/backends/platform/tizen/audio.cpp @@ -23,18 +23,12 @@ #include <FSysSettingInfo.h> #include <FAppAppRegistry.h> -#include "backends/platform/bada/audio.h" -#include "backends/platform/bada/system.h" +#include "backends/platform/tizen/audio.h" +#include "backends/platform/tizen/system.h" -#define TIMER_INCREMENT 10 -#define TIMER_INTERVAL 40 -#define MIN_TIMER_INTERVAL 10 -#define MAX_TIMER_INTERVAL 160 -#define INIT_LEVEL 3 -#define CONFIG_KEY L"audiovol" - -// sound level pre-sets -const int levels[] = {0, 1, 10, 45, 70, 99}; +#define TIMER_INTERVAL 10 +#define VOLUME 96 +#define MIN_TIMER_INTERVAL 5 AudioThread::AudioThread() : _mixer(0), @@ -45,15 +39,14 @@ AudioThread::AudioThread() : _ready(0), _interval(TIMER_INTERVAL), _playing(-1), + _size(0), _muted(true) { } Audio::MixerImpl *AudioThread::Construct(OSystem *system) { logEntered(); - if (IsFailed(Thread::Construct(THREAD_TYPE_EVENT_DRIVEN, - DEFAULT_STACK_SIZE, - THREAD_PRIORITY_HIGH))) { + if (IsFailed(EventDrivenThread::Construct(DEFAULT_STACK_SIZE, THREAD_PRIORITY_HIGH))) { AppLog("Failed to create AudioThread"); return NULL; } @@ -69,7 +62,7 @@ AudioThread::~AudioThread() { bool AudioThread::isSilentMode() { bool silentMode; String key(L"SilentMode"); - Osp::System::SettingInfo::GetValue(key, silentMode); + Tizen::System::SettingInfo::GetValue(key, silentMode); return silentMode; } @@ -84,54 +77,11 @@ void AudioThread::setMute(bool on) { } } -int AudioThread::setVolume(bool up, bool minMax) { - int level = -1; - int numLevels = sizeof(levels) / sizeof(levels[0]); - - if (_audioOut) { - int volume = _audioOut->GetVolume(); - if (minMax) { - level = up ? numLevels - 1 : 0; - volume = levels[level]; - } else { - // adjust volume to be one of the preset values - for (int i = 0; i < numLevels && level == -1; i++) { - if (volume == levels[i]) { - level = i; - if (up) { - if (i + 1 < numLevels) { - level = i + 1; - } - } else if (i > 0) { - level = i - 1; - } - } - } - - // default to INIT_LEVEL when current not preset value - if (level == -1) { - level = INIT_LEVEL; - } - volume = levels[level]; - } - - _audioOut->SetVolume(volume); - - // remember the chosen setting - AppRegistry *registry = Application::GetInstance()->GetAppRegistry(); - if (registry) { - registry->Set(CONFIG_KEY, volume); - } - } - return level; -} - bool AudioThread::OnStart(void) { logEntered(); - _audioOut = new Osp::Media::AudioOut(); - if (!_audioOut || - IsFailed(_audioOut->Construct(*this))) { + _audioOut = new Tizen::Media::AudioOut(); + if (!_audioOut || IsFailed(_audioOut->Construct(*this))) { AppLog("Failed to create AudioOut"); return false; } @@ -144,8 +94,7 @@ bool AudioThread::OnStart(void) { } if (IsFailed(_audioOut->Prepare(AUDIO_TYPE_PCM_S16_LE, - AUDIO_CHANNEL_TYPE_STEREO, - sampleRate))) { + AUDIO_CHANNEL_TYPE_STEREO, sampleRate))) { AppLog("Failed to prepare AudioOut %d", sampleRate); return false; } @@ -158,6 +107,7 @@ bool AudioThread::OnStart(void) { } } + _size = _audioBuffer[0].GetCapacity(); _timer = new Timer(); if (!_timer || IsFailed(_timer->Construct(*this))) { AppLog("Failed to create audio timer"); @@ -169,21 +119,9 @@ bool AudioThread::OnStart(void) { return false; } - // get the volume from the app-registry - int volume = levels[INIT_LEVEL]; - AppRegistry *registry = Application::GetInstance()->GetAppRegistry(); - if (registry) { - if (E_KEY_NOT_FOUND == registry->Get(CONFIG_KEY, volume)) { - registry->Add(CONFIG_KEY, volume); - volume = levels[INIT_LEVEL]; - } else { - AppLog("Setting volume: %d", volume); - } - } - _muted = false; _mixer->setReady(true); - _audioOut->SetVolume(isSilentMode() ? 0 : volume); + _audioOut->SetVolume(isSilentMode() ? 0 : VOLUME); _audioOut->Start(); return true; } @@ -202,53 +140,52 @@ void AudioThread::OnStop(void) { if (_audioOut) { _audioOut->Reset(); + _audioOut->Unprepare(); delete _audioOut; } } -void AudioThread::OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r) { +void AudioThread::OnAudioOutErrorOccurred(Tizen::Media::AudioOut &src, result r) { logEntered(); } -void AudioThread::OnAudioOutInterrupted(Osp::Media::AudioOut &src) { +void AudioThread::OnAudioOutInterrupted(Tizen::Media::AudioOut &src) { logEntered(); } -void AudioThread::OnAudioOutReleased(Osp::Media::AudioOut &src) { +void AudioThread::OnAudioOutReleased(Tizen::Media::AudioOut &src) { logEntered(); _audioOut->Start(); } -void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) { +void AudioThread::OnAudioOutBufferEndReached(Tizen::Media::AudioOut &src) { if (_ready > 0) { _playing = _tail; _audioOut->WriteBuffer(_audioBuffer[_tail]); _tail = (_tail + 1) % NUM_AUDIO_BUFFERS; _ready--; } else { - // audio buffer empty: decrease timer inverval + // audio buffer empty: decrease timer interval _playing = -1; - _interval -= TIMER_INCREMENT; + _interval -= 1; if (_interval < MIN_TIMER_INTERVAL) { _interval = MIN_TIMER_INTERVAL; } } + } void AudioThread::OnTimerExpired(Timer &timer) { if (_ready < NUM_AUDIO_BUFFERS) { - uint len = _audioBuffer[_head].GetCapacity(); - int samples = _mixer->mixCallback((byte *)_audioBuffer[_head].GetPointer(), len); - if (samples) { - _head = (_head + 1) % NUM_AUDIO_BUFFERS; - _ready++; + if (_playing != _head) { + if (_mixer->mixCallback((byte *)_audioBuffer[_head].GetPointer(), _size)) { + _head = (_head + 1) % NUM_AUDIO_BUFFERS; + _ready++; + } } } else { - // audio buffer full: increase timer inverval - _interval += TIMER_INCREMENT; - if (_interval > MAX_TIMER_INTERVAL) { - _interval = MAX_TIMER_INTERVAL; - } + // audio buffer full: restore timer interval + _interval = TIMER_INTERVAL; } if (_ready && _playing == -1) { diff --git a/backends/platform/bada/audio.h b/backends/platform/tizen/audio.h index 72c537a942..a304231578 100644 --- a/backends/platform/bada/audio.h +++ b/backends/platform/tizen/audio.h @@ -20,8 +20,8 @@ * */ -#ifndef BADA_AUDIO_H -#define BADA_AUDIO_H +#ifndef TIZEN_AUDIO_H +#define TIZEN_AUDIO_H #include <FBase.h> #include <FMedia.h> @@ -33,17 +33,19 @@ #include "common/system.h" #include "audio/mixer_intern.h" -using namespace Osp::Base; -using namespace Osp::Base::Collection; -using namespace Osp::Base::Runtime; -using namespace Osp::Media; -using namespace Osp::Io; +using namespace Tizen::Base; +using namespace Tizen::Base::Collection; +using namespace Tizen::Base::Runtime; +using namespace Tizen::Media; +using namespace Tizen::Io; #define NUM_AUDIO_BUFFERS 2 -class AudioThread: public Osp::Media::IAudioOutEventListener, - public Osp::Base::Runtime::ITimerEventListener, - public Osp::Base::Runtime::Thread { +class AudioThread: + public Tizen::Media::IAudioOutEventListener, + public Tizen::Base::Runtime::ITimerEventListener, + public Tizen::Base::Runtime::EventDrivenThread { + public: AudioThread(void); ~AudioThread(void); @@ -51,22 +53,21 @@ public: Audio::MixerImpl *Construct(OSystem *system); bool isSilentMode(); void setMute(bool on); - int setVolume(bool up, bool minMax); +private: bool OnStart(void); void OnStop(void); - void OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r); - void OnAudioOutInterrupted(Osp::Media::AudioOut &src); - void OnAudioOutReleased(Osp::Media::AudioOut &src); - void OnAudioOutBufferEndReached(Osp::Media::AudioOut &src); + void OnAudioOutErrorOccurred(Tizen::Media::AudioOut &src, result r); + void OnAudioOutInterrupted(Tizen::Media::AudioOut &src); + void OnAudioOutReleased(Tizen::Media::AudioOut &src); + void OnAudioOutBufferEndReached(Tizen::Media::AudioOut &src); void OnTimerExpired(Timer &timer); -private: Audio::MixerImpl *_mixer; - Osp::Base::Runtime::Timer *_timer; - Osp::Media::AudioOut *_audioOut; - Osp::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS]; - int _head, _tail, _ready, _interval, _playing; + Tizen::Base::Runtime::Timer *_timer; + Tizen::Media::AudioOut *_audioOut; + Tizen::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS]; + int _head, _tail, _ready, _interval, _playing, _size; bool _muted; }; diff --git a/backends/platform/tizen/form.cpp b/backends/platform/tizen/form.cpp new file mode 100644 index 0000000000..10d51cc610 --- /dev/null +++ b/backends/platform/tizen/form.cpp @@ -0,0 +1,432 @@ +/* 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. + * + */ + +#include <FApp.h> +#include <FSysSystemTime.h> + +#include "common/translation.h" +#include "base/main.h" + +#include "backends/platform/tizen/form.h" +#include "backends/platform/tizen/system.h" + +using namespace Tizen::Base::Collection; +using namespace Tizen::Base::Runtime; +using namespace Tizen::Ui::Controls; + +// round down small Y touch values to 1 to allow the +// cursor to be positioned at the top of the screen +#define MIN_TOUCH_Y 20 + +// block for up to 2.5 seconds during shutdown to +// allow the game thread to exit gracefully. +#define EXIT_SLEEP_STEP 10 +#define EXIT_SLEEP 250 + +// +// TizenAppForm +// +TizenAppForm::TizenAppForm() : + _gestureMode(false), + _osdMessage(NULL), + _gameThread(NULL), + _eventQueueLock(NULL), + _state(kInitState), + _buttonState(kLeftButton), + _shortcut(kEscapeKey) { +} + +result TizenAppForm::Construct() { + TizenSystem *tizenSystem = NULL; + result r = Form::Construct(FORM_STYLE_NORMAL); + if (!IsFailed(r)) { + tizenSystem = new TizenSystem(this); + r = tizenSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY; + } + if (!IsFailed(r)) { + r = tizenSystem->Construct(); + } + if (!IsFailed(r)) { + _gameThread = new Thread(); + r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY; + } + if (!IsFailed(r)) { + r = _gameThread->Construct(*this); + } + if (!IsFailed(r)) { + _eventQueueLock = new Mutex(); + r = _eventQueueLock != NULL ? E_SUCCESS : E_OUT_OF_MEMORY; + } + if (!IsFailed(r)) { + r = _eventQueueLock->Create(); + } + + if (!IsFailed(r)) { + g_system = tizenSystem; + } else { + AppLog("Form startup failed"); + delete tizenSystem; + delete _gameThread; + _gameThread = NULL; + } + return r; +} + +TizenAppForm::~TizenAppForm() { + logEntered(); + + if (_gameThread && _state != kErrorState) { + terminate(); + + _gameThread->Stop(); + if (_state != kErrorState) { + _gameThread->Join(); + } + + delete _gameThread; + _gameThread = NULL; + } + + delete _eventQueueLock; + _eventQueueLock = NULL; + + logLeaving(); +} + +// +// abort the game thread +// +void TizenAppForm::terminate() { + if (_state == kActiveState) { + ((TizenSystem *)g_system)->setMute(true); + + _eventQueueLock->Acquire(); + + Common::Event e; + e.type = Common::EVENT_QUIT; + _eventQueue.push(e); + _state = kClosingState; + + _eventQueueLock->Release(); + + // block while thread ends + AppLog("waiting for shutdown"); + for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) { + Thread::Sleep(EXIT_SLEEP); + } + + if (_state == kClosingState) { + // failed to terminate - Join() will freeze + _state = kErrorState; + } + } +} + +void TizenAppForm::exitSystem() { + _state = kErrorState; + + if (_gameThread) { + _gameThread->Stop(); + delete _gameThread; + _gameThread = NULL; + } +} + +result TizenAppForm::OnInitializing(void) { + logEntered(); + + AddOrientationEventListener(*this); + AddTouchEventListener(*this); + SetMultipointTouchEnabled(true); + SetFormBackEventListener(this); + SetFormMenuEventListener(this); + + // set focus to enable receiving key events + SetEnabled(true); + SetFocusable(true); + SetFocus(); + + return E_SUCCESS; +} + +result TizenAppForm::OnDraw(void) { + logEntered(); + return E_SUCCESS; +} + +void TizenAppForm::OnOrientationChanged(const Control &source, OrientationStatus orientationStatus) { + logEntered(); + if (_state == kInitState) { + _state = kActiveState; + _gameThread->Start(); + } +} + +Tizen::Base::Object *TizenAppForm::Run() { + logEntered(); + + scummvm_main(0, 0); + if (_state == kActiveState) { + Tizen::App::Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL); + } + _state = kDoneState; + return NULL; +} + +bool TizenAppForm::pollEvent(Common::Event &event) { + bool result = false; + + _eventQueueLock->Acquire(); + if (!_eventQueue.empty()) { + event = _eventQueue.pop(); + result = true; + } + if (_osdMessage) { + TizenSystem *system = (TizenSystem *)g_system; + TizenGraphicsManager *graphics = system->getGraphics(); + if (graphics) { + graphics->displayMessageOnOSD(_osdMessage); + _osdMessage = NULL; + } + } + _eventQueueLock->Release(); + + return result; +} + +void TizenAppForm::pushEvent(Common::EventType type, const Point ¤tPosition) { + TizenSystem *system = (TizenSystem *)g_system; + TizenGraphicsManager *graphics = system->getGraphics(); + if (graphics) { + // graphics could be NULL at startup or when + // displaying the system error screen + Common::Event e; + e.type = type; + e.mouse.x = currentPosition.x; + e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1; + + bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y); + + _eventQueueLock->Acquire(); + + if (moved && type != Common::EVENT_MOUSEMOVE) { + Common::Event moveEvent; + moveEvent.type = Common::EVENT_MOUSEMOVE; + moveEvent.mouse = e.mouse; + _eventQueue.push(moveEvent); + } + + _eventQueue.push(e); + _eventQueueLock->Release(); + } +} + +void TizenAppForm::pushKey(Common::KeyCode keycode) { + if (_eventQueueLock) { + Common::Event e; + e.synthetic = false; + e.kbd.keycode = keycode; + e.kbd.ascii = keycode; + e.kbd.flags = 0; + + _eventQueueLock->Acquire(); + e.type = Common::EVENT_KEYDOWN; + _eventQueue.push(e); + e.type = Common::EVENT_KEYUP; + _eventQueue.push(e); + _eventQueueLock->Release(); + } +} + +void TizenAppForm::setButtonShortcut() { + switch (_buttonState) { + case kLeftButton: + setMessage(_s("Right Click Once")); + _buttonState = kRightButtonOnce; + break; + case kRightButtonOnce: + setMessage(_s("Right Click")); + _buttonState = kRightButton; + break; + case kRightButton: + setMessage(_s("Move Only")); + _buttonState = kMoveOnly; + break; + case kMoveOnly: + setMessage(_s("Left Click")); + _buttonState = kLeftButton; + break; + } +} + +void TizenAppForm::setMessage(const char *message) { + if (_eventQueueLock) { + _eventQueueLock->Acquire(); + _osdMessage = message; + _eventQueueLock->Release(); + } +} + +void TizenAppForm::setShortcut() { + logEntered(); + // cycle to the next shortcut + switch (_shortcut) { + case kControlMouse: + setMessage(_s("Escape Key")); + _shortcut = kEscapeKey; + break; + + case kEscapeKey: + setMessage(_s("Game Menu")); + _shortcut = kGameMenu; + break; + + case kGameMenu: + setMessage(_s("Show Keypad")); + _shortcut = kShowKeypad; + break; + + case kShowKeypad: + setMessage(_s("Control Mouse")); + _shortcut = kControlMouse; + break; + } +} + +void TizenAppForm::invokeShortcut() { + logEntered(); + switch (_shortcut) { + case kControlMouse: + setButtonShortcut(); + break; + + case kEscapeKey: + pushKey(Common::KEYCODE_ESCAPE); + break; + + case kGameMenu: + _buttonState = kLeftButton; + pushKey(Common::KEYCODE_F5); + break; + + case kShowKeypad: + showKeypad(); + break; + } +} + +void TizenAppForm::showKeypad() { + // display the soft keyboard + if (_state == kActiveState) { + _buttonState = kLeftButton; + pushKey(Common::KEYCODE_F7); + } +} + +int TizenAppForm::getTouchCount() { + Tizen::Ui::TouchEventManager *touch = Tizen::Ui::TouchEventManager::GetInstance(); + IListT<TouchEventInfo *> *touchList = touch->GetTouchInfoListN(); + int touchCount = touchList->GetCount(); + touchList->RemoveAll(); + delete touchList; + return touchCount; +} + +void TizenAppForm::OnTouchDoublePressed(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { + if (_buttonState != kMoveOnly) { + pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, + currentPosition); + } +} + +void TizenAppForm::OnTouchFocusIn(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { +} + +void TizenAppForm::OnTouchFocusOut(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { +} + +void TizenAppForm::OnTouchLongPressed(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { + logEntered(); + if (_buttonState != kLeftButton) { + pushKey(Common::KEYCODE_RETURN); + } +} + +void TizenAppForm::OnTouchMoved(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { + if (!_gestureMode) { + pushEvent(Common::EVENT_MOUSEMOVE, currentPosition); + } +} + +void TizenAppForm::OnTouchPressed(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { + if (getTouchCount() > 1) { + _gestureMode = true; + } else if (_buttonState != kMoveOnly) { + pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, + currentPosition); + } +} + +void TizenAppForm::OnTouchReleased(const Control &source, + const Point ¤tPosition, const TouchEventInfo &touchInfo) { + if (_gestureMode) { + int touchCount = getTouchCount(); + if (touchCount == 1) { + setShortcut(); + } else { + if (touchCount == 2) { + invokeShortcut(); + } + _gestureMode = false; + } + } else if (_buttonState != kMoveOnly) { + pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP, + currentPosition); + if (_buttonState == kRightButtonOnce) { + _buttonState = kLeftButton; + } + // flick to skip dialog + if (touchInfo.IsFlicked()) { + pushKey(Common::KEYCODE_PERIOD); + } + } +} + +void TizenAppForm::OnFormBackRequested(Form &source) { + logEntered(); + if (_state == kActiveState) { + invokeShortcut(); + } +} + +void TizenAppForm::OnFormMenuRequested(Form &source) { + logEntered(); + if (_state == kActiveState) { + setShortcut(); + } +} diff --git a/backends/platform/tizen/form.h b/backends/platform/tizen/form.h new file mode 100644 index 0000000000..e419c14d24 --- /dev/null +++ b/backends/platform/tizen/form.h @@ -0,0 +1,120 @@ +/* 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 TIZEN_FORM_H +#define TIZEN_FORM_H + +#include <FApp.h> +#include <FUi.h> +#include <FSystem.h> +#include <FBase.h> +#include <FUiITouchEventListener.h> +#include <FUiITextEventListener.h> +#include <FUiCtrlIFormBackEventListener.h> +#include <FUiCtrlIFormMenuEventListener.h> + +#include "config.h" +#include "common/scummsys.h" +#include "common/events.h" +#include "common/queue.h" +#include "common/mutex.h" +#include "engines/engine.h" + +using namespace Tizen::Ui; +using namespace Tizen::Graphics; +using namespace Tizen::Base::Runtime; +using namespace Tizen::Ui::Controls; + +// +// TizenAppForm +// +class TizenAppForm : + public Controls::Form, + public IRunnable, + public IOrientationEventListener, + public ITouchEventListener, + public IFormBackEventListener, + public IFormMenuEventListener { + +public: + TizenAppForm(); + virtual ~TizenAppForm(); + + result Construct(); + bool pollEvent(Common::Event &event); + bool isClosing() { return _state == kClosingState; } + bool isStarting() { return _state == kInitState; } + void pushKey(Common::KeyCode keycode); + void exitSystem(); + void showKeypad(); + +private: + Tizen::Base::Object *Run(); + result OnInitializing(void); + result OnDraw(void); + void OnOrientationChanged(const Control &source, + OrientationStatus orientationStatus); + void OnTouchDoublePressed(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnTouchFocusIn(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnTouchFocusOut(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnTouchLongPressed(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnTouchMoved(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnTouchPressed(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnTouchReleased(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo); + void OnFormBackRequested(Form &source); + void OnFormMenuRequested(Form &source); + + void pushEvent(Common::EventType type, const Point ¤tPosition); + void terminate(); + void setButtonShortcut(); + void setMessage(const char *message); + void setShortcut(); + void invokeShortcut(); + int getTouchCount(); + bool gameActive() { return _state == kActiveState && g_engine != NULL && !g_engine->isPaused(); } + + // event handling + bool _gestureMode; + const char *_osdMessage; + Tizen::Base::Runtime::Thread *_gameThread; + Tizen::Base::Runtime::Mutex *_eventQueueLock; + Common::Queue<Common::Event> _eventQueue; + enum { kInitState, kActiveState, kClosingState, kDoneState, kErrorState } _state; + enum { kLeftButton, kRightButtonOnce, kRightButton, kMoveOnly } _buttonState; + enum { kControlMouse, kEscapeKey, kGameMenu, kShowKeypad } _shortcut; +}; + +#endif diff --git a/backends/platform/bada/fs.cpp b/backends/platform/tizen/fs.cpp index 37ca496d18..8145cd5638 100644 --- a/backends/platform/bada/fs.cpp +++ b/backends/platform/tizen/fs.cpp @@ -20,33 +20,38 @@ */ #include "config.h" -#include "backends/platform/bada/system.h" -#include "backends/platform/bada/fs.h" +#include "common/translation.h" +#include "backends/platform/tizen/system.h" +#include "backends/platform/tizen/fs.h" + +#include <FAppApp.h> #define BUFFER_SIZE 1024 -// internal BADA paths -#define PATH_ROOT "/" -#define PATH_HOME "/Home" -#define PATH_HOME_SHARE "/Home/Share" -#define PATH_HOME_SHARE2 "/Home/Share2" -#define PATH_HOME_X "/Home/" -#define PATH_HOME_EXT "/HomeExt" -#define PATH_MEDIA "/Media" -#define PATH_CARD "/Storagecard" -#define PATH_CARD_MEDIA "/Storagecard/Media" +using namespace Tizen::App; + +// +// converts a Tizen (wchar) String into a scummVM (char) string +// +Common::String fromString(const Tizen::Base::String &in) { + ByteBuffer *buf = StringUtil::StringToUtf8N(in); + Common::String result((const char*)buf->GetPointer()); + delete buf; + return result; +} // -// BadaFileStream +// TizenFileStream // -class BadaFileStream : public Common::SeekableReadStream, - public Common::WriteStream, - public Common::NonCopyable { +class TizenFileStream : + public Common::SeekableReadStream, + public Common::WriteStream, + public Common::NonCopyable { public: - static BadaFileStream *makeFromPath(const String &path, bool writeMode); + static TizenFileStream *makeFromPath(const String &path, bool writeMode); - BadaFileStream(File *file, bool writeMode); - ~BadaFileStream(); + TizenFileStream(File *file, bool writeMode); + ~TizenFileStream(); bool err() const; void clearErr(); @@ -61,81 +66,81 @@ public: uint32 read(void *dataPtr, uint32 dataSize); private: - byte buffer[BUFFER_SIZE]; - uint32 bufferIndex; - uint32 bufferLength; - bool writeMode; - File *file; + byte _buffer[BUFFER_SIZE]; + uint32 _bufferIndex; + uint32 _bufferLength; + bool _writeMode; + File *_file; }; -BadaFileStream::BadaFileStream(File *ioFile, bool writeMode) : - bufferIndex(0), - bufferLength(0), - writeMode(writeMode), - file(ioFile) { +TizenFileStream::TizenFileStream(File *ioFile, bool writeMode) : + _bufferIndex(0), + _bufferLength(0), + _writeMode(writeMode), + _file(ioFile) { AppAssert(ioFile != 0); } -BadaFileStream::~BadaFileStream() { - if (file) { - if (writeMode) { +TizenFileStream::~TizenFileStream() { + if (_file) { + if (_writeMode) { flush(); } - delete file; + delete _file; } } -bool BadaFileStream::err() const { +bool TizenFileStream::err() const { result r = GetLastResult(); return (r != E_SUCCESS && r != E_END_OF_FILE); } -void BadaFileStream::clearErr() { +void TizenFileStream::clearErr() { SetLastResult(E_SUCCESS); } -bool BadaFileStream::eos() const { - return (bufferLength - bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE); +bool TizenFileStream::eos() const { + return (_bufferLength - _bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE); } -int32 BadaFileStream::pos() const { - return file->Tell() - (bufferLength - bufferIndex); +int32 TizenFileStream::pos() const { + return _file->Tell() - (_bufferLength - _bufferIndex); } -int32 BadaFileStream::size() const { - int32 oldPos = file->Tell(); - file->Seek(FILESEEKPOSITION_END, 0); +int32 TizenFileStream::size() const { + int32 oldPos = _file->Tell(); + _file->Seek(FILESEEKPOSITION_END, 0); - int32 length = file->Tell(); - SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, oldPos)); + int32 length = _file->Tell(); + SetLastResult(_file->Seek(FILESEEKPOSITION_BEGIN, oldPos)); return length; } -bool BadaFileStream::seek(int32 offs, int whence) { +bool TizenFileStream::seek(int32 offs, int whence) { bool result = false; switch (whence) { case SEEK_SET: // set from start of file - SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, offs)); + SetLastResult(_file->Seek(FILESEEKPOSITION_BEGIN, offs)); result = (E_SUCCESS == GetLastResult()); break; case SEEK_CUR: // set relative to offs - if (bufferIndex < bufferLength && bufferIndex > (uint32)-offs) { + if (_bufferIndex < _bufferLength && _bufferIndex > (uint32)-offs) { // re-position within the buffer SetLastResult(E_SUCCESS); - bufferIndex += offs; + _bufferIndex += offs; return true; } else { - offs -= (bufferLength - bufferIndex); - if (offs < 0 && file->Tell() + offs < 0) { + offs -= (_bufferLength - _bufferIndex); + if (offs < 0 && _file->Tell() + offs < 0) { // avoid negative positioning offs = 0; } if (offs != 0) { - SetLastResult(file->Seek(FILESEEKPOSITION_CURRENT, offs)); + SetLastResult(_file->Seek(FILESEEKPOSITION_CURRENT, offs)); result = (E_SUCCESS == GetLastResult()); } else { result = true; @@ -145,7 +150,7 @@ bool BadaFileStream::seek(int32 offs, int whence) { case SEEK_END: // set relative to end - positive will increase the file size - SetLastResult(file->Seek(FILESEEKPOSITION_END, offs)); + SetLastResult(_file->Seek(FILESEEKPOSITION_END, offs)); result = (E_SUCCESS == GetLastResult()); break; @@ -158,46 +163,46 @@ bool BadaFileStream::seek(int32 offs, int whence) { AppLog("seek failed"); } - bufferIndex = bufferLength = 0; + _bufferIndex = _bufferLength = 0; return result; } -uint32 BadaFileStream::read(void *ptr, uint32 len) { +uint32 TizenFileStream::read(void *ptr, uint32 len) { uint32 result = 0; if (!eos()) { - if (bufferIndex < bufferLength) { + if (_bufferIndex < _bufferLength) { // use existing buffer - uint32 available = bufferLength - bufferIndex; + uint32 available = _bufferLength - _bufferIndex; if (len <= available) { // use allocation - memcpy((byte *)ptr, &buffer[bufferIndex], len); - bufferIndex += len; + memcpy((byte *)ptr, &_buffer[_bufferIndex], len); + _bufferIndex += len; result = len; } else { // use remaining allocation - memcpy((byte *)ptr, &buffer[bufferIndex], available); + memcpy((byte *)ptr, &_buffer[_bufferIndex], available); uint32 remaining = len - available; result = available; if (remaining) { - result += file->Read(((byte *)ptr) + available, remaining); + result += _file->Read(((byte *)ptr) + available, remaining); } - bufferIndex = bufferLength = 0; + _bufferIndex = _bufferLength = 0; } } else if (len < BUFFER_SIZE) { // allocate and use buffer - bufferIndex = 0; - bufferLength = file->Read(buffer, BUFFER_SIZE); - if (bufferLength) { - if (bufferLength < len) { - len = bufferLength; + _bufferIndex = 0; + _bufferLength = _file->Read(_buffer, BUFFER_SIZE); + if (_bufferLength) { + if (_bufferLength < len) { + len = _bufferLength; } - memcpy((byte *)ptr, buffer, len); - result = bufferIndex = len; + memcpy((byte *)ptr, _buffer, len); + result = _bufferIndex = len; } } else { - result = file->Read((byte *)ptr, len); - bufferIndex = bufferLength = 0; + result = _file->Read((byte *)ptr, len); + _bufferIndex = _bufferLength = 0; } } else { AppLog("Attempted to read past EOS"); @@ -205,59 +210,77 @@ uint32 BadaFileStream::read(void *ptr, uint32 len) { return result; } -uint32 BadaFileStream::write(const void *ptr, uint32 len) { - result r = file->Write(ptr, len); +uint32 TizenFileStream::write(const void *ptr, uint32 len) { + result r = _file->Write(ptr, len); SetLastResult(r); return (r == E_SUCCESS ? len : 0); } -bool BadaFileStream::flush() { +bool TizenFileStream::flush() { logEntered(); - SetLastResult(file->Flush()); + SetLastResult(_file->Flush()); return (E_SUCCESS == GetLastResult()); } -BadaFileStream *BadaFileStream::makeFromPath(const String &path, bool writeMode) { +TizenFileStream *TizenFileStream::makeFromPath(const String &path, bool writeMode) { File *ioFile = new File(); String filePath = path; if (writeMode && (path[0] != '.' && path[0] != '/')) { - filePath.Insert(PATH_HOME_X, 0); + filePath.Insert(App::GetInstance()->GetAppDataPath() + L"/", 0); } AppLog("Open file %S", filePath.GetPointer()); - + TizenFileStream *stream; result r = ioFile->Construct(filePath, writeMode ? L"w" : L"r", writeMode); if (r == E_SUCCESS) { - return new BadaFileStream(ioFile, writeMode); + stream = new TizenFileStream(ioFile, writeMode); + } else { + AppLog("Failed to open file"); + delete ioFile; + stream = NULL; } - - AppLog("Failed to open file"); - delete ioFile; - return 0; -} - -// -// converts a bada (wchar) String into a scummVM (char) string -// -Common::String fromString(const Osp::Base::String &in) { - ByteBuffer *buf = StringUtil::StringToUtf8N(in); - Common::String result((const char*)buf->GetPointer()); - delete buf; - - return result; + return stream; } // -// BadaFilesystemNode +// TizenFilesystemNode // -BadaFilesystemNode::BadaFilesystemNode(const Common::String &nodePath) { +TizenFilesystemNode::TizenFilesystemNode(const Common::String &nodePath) { AppAssert(nodePath.size() > 0); init(nodePath); } -BadaFilesystemNode::BadaFilesystemNode(const Common::String &root, - const Common::String &nodePath) { +TizenFilesystemNode::TizenFilesystemNode(SystemPath systemPath) { + switch (systemPath) { + case kData: + _unicodePath = App::GetInstance()->GetAppDataPath(); + _displayName = _s("[ Data ]"); + break; + case kResource: + _unicodePath = App::GetInstance()->GetAppResourcePath(); + _displayName = _s("[ Resources ]"); + break; + case kSdCard: + _unicodePath = Tizen::System::Environment::GetExternalStoragePath(); + _displayName = _s("[ SDCard ]"); + break; + case kMedia: + _unicodePath = Tizen::System::Environment::GetMediaPath(); + _displayName = _s("[ Media ]"); + break; + case kShared: + _unicodePath = App::GetInstance()->GetAppSharedPath(); + _displayName = _s("[ Shared ]"); + break; + } + _path = ::fromString(_unicodePath); + _isValid = _isVirtualDir = !IsFailed(File::GetAttributes(_unicodePath, _attr)); +} + +TizenFilesystemNode::TizenFilesystemNode(const Common::String &root, const Common::String &nodePath) { + AppLog("TizenFilesystemNode '%s' '%s'", root.c_str(), nodePath.c_str()); + // Make sure the string contains no slashes AppAssert(!nodePath.contains('/')); @@ -272,71 +295,53 @@ BadaFilesystemNode::BadaFilesystemNode(const Common::String &root, init(newPath); } -void BadaFilesystemNode::init(const Common::String &nodePath) { +void TizenFilesystemNode::init(const Common::String &nodePath) { // Normalize the path (that is, remove unneeded slashes etc.) _path = Common::normalizePath(nodePath, '/'); _displayName = Common::lastPathComponent(_path, '/'); StringUtil::Utf8ToString(_path.c_str(), _unicodePath); - _isVirtualDir = (_path == PATH_ROOT || - _path == PATH_HOME || - _path == PATH_HOME_SHARE || - _path == PATH_HOME_SHARE2 || - _path == PATH_CARD); + _isVirtualDir = (_path == "/"); _isValid = _isVirtualDir || !IsFailed(File::GetAttributes(_unicodePath, _attr)); } -bool BadaFilesystemNode::exists() const { +bool TizenFilesystemNode::exists() const { return _isValid; } -bool BadaFilesystemNode::isReadable() const { +bool TizenFilesystemNode::isReadable() const { return _isVirtualDir || _isValid; } -bool BadaFilesystemNode::isDirectory() const { +bool TizenFilesystemNode::isDirectory() const { return _isVirtualDir || (_isValid && _attr.IsDirectory()); } -bool BadaFilesystemNode::isWritable() const { - bool result = (_isValid && !_isVirtualDir && !_attr.IsDirectory() && !_attr.IsReadOnly()); - if (_path == PATH_HOME || - _path == PATH_HOME_EXT || - _path == PATH_HOME_SHARE || - _path == PATH_HOME_SHARE2) { - result = true; +bool TizenFilesystemNode::isWritable() const { + bool result = (_isValid && !_attr.IsReadOnly()); + if (_unicodePath == App::GetInstance()->GetAppResourcePath()) { + result = false; } return result; } -AbstractFSNode *BadaFilesystemNode::getChild(const Common::String &n) const { +AbstractFSNode *TizenFilesystemNode::getChild(const Common::String &n) const { AppAssert(!_path.empty()); AppAssert(isDirectory()); - return new BadaFilesystemNode(_path, n); + return new TizenFilesystemNode(_path, n); } -bool BadaFilesystemNode::getChildren(AbstractFSList &myList, - ListMode mode, bool hidden) const { +bool TizenFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const { AppAssert(isDirectory()); bool result = false; - if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly) { - // present well known BADA file system areas - if (_path == PATH_ROOT) { - myList.push_back(new BadaFilesystemNode(PATH_HOME)); - myList.push_back(new BadaFilesystemNode(PATH_HOME_EXT)); - myList.push_back(new BadaFilesystemNode(PATH_MEDIA)); - myList.push_back(new BadaFilesystemNode(PATH_CARD)); - result = true; // no more entries - } else if (_path == PATH_CARD) { - myList.push_back(new BadaFilesystemNode(PATH_CARD_MEDIA)); - result = true; // no more entries - } else if (_path == PATH_HOME) { - // ensure share path is always included - myList.push_back(new BadaFilesystemNode(PATH_HOME_SHARE)); - myList.push_back(new BadaFilesystemNode(PATH_HOME_SHARE2)); - } + if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly && _path == "/") { + // present well known TIZEN file system areas + myList.push_back(new TizenFilesystemNode(kData)); + myList.push_back(new TizenFilesystemNode(kSdCard)); + myList.push_back(new TizenFilesystemNode(kMedia)); + myList.push_back(new TizenFilesystemNode(kShared)); } if (!result) { @@ -358,7 +363,7 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList, DirEntry dirEntry = pDirEnum->GetCurrentDirEntry(); // skip 'invisible' files if necessary - Osp::Base::String fileName = dirEntry.GetName(); + Tizen::Base::String fileName = dirEntry.GetName(); if (fileName[0] == '.' && !hidden) { continue; @@ -374,7 +379,7 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList, (mode == Common::FSNode::kListDirectoriesOnly && !dirEntry.IsDirectory())) { continue; } - myList.push_back(new BadaFilesystemNode(_path, fromString(fileName))); + myList.push_back(new TizenFilesystemNode(_path, ::fromString(fileName))); } } @@ -392,9 +397,9 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList, return result; } -AbstractFSNode *BadaFilesystemNode::getParent() const { - logEntered(); - if (_path == PATH_ROOT) { +AbstractFSNode *TizenFilesystemNode::getParent() const { + logEntered(); + if (_path == "/") { return 0; // The filesystem root has no parent } @@ -412,22 +417,22 @@ AbstractFSNode *BadaFilesystemNode::getParent() const { // there simply is no parent. // TODO: We could also resolve this by assuming that the parent is the // current working directory, and returning a node referring to that. - return 0; + return NULL; } - return new BadaFilesystemNode(Common::String(start, end)); + return new TizenFilesystemNode(Common::String(start, end)); } -Common::SeekableReadStream *BadaFilesystemNode::createReadStream() { - Common::SeekableReadStream *result = BadaFileStream::makeFromPath(_unicodePath, false); +Common::SeekableReadStream *TizenFilesystemNode::createReadStream() { + Common::SeekableReadStream *result = TizenFileStream::makeFromPath(_unicodePath, false); if (result != NULL) { _isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr)); } return result; } -Common::WriteStream *BadaFilesystemNode::createWriteStream() { - Common::WriteStream *result = BadaFileStream::makeFromPath(_unicodePath, true); +Common::WriteStream *TizenFilesystemNode::createWriteStream() { + Common::WriteStream *result = TizenFileStream::makeFromPath(_unicodePath, true); if (result != NULL) { _isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr)); } diff --git a/backends/platform/bada/fs.h b/backends/platform/tizen/fs.h index d7d368ac20..0356aaad33 100644 --- a/backends/platform/bada/fs.h +++ b/backends/platform/tizen/fs.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef BADA_FILESYSTEM_H -#define BADA_FILESYSTEM_H +#ifndef TIZEN_FILESYSTEM_H +#define TIZEN_FILESYSTEM_H #include <FBaseString.h> #include <FBaseUtilStringUtil.h> @@ -32,23 +32,40 @@ #include "common/stream.h" #include "backends/fs/abstract-fs.h" -using namespace Osp::Io; -using namespace Osp::Base; -using namespace Osp::Base::Utility; +using namespace Tizen::Io; +using namespace Tizen::Base; +using namespace Tizen::Base::Utility; + +// +// converts a Tizen (wchar) String into a scummVM (char) string +// +Common::String fromString(const Tizen::Base::String &in); + +// +// Enumerates the possible system paths +// +enum SystemPath { kData, kResource, kSdCard, kMedia, kShared }; /** - * Implementation of the ScummVM file system API based on BADA. + * Implementation of the ScummVM file system API based on TIZEN. * * Parts of this class are documented in the base interface class, AbstractFSNode. */ -class BadaFilesystemNode : public AbstractFSNode { +class TizenFilesystemNode : public AbstractFSNode { public: /** - * Creates a BadaFilesystemNode for a given path. + * Creates a TizenFilesystemNode for a given path. + * + * @param path the path the new node should point to. + */ + TizenFilesystemNode(const Common::String &path); + + /** + * Creates a TizenFilesystemNode from the given Tizen internal path * * @param path the path the new node should point to. */ - BadaFilesystemNode(const Common::String &path); + TizenFilesystemNode(SystemPath systemPath); Common::String getDisplayName() const { return _displayName; } Common::String getName() const { return _displayName; } @@ -67,8 +84,7 @@ public: Common::WriteStream *createWriteStream(); protected: - BadaFilesystemNode(const Common::String &root, - const Common::String &p); + TizenFilesystemNode(const Common::String &root, const Common::String &p); void init(const Common::String &nodePath); Common::String _displayName; diff --git a/backends/platform/bada/graphics.cpp b/backends/platform/tizen/graphics.cpp index bd65c597c6..390796dc0e 100644 --- a/backends/platform/bada/graphics.cpp +++ b/backends/platform/tizen/graphics.cpp @@ -22,35 +22,62 @@ #include "graphics/fontman.h" -#include "backends/platform/bada/form.h" -#include "backends/platform/bada/system.h" -#include "backends/platform/bada/graphics.h" +#include "backends/platform/tizen/form.h" +#include "backends/platform/tizen/system.h" +#include "backends/platform/tizen/graphics.h" // -// BadaGraphicsManager +// TizenGraphicsManager // -BadaGraphicsManager::BadaGraphicsManager(BadaAppForm *appForm) : +TizenGraphicsManager::TizenGraphicsManager(TizenAppForm *appForm) : _appForm(appForm), _eglDisplay(EGL_DEFAULT_DISPLAY), _eglSurface(EGL_NO_SURFACE), - _eglConfig(0), + _eglConfig(NULL), _eglContext(EGL_NO_CONTEXT), _initState(true) { assert(appForm != NULL); - _videoMode.fullscreen = true; } -const Graphics::Font *BadaGraphicsManager::getFontOSD() { +TizenGraphicsManager::~TizenGraphicsManager() { + logEntered(); + + if (_eglDisplay != EGL_NO_DISPLAY) { + eglMakeCurrent(_eglDisplay, NULL, NULL, NULL); + if (_eglContext != EGL_NO_CONTEXT) { + eglDestroyContext(_eglDisplay, _eglContext); + } + } +} + +result TizenGraphicsManager::Construct() { + // Initialize our OpenGL ES context. + loadEgl(); + + // Notify the OpenGL code about our context. + + // We default to RGB565 and RGBA5551 which is closest to the actual output + // mode we setup. + notifyContextChange(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); + + // Tell our size. + int x, y, width, height; + _appForm->GetBounds(x, y, width, height); + AppLog("screen size: %dx%d", width, height); + setActualScreenSize(width, height); + return E_SUCCESS; +} + +const Graphics::Font *TizenGraphicsManager::getFontOSD() { return FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); } -bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) { - int16 currentX = _cursorState.x; - int16 currentY = _cursorState.y; +bool TizenGraphicsManager::moveMouse(int16 &x, int16 &y) { + int16 currentX, currentY; + getMousePosition(currentX, currentY); // save the current hardware coordinates - _cursorState.x = x; - _cursorState.y = y; + setMousePosition(x, y); // return x/y as game coordinates adjustMousePosition(x, y); @@ -62,7 +89,7 @@ bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) { return (currentX != x || currentY != y); } -Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() const { +Common::List<Graphics::PixelFormat> TizenGraphicsManager::getSupportedFormats() const { logEntered(); Common::List<Graphics::PixelFormat> res; @@ -73,33 +100,42 @@ Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() c return res; } -bool BadaGraphicsManager::hasFeature(OSystem::Feature f) { - bool result = (f == OSystem::kFeatureFullscreenMode || - f == OSystem::kFeatureVirtualKeyboard || - OpenGLGraphicsManager::hasFeature(f)); +bool TizenGraphicsManager::hasFeature(OSystem::Feature f) { + bool result = + (f == OSystem::kFeatureVirtualKeyboard || + OpenGLGraphicsManager::hasFeature(f)); return result; } -void BadaGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { - OpenGLGraphicsManager::setFeatureState(f, enable); +void TizenGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + if (f == OSystem::kFeatureVirtualKeyboard) { + if (enable) { + _appForm->showKeypad(); + } + } else { + OpenGLGraphicsManager::setFeatureState(f, enable); + } } -void BadaGraphicsManager::setReady() { +void TizenGraphicsManager::setReady() { + logEntered(); + _appForm->GetVisualElement()->SetShowState(true); _initState = false; } -void BadaGraphicsManager::updateScreen() { - if (_transactionMode == kTransactionNone) { - internUpdateScreen(); +void TizenGraphicsManager::updateScreen() { + if (!_initState) { + OpenGLGraphicsManager::updateScreen(); + eglSwapBuffers(_eglDisplay, _eglSurface); } } -bool BadaGraphicsManager::loadEgl() { +bool TizenGraphicsManager::loadEgl() { logEntered(); EGLint numConfigs = 1; EGLint eglConfigList[] = { - EGL_RED_SIZE, 5, + EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 0, @@ -116,10 +152,6 @@ bool BadaGraphicsManager::loadEgl() { eglBindAPI(EGL_OPENGL_ES_API); - if (_eglDisplay) { - unloadGFXMode(); - } - _eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY); if (EGL_NO_DISPLAY == _eglDisplay) { systemError("eglGetDisplay() failed"); @@ -132,8 +164,7 @@ bool BadaGraphicsManager::loadEgl() { return false; } - if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList, - &_eglConfig, 1, &numConfigs) || + if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList, &_eglConfig, 1, &numConfigs) || EGL_SUCCESS != eglGetError()) { systemError("eglChooseConfig() failed"); return false; @@ -144,15 +175,13 @@ bool BadaGraphicsManager::loadEgl() { return false; } - _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, - (EGLNativeWindowType)_appForm, NULL); + _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, (EGLNativeWindowType)_appForm, NULL); if (EGL_NO_SURFACE == _eglSurface || EGL_SUCCESS != eglGetError()) { systemError("eglCreateWindowSurface() failed. EGL_NO_SURFACE"); return false; } - _eglContext = eglCreateContext(_eglDisplay, _eglConfig, - EGL_NO_CONTEXT, eglContextList); + _eglContext = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT, eglContextList); if (EGL_NO_CONTEXT == _eglContext || EGL_SUCCESS != eglGetError()) { systemError("eglCreateContext() failed"); @@ -164,98 +193,12 @@ bool BadaGraphicsManager::loadEgl() { systemError("eglMakeCurrent() failed"); return false; } - logLeaving(); return true; } -bool BadaGraphicsManager::loadGFXMode() { - logEntered(); - - if (!loadEgl()) { - unloadGFXMode(); - return false; - } - - int x, y, width, height; - _appForm->GetBounds(x, y, width, height); - _videoMode.overlayWidth = _videoMode.hardwareWidth = width; - _videoMode.overlayHeight = _videoMode.hardwareHeight = height; - _videoMode.scaleFactor = 3; // for proportional sized cursor in the launcher - - AppLog("screen size: %dx%d", _videoMode.hardwareWidth, _videoMode.hardwareHeight); - return OpenGLGraphicsManager::loadGFXMode(); -} - -void BadaGraphicsManager::loadTextures() { - logEntered(); - - OpenGLGraphicsManager::loadTextures(); - - // prevent image skew in some games, see: - // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -} - -void BadaGraphicsManager::internUpdateScreen() { - if (!_initState) { - OpenGLGraphicsManager::internUpdateScreen(); - eglSwapBuffers(_eglDisplay, _eglSurface); - } else { - showSplash(); - } -} - -void BadaGraphicsManager::unloadGFXMode() { - logEntered(); - - if (EGL_NO_DISPLAY != _eglDisplay) { - eglMakeCurrent(_eglDisplay, NULL, NULL, NULL); - - if (_eglContext != EGL_NO_CONTEXT) { - eglDestroyContext(_eglDisplay, _eglContext); - _eglContext = EGL_NO_CONTEXT; - } - - if (_eglSurface != EGL_NO_SURFACE) { - eglDestroySurface(_eglDisplay, _eglSurface); - _eglSurface = EGL_NO_SURFACE; - } - - eglTerminate(_eglDisplay); - _eglDisplay = EGL_NO_DISPLAY; - } - - _eglConfig = NULL; - - OpenGLGraphicsManager::unloadGFXMode(); - logLeaving(); -} - -// display a simple splash screen until launcher is ready -void BadaGraphicsManager::showSplash() { - Canvas canvas; - canvas.Construct(); - canvas.SetBackgroundColor(Color::COLOR_BLACK); - canvas.Clear(); - - int x = _videoMode.hardwareWidth / 3; - int y = _videoMode.hardwareHeight / 3; - - Font *pFont = new Font(); - pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 55); - canvas.SetFont(*pFont); - canvas.SetForegroundColor(Color::COLOR_GREEN); - canvas.DrawText(Point(x, y), L"ScummVM"); - delete pFont; - - pFont = new Font(); - pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 35); - canvas.SetFont(*pFont); - canvas.SetForegroundColor(Color::COLOR_WHITE); - canvas.DrawText(Point(x + 70, y + 50), L"Loading ..."); - delete pFont; - - canvas.Show(); - +bool TizenGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) { + // We get this whenever a new resolution is requested. Since Tizen is + // using a fixed output size we do nothing like that here. + return true; } diff --git a/backends/platform/bada/graphics.h b/backends/platform/tizen/graphics.h index b2aaca43bc..29ba86a3c4 100644 --- a/backends/platform/bada/graphics.h +++ b/backends/platform/tizen/graphics.h @@ -20,8 +20,8 @@ * */ -#ifndef BADA_GRAPHICS_H -#define BADA_GRAPHICS_H +#ifndef TIZEN_GRAPHICS_H +#define TIZEN_GRAPHICS_H #include <FBase.h> #include <FGraphics.h> @@ -33,35 +33,39 @@ #include "config.h" #include "backends/graphics/opengl/opengl-graphics.h" #include "graphics/font.h" -#include "backends/platform/bada/form.h" +#include "backends/platform/tizen/form.h" -using namespace Osp::Graphics; -using namespace Osp::Graphics::Opengl; -using namespace Osp::App; +using namespace Tizen::Graphics; +using namespace Tizen::Graphics::Opengl; +using namespace Tizen::App; -class BadaGraphicsManager : public OpenGLGraphicsManager { +class TizenGraphicsManager : public OpenGL::OpenGLGraphicsManager { public: - BadaGraphicsManager(BadaAppForm *appForm); + TizenGraphicsManager(TizenAppForm *appForm); + virtual ~TizenGraphicsManager(); + + result Construct(); Common::List<Graphics::PixelFormat> getSupportedFormats() const; bool hasFeature(OSystem::Feature f); - void updateScreen(); void setFeatureState(OSystem::Feature f, bool enable); + void updateScreen(); + void setReady(); bool isReady() { return !_initState; } - const Graphics::Font *getFontOSD(); + bool moveMouse(int16 &x, int16 &y); -private: - void internUpdateScreen(); - bool loadGFXMode(); - void loadTextures(); - void unloadGFXMode(); +protected: void setInternalMousePosition(int x, int y) {} - void showSplash(); + bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format); + + const Graphics::Font *getFontOSD(); + +private: bool loadEgl(); - BadaAppForm *_appForm; + TizenAppForm *_appForm; EGLDisplay _eglDisplay; EGLSurface _eglSurface; EGLConfig _eglConfig; diff --git a/backends/platform/bada/main.cpp b/backends/platform/tizen/main.cpp index 8c40f24dd1..b12cc3adc9 100644 --- a/backends/platform/bada/main.cpp +++ b/backends/platform/tizen/main.cpp @@ -24,44 +24,28 @@ #include <FApp.h> #include <FSystem.h> -#include "backends/platform/bada/portdefs.h" -#include "backends/platform/bada/form.h" -#include "backends/platform/bada/system.h" -#include "backends/platform/bada/application.h" +#include "backends/platform/tizen/application.h" -using namespace Osp::Base; -using namespace Osp::Base::Collection; - -C_LINKAGE_BEGIN - -_EXPORT_ int OspMain(int argc, char *pArgv[]); +using namespace Tizen::Base; +using namespace Tizen::Base::Collection; /** - * The entry function of bada application called by the operating system. + * The entry function of tizen application called by the operating system. */ -int OspMain(int argc, char *pArgv[]) { +extern "C" _EXPORT_ int OspMain(int argc, char *pArgv[]) { result r = E_SUCCESS; AppLog("Application started."); - ArrayList *pArgs = new ArrayList(); - pArgs->Construct(); - + ArrayList args(SingleObjectDeleter); + args.Construct(); for (int i = 0; i < argc; i++) { - pArgs->Add(*(new String(pArgv[i]))); + args.Add(new (std::nothrow) String(pArgv[i])); } - r = Osp::App::Application::Execute(BadaScummVM::createInstance, pArgs); - if (IsFailed(r)) { - r &= 0x0000FFFF; - } - - pArgs->RemoveAll(true); - delete pArgs; + r = Tizen::App::UiApp::Execute(TizenScummVM::createInstance, &args); + TryLog(r == E_SUCCESS, "[%s] Application execution failed", GetErrorMessage(r)); AppLog("Application finished."); return static_cast<int>(r); } -C_LINKAGE_END - - diff --git a/backends/platform/bada/missing.cpp b/backends/platform/tizen/missing.cpp index 10d45ca4b5..5ac55d0f6c 100644 --- a/backends/platform/bada/missing.cpp +++ b/backends/platform/tizen/missing.cpp @@ -26,7 +26,7 @@ #include <FSystem.h> #include <FBase.h> -#include "backends/platform/bada/portdefs.h" +#include "backends/platform/tizen/portdefs.h" #include <stdio.h> #include <string.h> @@ -48,7 +48,7 @@ void __assert_func(const char *file, int line, systemError(buffer); } -void stderr_fprintf(void*, const char *format, ...) { +void stderr_fprintf(void *, const char *format, ...) { va_list ap; char buffer[BUF_SIZE]; @@ -59,7 +59,7 @@ void stderr_fprintf(void*, const char *format, ...) { AppLog(buffer); } -void stderr_vfprintf(void*, const char *format, va_list ap) { +void stderr_vfprintf(void *, const char *format, va_list ap) { char buffer[BUF_SIZE]; vsnprintf(buffer, sizeof(buffer), format, ap); AppLog(buffer); @@ -79,35 +79,4 @@ int printf(const char *format, ...) { return result; } -int sprintf(char *str, const char *format, ...) { - va_list ap; - int result; - char buffer[BUF_SIZE]; - - va_start(ap, format); - result = vsnprintf(buffer, sizeof(buffer), format, ap); - va_end(ap); - - strcpy(str, buffer); - - return result; -} - -char *strdup(const char *strSource) { - char *buffer; - int len = strlen(strSource) + 1; - buffer = (char *)malloc(len); - if (buffer) { - memcpy(buffer, strSource, len); - } - return buffer; -} - -int vsprintf(char *str, const char *format, va_list ap) { - char buffer[BUF_SIZE]; - int result = vsnprintf(buffer, sizeof(buffer), format, ap); - strcpy(str, buffer); - return result; -} - C_LINKAGE_END diff --git a/backends/platform/bada/portdefs.h b/backends/platform/tizen/portdefs.h index 813c5acde3..050ce7d1e0 100644 --- a/backends/platform/bada/portdefs.h +++ b/backends/platform/tizen/portdefs.h @@ -43,6 +43,9 @@ #define C_LINKAGE_END #endif +// value missing from osp gl headers +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 + C_LINKAGE_BEGIN // for libFLAC @@ -51,11 +54,11 @@ C_LINKAGE_BEGIN #define fseeko fseek #define ftello ftell -// overcome use of fprintf since bada/newlib (1.2) does not +// overcome use of fprintf since newlib (1.2) does not // support stderr/stdout (undefined reference to `_impure_ptr'). -void stderr_fprintf(void*, const char *format, ...); -void stderr_vfprintf(void*, const char *format, va_list ap); +void stderr_fprintf(void *, const char *format, ...); +void stderr_vfprintf(void *, const char *format, va_list ap); #undef fprintf #undef vfprintf @@ -75,10 +78,7 @@ void stderr_vfprintf(void*, const char *format, va_list ap); #define vfprintf stderr_vfprintf int printf(const char *format, ...); -int sprintf(char *str, const char *format, ...); int simple_sscanf(const char *buffer, const char *format, ...); -char *strdup(const char *s1); -int vsprintf(char *str, const char *format, va_list ap); C_LINKAGE_END diff --git a/backends/platform/bada/sscanf.cpp b/backends/platform/tizen/sscanf.cpp index aa846698f6..75f009cc61 100644 --- a/backends/platform/bada/sscanf.cpp +++ b/backends/platform/tizen/sscanf.cpp @@ -93,7 +93,7 @@ bool scanStringUntil(const char **in, va_list *ap, char c_end) { char *arg = va_arg(*ap, char*); while (**in && **in != c_end) { *arg = **in; - *arg++; + arg++; (*in)++; } *arg = 0; diff --git a/backends/platform/bada/system.cpp b/backends/platform/tizen/system.cpp index 3f862c2571..f7ebc46719 100644 --- a/backends/platform/bada/system.cpp +++ b/backends/platform/tizen/system.cpp @@ -34,53 +34,53 @@ #include "backends/audiocd/default/default-audiocd.h" #include "backends/mutex/mutex.h" #include "backends/fs/fs-factory.h" -#include "backends/timer/bada/timer.h" +#include "backends/timer/tizen/timer.h" -#include "backends/platform/bada/form.h" -#include "backends/platform/bada/system.h" -#include "backends/platform/bada/graphics.h" -#include "backends/platform/bada/audio.h" +#include "backends/platform/tizen/form.h" +#include "backends/platform/tizen/system.h" +#include "backends/platform/tizen/graphics.h" +#include "backends/platform/tizen/audio.h" -using namespace Osp::Base; -using namespace Osp::Base::Runtime; -using namespace Osp::Locales; -using namespace Osp::Ui::Controls; -using namespace Osp::System; +using namespace Tizen::Base; +using namespace Tizen::Base::Runtime; +using namespace Tizen::Locales; +using namespace Tizen::Ui; +using namespace Tizen::Ui::Controls; +using namespace Tizen::System; -#define DEFAULT_CONFIG_FILE "/Home/scummvm.ini" -#define RESOURCE_PATH "/Res" +#define DEFAULT_CONFIG_FILE "scummvm.ini" #define MUTEX_BUFFER_SIZE 5 // -// BadaFilesystemFactory +// TizenFilesystemFactory // -class BadaFilesystemFactory : public FilesystemFactory { +class TizenFilesystemFactory : public FilesystemFactory { AbstractFSNode *makeRootFileNode() const; AbstractFSNode *makeCurrentDirectoryFileNode() const; AbstractFSNode *makeFileNodePath(const Common::String &path) const; }; -AbstractFSNode *BadaFilesystemFactory::makeRootFileNode() const { - return new BadaFilesystemNode("/"); +AbstractFSNode *TizenFilesystemFactory::makeRootFileNode() const { + return new TizenFilesystemNode("/"); } -AbstractFSNode *BadaFilesystemFactory::makeCurrentDirectoryFileNode() const { - return new BadaFilesystemNode("/Home"); +AbstractFSNode *TizenFilesystemFactory::makeCurrentDirectoryFileNode() const { + return new TizenFilesystemNode("/"); } -AbstractFSNode *BadaFilesystemFactory::makeFileNodePath(const Common::String &path) const { +AbstractFSNode *TizenFilesystemFactory::makeFileNodePath(const Common::String &path) const { AppAssert(!path.empty()); - return new BadaFilesystemNode(path); + return new TizenFilesystemNode(path); } // -// BadaSaveFileManager +// TizenSaveFileManager // -struct BadaSaveFileManager : public DefaultSaveFileManager { +struct TizenSaveFileManager : public DefaultSaveFileManager { bool removeSavefile(const Common::String &filename); }; -bool BadaSaveFileManager::removeSavefile(const Common::String &filename) { +bool TizenSaveFileManager::removeSavefile(const Common::String &filename) { Common::String savePathName = getSavePath(); checkPath(Common::FSNode(savePathName)); @@ -95,18 +95,18 @@ bool BadaSaveFileManager::removeSavefile(const Common::String &filename) { String unicodeFileName; StringUtil::Utf8ToString(file.getPath().c_str(), unicodeFileName); - switch (Osp::Io::File::Remove(unicodeFileName)) { + switch (Tizen::Io::File::Remove(unicodeFileName)) { case E_SUCCESS: return true; case E_ILLEGAL_ACCESS: setError(Common::kWritePermissionDenied, "Search or write permission denied: " + - file.getName()); + file.getName()); break; default: setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() + - "' does not exist or path is invalid"); + "' does not exist or path is invalid"); break; } @@ -114,40 +114,40 @@ bool BadaSaveFileManager::removeSavefile(const Common::String &filename) { } // -// BadaMutexManager +// TizenMutexManager // -struct BadaMutexManager : public MutexManager { - BadaMutexManager(); - ~BadaMutexManager(); +struct TizenMutexManager : public MutexManager { + TizenMutexManager(); + ~TizenMutexManager(); OSystem::MutexRef createMutex(); void lockMutex(OSystem::MutexRef mutex); void unlockMutex(OSystem::MutexRef mutex); void deleteMutex(OSystem::MutexRef mutex); private: - Mutex *buffer[MUTEX_BUFFER_SIZE]; + Mutex *_buffer[MUTEX_BUFFER_SIZE]; }; -BadaMutexManager::BadaMutexManager() { +TizenMutexManager::TizenMutexManager() { for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { - buffer[i] = NULL; + _buffer[i] = NULL; } } -BadaMutexManager::~BadaMutexManager() { +TizenMutexManager::~TizenMutexManager() { for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { - if (buffer[i] != NULL) { - delete buffer[i]; + if (_buffer[i] != NULL) { + delete _buffer[i]; } } } -OSystem::MutexRef BadaMutexManager::createMutex() { +OSystem::MutexRef TizenMutexManager::createMutex() { Mutex *mutex = new Mutex(); mutex->Create(); for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { - if (buffer[i] == NULL) { - buffer[i] = mutex; + if (_buffer[i] == NULL) { + _buffer[i] = mutex; break; } } @@ -155,22 +155,22 @@ OSystem::MutexRef BadaMutexManager::createMutex() { return (OSystem::MutexRef) mutex; } -void BadaMutexManager::lockMutex(OSystem::MutexRef mutex) { +void TizenMutexManager::lockMutex(OSystem::MutexRef mutex) { Mutex *m = (Mutex *)mutex; m->Acquire(); } -void BadaMutexManager::unlockMutex(OSystem::MutexRef mutex) { +void TizenMutexManager::unlockMutex(OSystem::MutexRef mutex) { Mutex *m = (Mutex *)mutex; m->Release(); } -void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) { +void TizenMutexManager::deleteMutex(OSystem::MutexRef mutex) { Mutex *m = (Mutex *)mutex; for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { - if (buffer[i] == m) { - buffer[i] = NULL; + if (_buffer[i] == m) { + _buffer[i] = NULL; } } @@ -178,84 +178,101 @@ void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) { } // -// BadaEventManager +// TizenEventManager // -struct BadaEventManager : public DefaultEventManager { - BadaEventManager(Common::EventSource *boss); +struct TizenEventManager : public DefaultEventManager { + TizenEventManager(Common::EventSource *boss); void init(); int shouldQuit() const; }; -BadaEventManager::BadaEventManager(Common::EventSource *boss) : +TizenEventManager::TizenEventManager(Common::EventSource *boss) : DefaultEventManager(boss) { } -void BadaEventManager::init() { +void TizenEventManager::init() { DefaultEventManager::init(); // theme and vkbd should have now loaded - clear the splash screen - BadaSystem *system = (BadaSystem *)g_system; - BadaGraphicsManager *graphics = system->getGraphics(); + TizenSystem *system = (TizenSystem *)g_system; + TizenGraphicsManager *graphics = system->getGraphics(); if (graphics) { graphics->setReady(); - graphics->updateScreen(); } } -int BadaEventManager::shouldQuit() const { - BadaSystem *system = (BadaSystem *)g_system; +int TizenEventManager::shouldQuit() const { + TizenSystem *system = (TizenSystem *)g_system; return DefaultEventManager::shouldQuit() || system->isClosing(); } // -// BadaSystem +// TizenAppFrame - avoid drawing the misplaced UiTheme at startup // -BadaSystem::BadaSystem(BadaAppForm *appForm) : +struct TizenAppFrame : Frame { + result OnDraw(void) { + logEntered(); + TizenAppForm *form = (TizenAppForm *)GetCurrentForm(); + if (form->isStarting()) { + Canvas *canvas = GetCanvasN(); + canvas->SetBackgroundColor(Color::GetColor(COLOR_ID_BLACK)); + canvas->Clear(); + delete canvas; + } + return E_SUCCESS; + } +}; + +// +// TizenSystem +// +TizenSystem::TizenSystem(TizenAppForm *appForm) : _appForm(appForm), _audioThread(0), _epoch(0) { } -result BadaSystem::Construct(void) { +result TizenSystem::Construct(void) { logEntered(); - _fsFactory = new BadaFilesystemFactory(); + _fsFactory = new TizenFilesystemFactory(); if (!_fsFactory) { return E_OUT_OF_MEMORY; } + _resourcePath = fromString(App::GetInstance()->GetAppResourcePath()); return E_SUCCESS; } -BadaSystem::~BadaSystem() { +TizenSystem::~TizenSystem() { logEntered(); } -result BadaSystem::initModules() { +result TizenSystem::initModules() { logEntered(); - _mutexManager = new BadaMutexManager(); + _mutexManager = new TizenMutexManager(); if (!_mutexManager) { return E_OUT_OF_MEMORY; } - _timerManager = new BadaTimerManager(); + _timerManager = new TizenTimerManager(); if (!_timerManager) { return E_OUT_OF_MEMORY; } - _savefileManager = new BadaSaveFileManager(); + _savefileManager = new TizenSaveFileManager(); if (!_savefileManager) { return E_OUT_OF_MEMORY; } - _graphicsManager = (GraphicsManager *)new BadaGraphicsManager(_appForm); - if (!_graphicsManager) { + _graphicsManager = (GraphicsManager *)new TizenGraphicsManager(_appForm); + if (!_graphicsManager || graphicsManager->Construct() != E_SUCCESS) { return E_OUT_OF_MEMORY; } // depends on _graphicsManager when ENABLE_VKEYBD enabled - _eventManager = new BadaEventManager(this); + _eventManager = new TizenEventManager(this); if (!_eventManager) { return E_OUT_OF_MEMORY; } @@ -284,19 +301,21 @@ result BadaSystem::initModules() { return E_SUCCESS; } -void BadaSystem::initBackend() { +void TizenSystem::initBackend() { logEntered(); + Common::String dataPath = fromString(App::GetInstance()->GetAppDataPath()); + // use the mobile device theme - ConfMan.set("gui_theme", "/Res/scummmobile"); + ConfMan.set("gui_theme", _resourcePath + "scummmodern"); - // allow bada virtual keypad pack to be found - ConfMan.set("vkeybdpath", "/Res/vkeybd_bada"); + // allow tizen virtual keypad pack to be found + ConfMan.set("vkeybdpath", _resourcePath + "vkeybd_bada"); ConfMan.set("vkeybd_pack_name", "vkeybd_bada"); // set default save path to writable area if (!ConfMan.hasKey("savepath")) { - ConfMan.set("savepath", "/Home/Share"); + ConfMan.set("savepath", dataPath); } // default to no auto-save @@ -314,85 +333,93 @@ void BadaSystem::initBackend() { AppLog("initModules failed"); } else { OSystem::initBackend(); - } - // replace kBigGUIFont using the large font from the scummmobile theme - Common::File fontFile; - Common::String fileName = "/Res/scummmobile/helvB14-iso-8859-1.fcc"; - BadaFilesystemNode file(fileName); - if (file.exists()) { - Common::SeekableReadStream *stream = file.createReadStream(); - if (stream) { - if (fontFile.open(stream, fileName)) { + // replace kBigGUIFont for the vkbd and on-screen messages + Common::String fontCacheFile = dataPath + "helvR24.fcc"; + TizenFilesystemNode file(fontCacheFile); + if (!file.exists()) { + Common::String bdfFile = _resourcePath + "fonts/helvR24.bdf"; + TizenFilesystemNode file(bdfFile); + if (file.exists()) { + Common::SeekableReadStream *stream = file.createReadStream(); + Common::File fontFile; + if (stream && fontFile.open(stream, bdfFile)) { + Graphics::BdfFont *font = Graphics::BdfFont::loadFont(fontFile); + Graphics::BdfFont::cacheFontData(*font, fontCacheFile); + FontMan.setFont(Graphics::FontManager::kBigGUIFont, font); + } + } + } else { + Common::SeekableReadStream *stream = file.createReadStream(); + Common::File fontFile; + if (stream && fontFile.open(stream, fontCacheFile)) { Graphics::BdfFont *font = Graphics::BdfFont::loadFromCache(fontFile); if (font) { - // use this font for the vkbd and on-screen messages FontMan.setFont(Graphics::FontManager::kBigGUIFont, font); } } } } - logLeaving(); } -void BadaSystem::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { +void TizenSystem::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { // allow translations.dat and game .DAT files to be found - s.addDirectory(RESOURCE_PATH, RESOURCE_PATH, priority); + s.addDirectory(_resourcePath, _resourcePath, priority); } -void BadaSystem::destroyBackend() { +void TizenSystem::destroyBackend() { closeAudio(); delete _graphicsManager; - _graphicsManager = 0; + _graphicsManager = NULL; delete _savefileManager; - _savefileManager = 0; + _savefileManager = NULL; delete _fsFactory; - _fsFactory = 0; + _fsFactory = NULL; delete _mixer; - _mixer = 0; + _mixer = NULL; delete _audiocdManager; - _audiocdManager = 0; + _audiocdManager = NULL; delete _timerManager; - _timerManager = 0; + _timerManager = NULL; delete _eventManager; - _eventManager = 0; + _eventManager = NULL; delete _mutexManager; - _mutexManager = 0; + _mutexManager = NULL; } -bool BadaSystem::pollEvent(Common::Event &event) { +bool TizenSystem::pollEvent(Common::Event &event) { return _appForm->pollEvent(event); } -uint32 BadaSystem::getMillis() { +uint32 TizenSystem::getMillis(bool skipRecord) { long long result, ticks = 0; SystemTime::GetTicks(ticks); result = ticks - _epoch; return result; } -void BadaSystem::delayMillis(uint msecs) { +void TizenSystem::delayMillis(uint msecs) { if (!_appForm->isClosing()) { Thread::Sleep(msecs); } } -void BadaSystem::updateScreen() { +void TizenSystem::updateScreen() { if (_graphicsManager != NULL) { _graphicsManager->updateScreen(); } } -void BadaSystem::getTimeAndDate(TimeDate &td) const { +void TizenSystem::getTimeAndDate(TimeDate &td) const { DateTime currentTime; if (E_SUCCESS == SystemTime::GetCurrentTime(WALL_TIME, currentTime)) { @@ -410,11 +437,11 @@ void BadaSystem::getTimeAndDate(TimeDate &td) const { } } -void BadaSystem::fatalError() { +void TizenSystem::fatalError() { systemError("ScummVM: Fatal internal error."); } -void BadaSystem::exitSystem() { +void TizenSystem::exitSystem() { if (_appForm) { closeAudio(); closeGraphics(); @@ -422,7 +449,7 @@ void BadaSystem::exitSystem() { } } -void BadaSystem::logMessage(LogMessageType::Type type, const char *message) { +void TizenSystem::logMessage(LogMessageType::Type type, const char *message) { if (type == LogMessageType::kError) { systemError(message); } else { @@ -430,69 +457,72 @@ void BadaSystem::logMessage(LogMessageType::Type type, const char *message) { } } -Common::SeekableReadStream *BadaSystem::createConfigReadStream() { - BadaFilesystemNode file(DEFAULT_CONFIG_FILE); +Common::SeekableReadStream *TizenSystem::createConfigReadStream() { + TizenFilesystemNode file(fromString(App::GetInstance()->GetAppDataPath()) + DEFAULT_CONFIG_FILE); return file.createReadStream(); } -Common::WriteStream *BadaSystem::createConfigWriteStream() { - BadaFilesystemNode file(DEFAULT_CONFIG_FILE); +Common::WriteStream *TizenSystem::createConfigWriteStream() { + TizenFilesystemNode file(fromString(App::GetInstance()->GetAppDataPath()) + DEFAULT_CONFIG_FILE); return file.createWriteStream(); } -void BadaSystem::closeAudio() { +void TizenSystem::closeAudio() { if (_audioThread) { - _audioThread->Stop(); + _audioThread->Quit(); _audioThread->Join(); delete _audioThread; - _audioThread = 0; + _audioThread = NULL; } } -void BadaSystem::closeGraphics() { +void TizenSystem::closeGraphics() { if (_graphicsManager) { delete _graphicsManager; - _graphicsManager = 0; + _graphicsManager = NULL; } } -void BadaSystem::setMute(bool on) { +void TizenSystem::setMute(bool on) { // only change mute after eventManager init() has completed if (_audioThread) { - BadaGraphicsManager *graphics = getGraphics(); + TizenGraphicsManager *graphics = getGraphics(); if (graphics && graphics->isReady()) { _audioThread->setMute(on); } } } -int BadaSystem::setVolume(bool up, bool minMax) { - int level = -1; - if (_audioThread) { - level = _audioThread->setVolume(up, minMax); - } - return level; -} - // // create the ScummVM system // -BadaAppForm *systemStart(Osp::App::Application *app) { +TizenAppForm *systemStart(Tizen::App::Application *app) { logEntered(); - BadaAppForm *appForm = new BadaAppForm(); + Frame *appFrame = new (std::nothrow) TizenAppFrame(); + if (!appFrame || appFrame->Construct() == E_FAILURE) { + AppLog("Failed to create appFrame"); + return NULL; + } + app->AddFrame(*appFrame); + + TizenAppForm *appForm = new TizenAppForm(); if (!appForm) { AppLog("Failed to create appForm"); return NULL; } if (E_SUCCESS != appForm->Construct() || - E_SUCCESS != app->GetAppFrame()->GetFrame()->AddControl(*appForm)) { + E_SUCCESS != appFrame->AddControl(appForm)) { delete appForm; AppLog("Failed to construct appForm"); return NULL; } + appFrame->SetCurrentForm(appForm); + appForm->GetVisualElement()->SetShowState(false); + + logLeaving(); return appForm; } @@ -502,13 +532,18 @@ BadaAppForm *systemStart(Osp::App::Application *app) { void systemError(const char *message) { AppLog("Fatal system error: %s", message); - ArrayList *args = new ArrayList(); - args->Construct(); - args->Add(*(new String(message))); - Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args); + if (strspn(message, "Config file buggy:") > 0) { + Tizen::Io::File::Remove(App::GetInstance()->GetAppDataPath() + DEFAULT_CONFIG_FILE); + Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR_CONFIG, NULL); + } else { + ArrayList *args = new ArrayList(); + args->Construct(); + args->Add(*(new String(message))); + Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args); + } if (g_system) { - BadaSystem *system = (BadaSystem *)g_system; + TizenSystem *system = (TizenSystem *)g_system; system->exitSystem(); } } diff --git a/backends/platform/bada/system.h b/backends/platform/tizen/system.h index c28686cb3d..b38940cc95 100644 --- a/backends/platform/bada/system.h +++ b/backends/platform/tizen/system.h @@ -20,8 +20,8 @@ * */ -#ifndef BADA_SYSTEM_H -#define BADA_SYSTEM_H +#ifndef TIZEN_SYSTEM_H +#define TIZEN_SYSTEM_H #include <FApp.h> #include <FGraphics.h> @@ -34,47 +34,46 @@ #include "common/scummsys.h" #include "backends/modular-backend.h" -#include "backends/platform/bada/fs.h" -#include "backends/platform/bada/form.h" -#include "backends/platform/bada/audio.h" -#include "backends/platform/bada/graphics.h" +#include "backends/platform/tizen/fs.h" +#include "backends/platform/tizen/form.h" +#include "backends/platform/tizen/audio.h" +#include "backends/platform/tizen/graphics.h" #if defined(_DEBUG) -#define logEntered() AppLog("%s entered (%s %d)", \ - __FUNCTION__, __FILE__, __LINE__); -#define logLeaving() AppLog("%s leaving (%s %d)", \ - __FUNCTION__, __FILE__, __LINE__); +#define logEntered() AppLog("%s entered (%s %d)", __FUNCTION__, __FILE__, __LINE__); +#define logLeaving() AppLog("%s leaving (%s %d)", __FUNCTION__, __FILE__, __LINE__); #else #define logEntered() #define logLeaving() #endif -BadaAppForm *systemStart(Osp::App::Application *app); +TizenAppForm *systemStart(Tizen::App::Application *app); void systemError(const char *message); -#define USER_MESSAGE_EXIT 1000 -#define USER_MESSAGE_EXIT_ERR 1001 +#define USER_MESSAGE_EXIT 1000 +#define USER_MESSAGE_EXIT_ERR 1001 +#define USER_MESSAGE_EXIT_ERR_CONFIG 1002 // -// BadaSystem +// TizenSystem // -class BadaSystem : public ModularBackend, - Common::EventSource { +class TizenSystem : + public ModularBackend, + Common::EventSource { public: - BadaSystem(BadaAppForm *appForm); - ~BadaSystem(); + TizenSystem(TizenAppForm *appForm); + ~TizenSystem(); result Construct(); void closeAudio(); void closeGraphics(); void destroyBackend(); void setMute(bool on); - int setVolume(bool up, bool minMax); void exitSystem(); bool isClosing() { return _appForm->isClosing(); } - BadaGraphicsManager *getGraphics() { - return (BadaGraphicsManager *)_graphicsManager; + TizenGraphicsManager *getGraphics() { + return (TizenGraphicsManager *)_graphicsManager; } private: @@ -83,7 +82,7 @@ private: void updateScreen(); bool pollEvent(Common::Event &event); - uint32 getMillis(); + uint32 getMillis(bool skipRecord = false); void delayMillis(uint msecs); void getTimeAndDate(TimeDate &t) const; void fatalError(); @@ -94,9 +93,10 @@ private: Common::SeekableReadStream *createConfigReadStream(); Common::WriteStream *createConfigWriteStream(); - BadaAppForm *_appForm; + TizenAppForm *_appForm; AudioThread *_audioThread; long long _epoch; + Common::String _resourcePath; }; #endif diff --git a/backends/platform/tizen/tizen.mk b/backends/platform/tizen/tizen.mk new file mode 100644 index 0000000000..d8925b62dc --- /dev/null +++ b/backends/platform/tizen/tizen.mk @@ -0,0 +1,7 @@ +# port files built under eclipse + +MODULE := backends/platform/tizen + +$(EXECUTABLE): $(OBJS) + rm -f $@ + arm-linux-gnueabi-ar Tru $@ $(OBJS) diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp index 22a6495f8f..9d3a7473e3 100644 --- a/backends/platform/wii/osystem.cpp +++ b/backends/platform/wii/osystem.cpp @@ -203,7 +203,7 @@ bool OSystem_Wii::getFeatureState(Feature f) { } } -uint32 OSystem_Wii::getMillis() { +uint32 OSystem_Wii::getMillis(bool skipRecord) { return ticks_to_millisecs(diff_ticks(_startup_time, gettime())); } diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h index 5d6998d0b6..287c70ad6b 100644 --- a/backends/platform/wii/osystem.h +++ b/backends/platform/wii/osystem.h @@ -193,7 +193,7 @@ public: const Graphics::PixelFormat *format); virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); + virtual uint32 getMillis(bool skipRecord = false); virtual void delayMillis(uint msecs); virtual MutexRef createMutex(); diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index a9bcdbb8d1..92c890b0a9 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -528,16 +528,13 @@ void OSystem_Wii::updateScreen() { } Graphics::Surface *OSystem_Wii::lockScreen() { - _surface.pixels = _gamePixels; - _surface.w = _gameWidth; - _surface.h = _gameHeight; + _surface.init(_gameWidth, _gameHeight, #ifdef USE_RGB_COLOR - _surface.pitch = _gameWidth * _pfGame.bytesPerPixel; - _surface.format = _pfGame; + _gameWidth * _pfGame.bytesPerPixel, _gamePixels, _pfGame #else - _surface.pitch = _gameWidth; - _surface.format = Graphics::PixelFormat::createFormatCLUT8(); + _gameWidth, _gamePixels, Graphics::PixelFormat::createFormatCLUT8() #endif + ); return &_surface; } diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index 3897731db4..1c5cd5565b 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -563,7 +563,7 @@ void OSystem_WINCE3::setGraphicsModeIntern() { void OSystem_WINCE3::initSDL() { // Check if SDL has not been initialized if (!_initedSDL) { - uint32 sdlFlags = SDL_INIT_EVENTTHREAD; + uint32 sdlFlags = SDL_INIT_EVENTTHREAD | SDL_INIT_VIDEO; if (ConfMan.hasKey("disable_sdl_parachute")) sdlFlags |= SDL_INIT_NOPARACHUTE; @@ -576,9 +576,6 @@ void OSystem_WINCE3::initSDL() { if (SDL_Init(sdlFlags) == -1) error("Could not initialize SDL: %s", SDL_GetError()); - // Enable unicode support if possible - SDL_EnableUNICODE(1); - _initedSDL = true; } } diff --git a/backends/saves/recorder/recorder-saves.cpp b/backends/saves/recorder/recorder-saves.cpp new file mode 100644 index 0000000000..49b4672913 --- /dev/null +++ b/backends/saves/recorder/recorder-saves.cpp @@ -0,0 +1,35 @@ +/* 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. + * + */ + +#include "backends/saves/recorder/recorder-saves.h" +#include "gui/EventRecorder.h" +#include "common/savefile.h" + +Common::InSaveFile *RecorderSaveFileManager::openForLoading(const Common::String &filename) { + Common::InSaveFile *result = g_eventRec.processSaveStream(filename); + return result; +} + +Common::StringArray RecorderSaveFileManager::listSaveFiles(const Common::String &pattern) { + return g_eventRec.listSaveFiles(pattern); +} + diff --git a/backends/saves/recorder/recorder-saves.h b/backends/saves/recorder/recorder-saves.h new file mode 100644 index 0000000000..692aeca329 --- /dev/null +++ b/backends/saves/recorder/recorder-saves.h @@ -0,0 +1,36 @@ +/* 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 BACKEND_SAVES_RECORDER_H +#define BACKEND_SAVES_RECORDER_H + +#include "backends/saves/default/default-saves.h" + +/** + * Provides a savefile manager implementation for event recorder. + */ +class RecorderSaveFileManager : public DefaultSaveFileManager { + virtual Common::StringArray listSaveFiles(const Common::String &pattern); + virtual Common::InSaveFile *openForLoading(const Common::String &filename); +}; + +#endif diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp index 9f56d58b12..ce93320f3d 100644 --- a/backends/timer/default/default-timer.cpp +++ b/backends/timer/default/default-timer.cpp @@ -80,7 +80,7 @@ DefaultTimerManager::~DefaultTimerManager() { void DefaultTimerManager::handler() { Common::StackLock lock(_mutex); - const uint32 curTime = g_system->getMillis(); + uint32 curTime = g_system->getMillis(true); // Repeat as long as there is a TimerSlot that is scheduled to fire. TimerSlot *slot = _head->next; diff --git a/backends/timer/bada/timer.cpp b/backends/timer/tizen/timer.cpp index e41ecd4864..fa226ce747 100644 --- a/backends/timer/bada/timer.cpp +++ b/backends/timer/tizen/timer.cpp @@ -20,15 +20,14 @@ * */ -#if defined(BADA) +#if defined(TIZEN) -#include "backends/timer/bada/timer.h" +#include "backends/timer/tizen/timer.h" // -// TimerSlot +// TimerSlot - an event driven thread // -TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback, - uint32 interval, void *refCon) : +TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback, uint32 interval, void *refCon) : _timer(0), _callback(callback), _interval(interval), @@ -36,16 +35,17 @@ TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback, } TimerSlot::~TimerSlot() { + delete _timer; } bool TimerSlot::OnStart() { - _timer = new Osp::Base::Runtime::Timer(); + _timer = new Tizen::Base::Runtime::Timer(); if (!_timer || IsFailed(_timer->Construct(*this))) { AppLog("Failed to create timer"); return false; } - if (IsFailed(_timer->Start(_interval))) { + if (IsFailed(_timer->StartAsRepeatable(_interval))) { AppLog("failed to start timer"); return false; } @@ -65,28 +65,28 @@ void TimerSlot::OnStop() { void TimerSlot::OnTimerExpired(Timer &timer) { _callback(_refCon); - timer.Start(_interval); } // -// BadaTimerManager +// TizenTimerManager // -BadaTimerManager::BadaTimerManager() { +TizenTimerManager::TizenTimerManager() { } -BadaTimerManager::~BadaTimerManager() { - for (Common::List<TimerSlot>::iterator slot = _timers.begin(); - slot != _timers.end(); ) { - slot->Stop(); - slot = _timers.erase(slot); +TizenTimerManager::~TizenTimerManager() { + for (Common::List<TimerSlot *>::iterator it = _timers.begin(); it != _timers.end(); ) { + TimerSlot *slot = (*it); + slot->Quit(); + slot->Join(); + delete slot; + it = _timers.erase(it); } } -bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon, - const Common::String &id) { +bool TizenTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon, const Common::String &id) { TimerSlot *slot = new TimerSlot(proc, interval / 1000, refCon); - if (IsFailed(slot->Construct(THREAD_TYPE_EVENT_DRIVEN))) { + if (IsFailed(slot->Construct())) { AppLog("Failed to create timer thread"); delete slot; return false; @@ -98,16 +98,18 @@ bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *re return false; } - _timers.push_back(*slot); + _timers.push_back(slot); return true; } -void BadaTimerManager::removeTimerProc(TimerProc proc) { - for (Common::List<TimerSlot>::iterator slot = _timers.begin(); - slot != _timers.end(); ++slot) { +void TizenTimerManager::removeTimerProc(TimerProc proc) { + for (Common::List<TimerSlot *>::iterator it = _timers.begin(); it != _timers.end(); ++it) { + TimerSlot *slot = (*it); if (slot->_callback == proc) { - slot->Stop(); - slot = _timers.erase(slot); + slot->Quit(); + slot->Join(); + delete slot; + it = _timers.erase(it); } } } diff --git a/backends/timer/bada/timer.h b/backends/timer/tizen/timer.h index 826064d7ff..4b2596401a 100644 --- a/backends/timer/bada/timer.h +++ b/backends/timer/tizen/timer.h @@ -20,20 +20,18 @@ * */ -#ifndef BADA_TIMER_H -#define BADA_TIMER_H +#ifndef TIZEN_TIMER_H +#define TIZEN_TIMER_H #include <FBase.h> #include "common/timer.h" #include "common/list.h" -using namespace Osp::Base::Runtime; +using namespace Tizen::Base::Runtime; -struct TimerSlot: public ITimerEventListener, public Thread { - TimerSlot(Common::TimerManager::TimerProc callback, - uint32 interval, - void *refCon); +struct TimerSlot: public EventDrivenThread, public ITimerEventListener { + TimerSlot(Common::TimerManager::TimerProc callback, uint32 interval, void *refCon); ~TimerSlot(); bool OnStart(void); @@ -46,17 +44,16 @@ struct TimerSlot: public ITimerEventListener, public Thread { void *_refCon; }; -class BadaTimerManager : public Common::TimerManager { +class TizenTimerManager : public Common::TimerManager { public: - BadaTimerManager(); - ~BadaTimerManager(); + TizenTimerManager(); + ~TizenTimerManager(); - bool installTimerProc(TimerProc proc, int32 interval, void *refCon, - const Common::String &id); + bool installTimerProc(TimerProc proc, int32 interval, void *refCon, const Common::String &id); void removeTimerProc(TimerProc proc); private: - Common::List<TimerSlot> _timers; + Common::List<TimerSlot *> _timers; }; #endif diff --git a/backends/vkeybd/virtual-keyboard-gui.cpp b/backends/vkeybd/virtual-keyboard-gui.cpp index 75de86472f..ec4cbf1de2 100644 --- a/backends/vkeybd/virtual-keyboard-gui.cpp +++ b/backends/vkeybd/virtual-keyboard-gui.cpp @@ -32,11 +32,9 @@ namespace Common { -static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, OverlayColor transparent) { - if (surf_dst->format.bytesPerPixel != sizeof(OverlayColor) || surf_src->format.bytesPerPixel != sizeof(OverlayColor)) - return; - - const OverlayColor *src = (const OverlayColor *)surf_src->pixels; +template<typename ColorType> +static void blitImplementation(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, ColorType transparent) { + const ColorType *src = (const ColorType *)surf_src->getPixels(); int blitW = surf_src->w; int blitH = surf_src->h; @@ -58,13 +56,13 @@ static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 if (blitW <= 0 || blitH <= 0) return; - OverlayColor *dst = (OverlayColor *)surf_dst->getBasePtr(x, y); + ColorType *dst = (ColorType *)surf_dst->getBasePtr(x, y); int dstAdd = surf_dst->w - blitW; int srcAdd = surf_src->w - blitW; for (int i = 0; i < blitH; ++i) { for (int j = 0; j < blitW; ++j, ++dst, ++src) { - OverlayColor col = *src; + ColorType col = *src; if (col != transparent) *dst = col; } @@ -73,6 +71,16 @@ static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 } } +static void blit(Graphics::Surface *surf_dst, Graphics::Surface *surf_src, int16 x, int16 y, uint32 transparent) { + if (surf_dst->format.bytesPerPixel != surf_src->format.bytesPerPixel) + return; + + if (surf_dst->format.bytesPerPixel == 2) + blitImplementation<uint16>(surf_dst, surf_src, x, y, transparent); + else if (surf_dst->format.bytesPerPixel == 4) + blitImplementation<uint32>(surf_dst, surf_src, x, y, transparent); +} + VirtualKeyboardGUI::VirtualKeyboardGUI(VirtualKeyboard *kbd) : _kbd(kbd), _displaying(false), _drag(false), _drawCaret(false), _displayEnabled(false), _firstRun(true), @@ -111,7 +119,7 @@ void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) { } } -void VirtualKeyboardGUI::setupDisplayArea(Rect &r, OverlayColor forecolor) { +void VirtualKeyboardGUI::setupDisplayArea(Rect &r, uint32 forecolor) { _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); if (!fontIsSuitable(_dispFont, r)) { @@ -161,7 +169,7 @@ void VirtualKeyboardGUI::run() { _system->clearOverlay(); } _overlayBackup.create(_screenW, _screenH, _system->getOverlayFormat()); - _system->grabOverlay(_overlayBackup.pixels, _overlayBackup.pitch); + _system->grabOverlay(_overlayBackup.getPixels(), _overlayBackup.pitch); setupCursor(); @@ -171,7 +179,7 @@ void VirtualKeyboardGUI::run() { removeCursor(); - _system->copyRectToOverlay(_overlayBackup.pixels, _overlayBackup.pitch, 0, 0, _overlayBackup.w, _overlayBackup.h); + _system->copyRectToOverlay(_overlayBackup.getPixels(), _overlayBackup.pitch, 0, 0, _overlayBackup.w, _overlayBackup.h); if (!g_gui.isActive()) _system->hideOverlay(); _overlayBackup.free(); @@ -262,7 +270,7 @@ void VirtualKeyboardGUI::screenChanged() { _screenH = newScreenH; _overlayBackup.create(_screenW, _screenH, _system->getOverlayFormat()); - _system->grabOverlay(_overlayBackup.pixels, _overlayBackup.pitch); + _system->grabOverlay(_overlayBackup.getPixels(), _overlayBackup.pitch); if (!_kbd->checkModeResolutions()) { _displaying = false; @@ -356,13 +364,13 @@ void VirtualKeyboardGUI::redraw() { Graphics::Surface surf; surf.create(w, h, _system->getOverlayFormat()); - OverlayColor *dst = (OverlayColor *)surf.pixels; - const OverlayColor *src = (OverlayColor *) _overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top); + byte *dst = (byte *)surf.getPixels(); + const byte *src = (const byte *)_overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top); while (h--) { - memcpy(dst, src, surf.w * sizeof(OverlayColor)); - dst += surf.w; - src += _overlayBackup.w; + memcpy(dst, src, surf.pitch); + dst += surf.pitch; + src += _overlayBackup.pitch; } blit(&surf, _kbdSurface, _kbdBound.left - _dirtyRect.left, @@ -371,7 +379,7 @@ void VirtualKeyboardGUI::redraw() { blit(&surf, &_dispSurface, _dispX - _dirtyRect.left, _dispY - _dirtyRect.top, _dispBackColor); } - _system->copyRectToOverlay(surf.pixels, surf.pitch, + _system->copyRectToOverlay(surf.getPixels(), surf.pitch, _dirtyRect.left, _dirtyRect.top, surf.w, surf.h); surf.free(); diff --git a/backends/vkeybd/virtual-keyboard-gui.h b/backends/vkeybd/virtual-keyboard-gui.h index d0f9c884ed..a2000adea0 100644 --- a/backends/vkeybd/virtual-keyboard-gui.h +++ b/backends/vkeybd/virtual-keyboard-gui.h @@ -99,7 +99,7 @@ private: VirtualKeyboard *_kbd; Rect _kbdBound; Graphics::Surface *_kbdSurface; - OverlayColor _kbdTransparentColor; + uint32 _kbdTransparentColor; Point _dragPoint; bool _drag; @@ -113,7 +113,7 @@ private: const Graphics::Font *_dispFont; int16 _dispX, _dispY; uint _dispI; - OverlayColor _dispForeColor, _dispBackColor; + uint32 _dispForeColor, _dispBackColor; int _lastScreenChanged; int16 _screenW, _screenH; @@ -121,7 +121,7 @@ private: bool _displaying; bool _firstRun; - void setupDisplayArea(Rect &r, OverlayColor forecolor); + void setupDisplayArea(Rect &r, uint32 forecolor); void move(int16 x, int16 y); void moveToDefaultPosition(); void screenChanged(); diff --git a/backends/vkeybd/virtual-keyboard.h b/backends/vkeybd/virtual-keyboard.h index 4ab5ad446d..3b2b2196bd 100644 --- a/backends/vkeybd/virtual-keyboard.h +++ b/backends/vkeybd/virtual-keyboard.h @@ -112,11 +112,11 @@ protected: String resolution; String bitmapName; Graphics::Surface *image; - OverlayColor transparentColor; + uint32 transparentColor; ImageMap imageMap; VKEventMap events; Rect displayArea; - OverlayColor displayFontColor; + uint32 displayFontColor; Mode() : image(0) {} ~Mode() { |