diff options
Diffstat (limited to 'backends')
89 files changed, 8165 insertions, 6072 deletions
diff --git a/backends/audiocd/audiocd.h b/backends/audiocd/audiocd.h new file mode 100644 index 0000000000..70eabf650b --- /dev/null +++ b/backends/audiocd/audiocd.h @@ -0,0 +1,135 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_AUDIOCD_ABSTRACT_H +#define BACKENDS_AUDIOCD_ABSTRACT_H + +#include "common/noncopyable.h" + +/** +* Abstract Audio CD manager class. Subclasses implement the actual +* functionality. +*/ +class AudioCDManager : Common::NonCopyable { +public: + virtual ~AudioCDManager() {} + + /** + * A structure containing the current playback information + */ + struct Status { + bool playing; + int track; + int start; + int duration; + int numLoops; + }; + + /** + * @name Emulated playback functions + * Engines should call these functions. Not all platforms + * support cd playback, and these functions should try to + * emulate it. + */ + //@{ + + /** + * Start audio CD playback + * @param track the track to play. + * @param num_loops how often playback should be repeated (-1 = infinitely often). + * @param start_frame the frame at which playback should start (75 frames = 1 second). + * @param duration the number of frames to play. + * @param only_emulate determines if the track should be emulated only + */ + virtual void play(int track, int numLoops, int startFrame, int duration, bool only_emulate = false) = 0; + + /** + * Get if audio is being played. + * @return true if CD or emulated audio is playing + */ + virtual bool isPlaying() const = 0; + + /** + * Stop CD or emulated audio playback. + */ + virtual void stop() = 0; + + /** + * Update CD or emulated audio status. + */ + virtual void update() = 0; + + /** + * Get the playback status. + * @return a Status struct with playback data. + */ + virtual Status getStatus() const = 0; + + //@} + + + /** + * @name Real CD audio methods + * These functions should be called from the emulated + * ones if they can't emulate the audio playback. + */ + //@{ + + /** + * Initialise the specified CD drive for audio playback. + * @param drive the drive id + * @return true if the CD drive was inited succesfully + */ + virtual bool openCD(int drive) = 0; + + /** + * Poll CD status. + * @return true if CD audio is playing + */ + virtual bool pollCD() const = 0; + + /** + * Start CD audio playback. + * @param track the track to play. + * @param num_loops how often playback should be repeated (-1 = infinitely often). + * @param start_frame the frame at which playback should start (75 frames = 1 second). + * @param duration the number of frames to play. + */ + virtual void playCD(int track, int num_loops, int start_frame, int duration) = 0; + + /** + * Stop CD audio playback. + */ + virtual void stopCD() = 0; + + /** + * Update CD audio status. + */ + virtual void updateCD() = 0; + + //@} +}; + +#endif diff --git a/backends/audiocd/default/default-audiocd.cpp b/backends/audiocd/default/default-audiocd.cpp new file mode 100644 index 0000000000..0e7dc66ba1 --- /dev/null +++ b/backends/audiocd/default/default-audiocd.cpp @@ -0,0 +1,123 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/audiocd/default/default-audiocd.h" +#include "sound/audiostream.h" +#include "common/system.h" + +DefaultAudioCDManager::DefaultAudioCDManager() { + _cd.playing = false; + _cd.track = 0; + _cd.start = 0; + _cd.duration = 0; + _cd.numLoops = 0; + _mixer = g_system->getMixer(); + _emulating = false; + assert(_mixer); +} + +void DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool only_emulate) { + if (numLoops != 0 || startFrame != 0) { + _cd.track = track; + _cd.numLoops = numLoops; + _cd.start = startFrame; + _cd.duration = duration; + + // Try to load the track from a compressed data file, and if found, use + // that. If not found, attempt to start regular Audio CD playback of + // the requested track. + char trackName[2][16]; + sprintf(trackName[0], "track%d", track); + sprintf(trackName[1], "track%02d", track); + Audio::SeekableAudioStream *stream = 0; + + for (int i = 0; !stream && i < 2; ++i) + stream = Audio::SeekableAudioStream::openStreamFile(trackName[i]); + + // Stop any currently playing emulated track + _mixer->stopHandle(_handle); + + if (stream != 0) { + Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75); + Audio::Timestamp end = duration ? Audio::Timestamp(0, startFrame + duration, 75) : stream->getLength(); + + /* + FIXME: Seems numLoops == 0 and numLoops == 1 both indicate a single repetition, + while all other positive numbers indicate precisely the number of desired + repetitions. Finally, -1 means infinitely many + */ + _emulating = true; + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle, + Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops)); + } else { + _emulating = false; + if (!only_emulate) + playCD(track, numLoops, startFrame, duration); + } + } +} + +void DefaultAudioCDManager::stop() { + if (_emulating) { + // Audio CD emulation + _mixer->stopHandle(_handle); + _emulating = false; + } else { + // Real Audio CD + stopCD(); + } +} + +bool DefaultAudioCDManager::isPlaying() const { + if (_emulating) { + // Audio CD emulation + return _mixer->isSoundHandleActive(_handle); + } else { + // Real Audio CD + return pollCD(); + } +} + +void DefaultAudioCDManager::update() { + if (_emulating) { + // Check whether the audio track stopped playback + if (!_mixer->isSoundHandleActive(_handle)) { + // FIXME: We do not update the numLoops parameter here (and in fact, + // currently can't do that). Luckily, only one engine ever checks + // this part of the AudioCD status, namely the SCUMM engine; and it + // only checks whether the track is currently set to infinite looping + // or not. + _emulating = false; + } + } else { + updateCD(); + } +} + +DefaultAudioCDManager::Status DefaultAudioCDManager::getStatus() const { + Status info = _cd; + info.playing = isPlaying(); + return info; +} diff --git a/backends/audiocd/default/default-audiocd.h b/backends/audiocd/default/default-audiocd.h new file mode 100644 index 0000000000..ec209d9eb5 --- /dev/null +++ b/backends/audiocd/default/default-audiocd.h @@ -0,0 +1,60 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_AUDIOCD_DEFAULT_H +#define BACKENDS_AUDIOCD_DEFAULT_H + +#include "backends/audiocd/audiocd.h" +#include "sound/mixer.h" + +/** + * The default audio cd manager. Implements emulation of audio cd playback. + */ +class DefaultAudioCDManager : public AudioCDManager { +public: + DefaultAudioCDManager(); + virtual ~DefaultAudioCDManager() {} + + void play(int track, int numLoops, int startFrame, int duration, bool only_emulate = false); + void stop(); + bool isPlaying() const; + void update(); + virtual Status getStatus() const; // Subclasses should override for better status results + + virtual bool openCD(int drive) { return false; } + virtual void updateCD() {} + virtual bool pollCD() const { return false; } + virtual void playCD(int track, int num_loops, int start_frame, int duration) {} + virtual void stopCD() {} + +protected: + Audio::SoundHandle _handle; + bool _emulating; + + Status _cd; + Audio::Mixer *_mixer; +}; + +#endif diff --git a/backends/audiocd/sdl/sdl-audiocd.cpp b/backends/audiocd/sdl/sdl-audiocd.cpp new file mode 100644 index 0000000000..d032df7eac --- /dev/null +++ b/backends/audiocd/sdl/sdl-audiocd.cpp @@ -0,0 +1,136 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(WIN32) || defined(UNIX) || defined(MACOSX) + +#include "backends/audiocd/sdl/sdl-audiocd.h" + +SdlAudioCDManager::SdlAudioCDManager() + : + _cdrom(0), + _cdTrack(0), + _cdNumLoops(0), + _cdStartFrame(0), + _cdDuration(0), + _cdEndTime(0), + _cdStopTime(0) { + +} + +SdlAudioCDManager::~SdlAudioCDManager() { + if (_cdrom) { + SDL_CDStop(_cdrom); + SDL_CDClose(_cdrom); + } +} + +bool SdlAudioCDManager::openCD(int drive) { + if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1) + _cdrom = NULL; + else { + _cdrom = SDL_CDOpen(drive); + // Did it open? Check if _cdrom is NULL + if (!_cdrom) { + warning("Couldn't open drive: %s", SDL_GetError()); + } else { + _cdNumLoops = 0; + _cdStopTime = 0; + _cdEndTime = 0; + } + } + + return (_cdrom != NULL); +} + +void SdlAudioCDManager::stopCD() { + // Stop CD Audio in 1/10th of a second + _cdStopTime = SDL_GetTicks() + 100; + _cdNumLoops = 0; +} + +void SdlAudioCDManager::playCD(int track, int num_loops, int start_frame, int duration) { + if (!num_loops && !start_frame) + return; + + if (!_cdrom) + return; + + if (duration > 0) + duration += 5; + + _cdTrack = track; + _cdNumLoops = num_loops; + _cdStartFrame = start_frame; + + SDL_CDStatus(_cdrom); + if (start_frame == 0 && duration == 0) + SDL_CDPlayTracks(_cdrom, track, 0, 1, 0); + else + SDL_CDPlayTracks(_cdrom, track, start_frame, 0, duration); + _cdDuration = duration; + _cdStopTime = 0; + _cdEndTime = SDL_GetTicks() + _cdrom->track[track].length * 1000 / CD_FPS; +} + +bool SdlAudioCDManager::pollCD() const { + if (!_cdrom) + return false; + + return (_cdNumLoops != 0 && (SDL_GetTicks() < _cdEndTime || SDL_CDStatus(_cdrom) == CD_PLAYING)); +} + +void SdlAudioCDManager::updateCD() { + if (!_cdrom) + return; + + if (_cdStopTime != 0 && SDL_GetTicks() >= _cdStopTime) { + SDL_CDStop(_cdrom); + _cdNumLoops = 0; + _cdStopTime = 0; + return; + } + + if (_cdNumLoops == 0 || SDL_GetTicks() < _cdEndTime) + return; + + if (_cdNumLoops != 1 && SDL_CDStatus(_cdrom) != CD_STOPPED) { + // Wait another second for it to be done + _cdEndTime += 1000; + return; + } + + if (_cdNumLoops > 0) + _cdNumLoops--; + + if (_cdNumLoops != 0) { + if (_cdStartFrame == 0 && _cdDuration == 0) + SDL_CDPlayTracks(_cdrom, _cdTrack, 0, 1, 0); + else + SDL_CDPlayTracks(_cdrom, _cdTrack, _cdStartFrame, 0, _cdDuration); + _cdEndTime = SDL_GetTicks() + _cdrom->track[_cdTrack].length * 1000 / CD_FPS; + } +} + +#endif diff --git a/backends/audiocd/sdl/sdl-audiocd.h b/backends/audiocd/sdl/sdl-audiocd.h new file mode 100644 index 0000000000..42ac980c51 --- /dev/null +++ b/backends/audiocd/sdl/sdl-audiocd.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_AUDIOCD_SDL_H +#define BACKENDS_AUDIOCD_SDL_H + +#include "backends/audiocd/default/default-audiocd.h" + +#if defined(__SYMBIAN32__) +#include <esdl\SDL.h> +#else +#include <SDL.h> +#endif + +/** + * The SDL audio cd manager. Implements real audio cd playback. + */ +class SdlAudioCDManager : public DefaultAudioCDManager { +public: + SdlAudioCDManager(); + virtual ~SdlAudioCDManager(); + +protected: + virtual bool openCD(int drive); + virtual void updateCD(); + virtual bool pollCD() const; + virtual void playCD(int track, int num_loops, int start_frame, int duration); + virtual void stopCD(); + + SDL_CD *_cdrom; + int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration; + uint32 _cdEndTime, _cdStopTime; +}; + +#endif diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp index c06695a727..aa08e94c32 100644 --- a/backends/base-backend.cpp +++ b/backends/base-backend.cpp @@ -84,3 +84,17 @@ Common::WriteStream *BaseBackend::createConfigWriteStream() { return file.createWriteStream(); #endif } + +static DefaultAudioCDManager *s_audiocdManager = 0; + +AudioCDManager *BaseBackend::getAudioCDManager() { + if (!s_audiocdManager) + s_audiocdManager = new DefaultAudioCDManager(); + return (AudioCDManager *)s_audiocdManager; +} + +void BaseBackend::resetGraphicsScale() { + // As a hack, we use 0 here. Backends should override this method + // and provide their own. + setGraphicsMode(0); +} diff --git a/backends/base-backend.h b/backends/base-backend.h index 3fcca9c3b7..bcacde9aad 100644 --- a/backends/base-backend.h +++ b/backends/base-backend.h @@ -28,6 +28,7 @@ #include "common/system.h" #include "backends/events/default/default-events.h" +#include "backends/audiocd/default/default-audiocd.h" class BaseBackend : public OSystem, Common::EventSource { public: @@ -37,6 +38,10 @@ public: virtual Common::SeekableReadStream *createConfigReadStream(); virtual Common::WriteStream *createConfigWriteStream(); + + virtual AudioCDManager *getAudioCDManager(); + + virtual void resetGraphicsScale(); }; diff --git a/backends/events/gp2xsdl/gp2xsdl-events.cpp b/backends/events/gp2xsdl/gp2xsdl-events.cpp new file mode 100644 index 0000000000..2be3f2b2e7 --- /dev/null +++ b/backends/events/gp2xsdl/gp2xsdl-events.cpp @@ -0,0 +1,373 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(GP2X) || defined(GP2XWIZ) + +#include "backends/events/gp2xsdl/gp2xsdl-events.h" +#if defined(GP2X) +#include "backends/platform/gp2x/gp2x-hw.h" +#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" +#else +#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" +#endif + +#include "backends/platform/sdl/sdl.h" + +// FIXME move joystick defines out and replace with confile file options +// we should really allow users to map any key to a joystick button using the keymapper. +#define JOY_DEADZONE 2200 + +#define JOY_XAXIS 0 +#define JOY_YAXIS 1 + +/* GP2X: Main Joystick Mappings */ +enum { + GP2X_BUTTON_UP = 0, + GP2X_BUTTON_UPLEFT = 1, + GP2X_BUTTON_LEFT = 2, + GP2X_BUTTON_DOWNLEFT = 3, + GP2X_BUTTON_DOWN = 4, + GP2X_BUTTON_DOWNRIGHT = 5, + GP2X_BUTTON_RIGHT = 6, + GP2X_BUTTON_UPRIGHT = 7, + GP2X_BUTTON_MENU = 8, + GP2X_BUTTON_SELECT = 9, + GP2X_BUTTON_L = 10, + GP2X_BUTTON_R = 11, + GP2X_BUTTON_A = 12, + GP2X_BUTTON_B = 13, + GP2X_BUTTON_X = 14, + GP2X_BUTTON_Y = 15, + GP2X_BUTTON_VOLUP = 16, + GP2X_BUTTON_VOLDOWN = 17, + GP2X_BUTTON_CLICK = 18 +}; + +GP2XSdlEventManager::GP2XSdlEventManager(Common::EventSource *boss) + : + _buttonStateL(false), + SdlEventManager(boss) { + +} + +void GP2XSdlEventManager::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { + event.kbd.flags = 0; + + if (mod & KMOD_SHIFT) + event.kbd.flags |= Common::KBD_SHIFT; + if (mod & KMOD_ALT) + event.kbd.flags |= Common::KBD_ALT; + if (mod & KMOD_CTRL) + event.kbd.flags |= Common::KBD_CTRL; +} + +void GP2XSdlEventManager::moveStick() { + bool stickBtn[32]; + + memcpy(stickBtn, _stickBtn, sizeof(stickBtn)); + + if ((stickBtn[0])||(stickBtn[2])||(stickBtn[4])||(stickBtn[6])) + stickBtn[1] = stickBtn[3] = stickBtn[5] = stickBtn[7] = 0; + + if ((stickBtn[1])||(stickBtn[2])||(stickBtn[3])) { + if (_km.x_down_count!=2) { + _km.x_vel = -1; + _km.x_down_count = 1; + } else + _km.x_vel = -4; + } else if ((stickBtn[5])||(stickBtn[6])||(stickBtn[7])) { + if (_km.x_down_count!=2) { + _km.x_vel = 1; + _km.x_down_count = 1; + } else + _km.x_vel = 4; + } else { + _km.x_vel = 0; + _km.x_down_count = 0; + } + + if ((stickBtn[0])||(stickBtn[1])||(stickBtn[7])) { + if (_km.y_down_count!=2) { + _km.y_vel = -1; + _km.y_down_count = 1; + } else + _km.y_vel = -4; + } else if ((stickBtn[3])||(stickBtn[4])||(stickBtn[5])) { + if (_km.y_down_count!=2) { + _km.y_vel = 1; + _km.y_down_count = 1; + } else + _km.y_vel = 4; + } else { + _km.y_vel = 0; + _km.y_down_count = 0; + } +} + +/* GP2X Input mappings. +Single Button + +Movement: + +GP2X_BUTTON_UP Cursor Up +GP2X_BUTTON_DOWN Cursor Down +GP2X_BUTTON_LEFT Cursor Left +GP2X_BUTTON_RIGHT Cursor Right + +GP2X_BUTTON_UPLEFT Cursor Up Left +GP2X_BUTTON_UPRIGHT Cursor Up Right +GP2X_BUTTON_DOWNLEFT Cursor Down Left +GP2X_BUTTON_DOWNRIGHT Cursor Down Right + +Button Emulation: + +GP2X_BUTTON_CLICK Left Mouse Click (GP2X only) +GP2X_BUTTON_A . (Period) +GP2X_BUTTON_B Left Mouse Click +GP2X_BUTTON_Y Space Bar +GP2X_BUTTON_X Right Mouse Click +GP2X_BUTTON_L Combo Modifier (Left Trigger) +GP2X_BUTTON_R Return (Right Trigger) +GP2X_BUTTON_MENU F5 (Game Menu) +GP2X_BUTTON_SELECT Escape +GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up +GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down + +Combos: + +GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) or Virtual Keyboard if enabled +GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) +GP2X_BUTTON_L & GP2X_BUTTON_MENU Common::EVENT_MAINMENU (ScummVM Global Main Menu) +GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) +GP2X_BUTTON_L & GP2X_BUTTON_Y Toggles setZoomOnMouse() for larger then 320*240 games to scale to the point + raduis. (GP2X only) +*/ + +bool GP2XSdlEventManager::handleKeyDown(SDL_Event &ev, Common::Event &event) { + SDLModToOSystemKeyFlags(SDL_GetModState(), event); + + if (remapKey(ev, event)) + return true; + + event.type = Common::EVENT_KEYDOWN; + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; + event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); + + return true; +} + +bool GP2XSdlEventManager::handleKeyUp(SDL_Event &ev, Common::Event &event) { + if (remapKey(ev, event)) + return true; + + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; + event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); + SDLModToOSystemKeyFlags(SDL_GetModState(), event); + + // Ctrl-Alt-<key> will change the GFX mode + if ((event.kbd.flags & (Common::KBD_CTRL | Common::KBD_ALT)) == (Common::KBD_CTRL | Common::KBD_ALT)) { + // Swallow these key up events + return false; + } + + return true; +} + +bool GP2XSdlEventManager::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { + _stickBtn[ev.jbutton.button] = 1; + if (ev.jbutton.button == GP2X_BUTTON_B) { + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); +#ifdef GP2X + } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); +#endif + } else if (ev.jbutton.button == GP2X_BUTTON_X) { + event.type = Common::EVENT_RBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + } else if (_stickBtn[GP2X_BUTTON_L] && (ev.jbutton.button == GP2X_BUTTON_SELECT)) { + event.type = Common::EVENT_QUIT; + } else if (ev.jbutton.button < 8) { + moveStick(); + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + } else { + event.type = Common::EVENT_KEYDOWN; + event.kbd.flags = 0; + switch (ev.jbutton.button) { + case GP2X_BUTTON_L: + _buttonStateL = true; + break; + case GP2X_BUTTON_R: + if (_buttonStateL) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } + break; + case GP2X_BUTTON_SELECT: + if (_buttonStateL) { + event.type = Common::EVENT_QUIT; + } else { + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); + } + break; + case GP2X_BUTTON_A: + if (_buttonStateL) { + event.type = Common::EVENT_PREDICTIVE_DIALOG; + } else { + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + } + break; + case GP2X_BUTTON_Y: +#ifdef GP2X + if (_buttonStateL) { + ((GP2XSdlGraphicsManager *)((OSystem_SDL *)g_system)->getGraphicsManager())->toggleZoomOnMouse(); + } else { +#endif + event.kbd.keycode = Common::KEYCODE_SPACE; + event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); +#ifdef GP2X + } +#endif + break; + case GP2X_BUTTON_MENU: + if (_buttonStateL) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } + break; + case GP2X_BUTTON_VOLUP: +#ifdef GP2X + GP2X_HW::mixerMoveVolume(2); + if (GP2X_HW::volumeLevel == 100) { +#else + WIZ_HW::mixerMoveVolume(2); + if (WIZ_HW::volumeLevel == 100) { +#endif + g_system->displayMessageOnOSD("Maximum Volume"); + } else { + g_system->displayMessageOnOSD("Increasing Volume"); + } + break; + + case GP2X_BUTTON_VOLDOWN: +#ifdef GP2X + GP2X_HW::mixerMoveVolume(1); + if (GP2X_HW::volumeLevel == 0) { +#else + WIZ_HW::mixerMoveVolume(1); + if (WIZ_HW::volumeLevel == 0) { +#endif + g_system->displayMessageOnOSD("Minimal Volume"); + } else { + g_system->displayMessageOnOSD("Decreasing Volume"); + } + break; + } + } + return true; +} + +bool GP2XSdlEventManager::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { + _stickBtn[ev.jbutton.button] = 0; + if (ev.jbutton.button == GP2X_BUTTON_B) { + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); +#ifdef GP2X + } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); +#endif + } else if (ev.jbutton.button == GP2X_BUTTON_X) { + event.type = Common::EVENT_RBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + } else if (ev.jbutton.button < 8) { + moveStick(); + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + } else { + event.type = Common::EVENT_KEYUP; + event.kbd.flags = 0; + switch (ev.jbutton.button) { + case GP2X_BUTTON_SELECT: + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); + break; + case GP2X_BUTTON_A: + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + break; + case GP2X_BUTTON_Y: + event.kbd.keycode = Common::KEYCODE_SPACE; + event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); + break; + case GP2X_BUTTON_MENU: + if (_buttonStateL == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } + break; + case GP2X_BUTTON_L: + _buttonStateL = false; + break; + case GP2X_BUTTON_R: + if (_buttonStateL == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } + break; + case GP2X_BUTTON_VOLUP: + break; + case GP2X_BUTTON_VOLDOWN: + break; + } + } + return true; +} + +#endif diff --git a/backends/events/gp2xsdl/gp2xsdl-events.h b/backends/events/gp2xsdl/gp2xsdl-events.h new file mode 100644 index 0000000000..559aa53388 --- /dev/null +++ b/backends/events/gp2xsdl/gp2xsdl-events.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(BACKEND_EVENTS_SDL_GP2X_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_SDL_GP2X_H + +#include "backends/events/sdl/sdl-events.h" + +/** + * SDL events manager for GP2X and GP2XWIZ + */ +class GP2XSdlEventManager : public SdlEventManager { +public: + GP2XSdlEventManager(Common::EventSource *boss); + +protected: + bool _stickBtn[32]; + + /** Button state for L button modifier */ + bool _buttonStateL; + + /** + * Handles the stick movement + */ + void moveStick(); + + virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event); + virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); + + virtual void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event); +}; + +#endif diff --git a/backends/platform/linuxmoto/linuxmoto-events.cpp b/backends/events/linuxmotosdl/linuxmotosdl-events.cpp index 379e34b7ac..1313007158 100644 --- a/backends/platform/linuxmoto/linuxmoto-events.cpp +++ b/backends/events/linuxmotosdl/linuxmotosdl-events.cpp @@ -23,49 +23,46 @@ * */ +#if defined(LINUXMOTO) + +#include "backends/events/linuxmotosdl/linuxmotosdl-events.h" #include "backends/platform/linuxmoto/linuxmoto-sdl.h" -#include "graphics/scaler/aspect.h" // for aspect2Real - -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { - if (key >= SDLK_F1 && key <= SDLK_F9) { - return key - SDLK_F1 + Common::ASCII_F1; - } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { - return key - SDLK_KP0 + '0'; - } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { - return key; - } else if (unicode) { - return unicode; - } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { - return key & ~0x20; - } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { - return 0; - } - return key; -} -void OSystem_LINUXMOTO::fillMouseEvent(Common::Event &event, int x, int y) { - if (_videoMode.mode == GFX_HALF && !_overlayVisible) { - event.mouse.x = x*2; - event.mouse.y = y*2; - } else { - event.mouse.x = x; - event.mouse.y = y; - } +enum { + GFX_HALF = 12 +}; - // Update the "keyboard mouse" coords - _km.x = x; - _km.y = y; +LinuxmotoSdlEventManager::LinuxmotoSdlEventManager(Common::EventSource *boss) + : + SdlEventManager(boss) { - // Adjust for the screen scaling - if (!_overlayVisible) { - event.mouse.x /= _videoMode.scaleFactor; - event.mouse.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - event.mouse.y = aspect2Real(event.mouse.y); +} + +void LinuxmotoSdlEventManager::preprocessEvents(SDL_Event *event) { + if (event->type == SDL_ACTIVEEVENT) { + if (event->active.state == SDL_APPINPUTFOCUS && !event->active.gain) { + ((OSystem_SDL* )g_system)->getMixerManager()->suspendAudio(); + for (;;) { + if (!SDL_WaitEvent(event)) { + SDL_Delay(10); + continue; + } + if (event->type == SDL_QUIT) + return; + if (event->type != SDL_ACTIVEEVENT) + continue; + if (event->active.state == SDL_APPINPUTFOCUS && event->active.gain) { + ((OSystem_SDL* )g_system)->getMixerManager()->resumeAudio(); + return; + } + } + } } } -bool OSystem_LINUXMOTO::remapKey(SDL_Event &ev, Common::Event &event) { +bool LinuxmotoSdlEventManager::remapKey(SDL_Event &ev, Common::Event &event) { + if (false) {} + // Motorol A1200/E6/A1600 remapkey by Lubomyr #ifdef MOTOEZX // Quit on MOD+Camera Key on A1200 @@ -226,3 +223,5 @@ bool OSystem_LINUXMOTO::remapKey(SDL_Event &ev, Common::Event &event) { return false; } + +#endif diff --git a/backends/events/linuxmotosdl/linuxmotosdl-events.h b/backends/events/linuxmotosdl/linuxmotosdl-events.h new file mode 100644 index 0000000000..414db080ed --- /dev/null +++ b/backends/events/linuxmotosdl/linuxmotosdl-events.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(BACKEND_EVENTS_SDL_LINUXMOTO_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_SDL_LINUXMOTO_H + +#include "backends/events/sdl/sdl-events.h" + +/** + * SDL events manager for LINUXMOTO + */ +class LinuxmotoSdlEventManager : public SdlEventManager { +public: + LinuxmotoSdlEventManager(Common::EventSource *boss); + +protected: + virtual void preprocessEvents(SDL_Event *event); + virtual bool remapKey(SDL_Event &ev, Common::Event &event); +}; + +#endif diff --git a/backends/platform/samsungtv/events.cpp b/backends/events/samsungtvsdl/samsungtvsdl-events.cpp index af39e67fe5..d1c35d3a5a 100644 --- a/backends/platform/samsungtv/events.cpp +++ b/backends/events/samsungtvsdl/samsungtvsdl-events.cpp @@ -23,13 +23,17 @@ * */ -#include "backends/platform/samsungtv/samsungtv.h" -#include "common/util.h" -#include "common/events.h" +#ifdef SAMSUNGTV -#if defined(SAMSUNGTV) +#include "backends/events/samsungtvsdl/samsungtvsdl-events.h" -bool OSystem_SDL_SamsungTV::remapKey(SDL_Event &ev, Common::Event &event) { +SamsungTVSdlEventManager::SamsungTVSdlEventManager(Common::EventSource *boss) + : + SdlEventManager(boss) { + +} + +bool SamsungTVSdlEventManager::remapKey(SDL_Event &ev, Common::Event &event) { switch (ev.type) { case SDL_KEYDOWN:{ if (ev.key.keysym.sym == SDLK_POWER) { @@ -67,7 +71,8 @@ bool OSystem_SDL_SamsungTV::remapKey(SDL_Event &ev, Common::Event &event) { } } - return false; + // Invoke parent implementation of this method + return SdlEventManager::remapKey(ev, event); } #endif diff --git a/backends/events/samsungtvsdl/samsungtvsdl-events.h b/backends/events/samsungtvsdl/samsungtvsdl-events.h new file mode 100644 index 0000000000..10e1eb84bb --- /dev/null +++ b/backends/events/samsungtvsdl/samsungtvsdl-events.h @@ -0,0 +1,42 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(BACKEND_EVENTS_SDL_SAMSUNGTV_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_SDL_SAMSUNGTV_H + +#include "backends/events/sdl/sdl-events.h" + +/** + * SDL events manager for Samsung TV + */ +class SamsungTVSdlEventManager : public SdlEventManager { +public: + SamsungTVSdlEventManager(Common::EventSource *boss); + +protected: + virtual bool remapKey(SDL_Event &ev, Common::Event &event); +}; + +#endif diff --git a/backends/platform/sdl/events.cpp b/backends/events/sdl/sdl-events.cpp index 1c1d82730f..66685e1886 100644 --- a/backends/platform/sdl/events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -23,10 +23,11 @@ * */ +#if defined(WIN32) || defined(UNIX) || defined(MACOSX) + +#include "backends/events/sdl/sdl-events.h" #include "backends/platform/sdl/sdl.h" -#include "common/util.h" -#include "common/events.h" -#include "graphics/scaler/aspect.h" // for aspect2Real +#include "common/config-manager.h" // FIXME move joystick defines out and replace with confile file options // we should really allow users to map any key to a joystick button @@ -47,10 +48,37 @@ #define JOY_BUT_SPACE 4 #define JOY_BUT_F5 5 +SdlEventManager::SdlEventManager(Common::EventSource *boss) + : + _scrollLock(false), + _joystick(0), + _lastScreenID(0), + DefaultEventManager(boss) { + + // Reset mouse state + memset(&_km, 0, sizeof(_km)); + + int joystick_num = ConfMan.getInt("joystick_num"); + if (joystick_num > -1) { + // Initialize SDL joystick subsystem + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + // Enable joystick + if (SDL_NumJoysticks() > 0) { + printf("Using joystick: %s\n", SDL_JoystickName(0)); + _joystick = SDL_JoystickOpen(joystick_num); + } + } +} +SdlEventManager::~SdlEventManager() { + if (_joystick) + SDL_JoystickClose(_joystick); +} -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { +int SdlEventManager::mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { if (key >= SDLK_F1 && key <= SDLK_F9) { return key - SDLK_F1 + Common::ASCII_F1; } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { @@ -67,25 +95,17 @@ static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { return key; } -void OSystem_SDL::fillMouseEvent(Common::Event &event, int x, int y) { +void SdlEventManager::fillMouseEvent(Common::Event &event, int x, int y) { event.mouse.x = x; event.mouse.y = y; // Update the "keyboard mouse" coords _km.x = x; _km.y = y; - - // Adjust for the screen scaling - if (!_overlayVisible) { - event.mouse.x /= _videoMode.scaleFactor; - event.mouse.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - event.mouse.y = aspect2Real(event.mouse.y); - } } -void OSystem_SDL::handleKbdMouse() { - uint32 curTime = getMillis(); +void SdlEventManager::handleKbdMouse() { + uint32 curTime = g_system->getMillis(); if (curTime >= _km.last_time + _km.delay_time) { _km.last_time = curTime; if (_km.x_down_count == 1) { @@ -153,7 +173,7 @@ void OSystem_SDL::handleKbdMouse() { } } -static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { +void SdlEventManager::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { event.kbd.flags = 0; @@ -178,19 +198,19 @@ static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { event.kbd.flags |= Common::KBD_CAPS; } -bool OSystem_SDL::pollEvent(Common::Event &event) { - SDL_Event ev; - ev.type = SDL_NOEVENT; - +bool SdlEventManager::pollSdlEvent(Common::Event &event) { handleKbdMouse(); - // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED - if (_modeChanged) { - _modeChanged = false; + // 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; } + SDL_Event ev; + ev.type = SDL_NOEVENT; while (SDL_PollEvent(&ev)) { preprocessEvents(&ev); if (dispatchSDLEvent(ev, event)) @@ -199,7 +219,7 @@ bool OSystem_SDL::pollEvent(Common::Event &event) { return false; } -bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { switch (ev.type) { case SDL_KEYDOWN: return handleKeyDown(ev, event); @@ -219,8 +239,16 @@ bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { return handleJoyAxisMotion(ev, event); case SDL_VIDEOEXPOSE: - _forceFull = true; - break; + // HACK: Send a fake event, handled by SdlGraphicsManager + event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose; + return true; + + case SDL_VIDEORESIZE: + // HACK: Send a fake event, handled by OpenGLSdlGraphicsManager + event.type = (Common::EventType)OSystem_SDL::kSdlEventResize; + event.mouse.x = ev.resize.w; + event.mouse.y = ev.resize.h; + return true; case SDL_QUIT: event.type = Common::EVENT_QUIT; @@ -232,7 +260,7 @@ bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { } -bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleKeyDown(SDL_Event &ev, Common::Event &event) { SDLModToOSystemKeyFlags(SDL_GetModState(), event); @@ -243,41 +271,6 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) { if (_scrollLock) event.kbd.flags |= Common::KBD_SCRL; - // Alt-Return and Alt-Enter toggle full screen mode - if (event.kbd.hasFlags(Common::KBD_ALT) && (ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_KP_ENTER)) { - beginGFXTransaction(); - setFullscreenMode(!_videoMode.fullscreen); - endGFXTransaction(); -#ifdef USE_OSD - if (_videoMode.fullscreen) - displayMessageOnOSD("Fullscreen mode"); - else - displayMessageOnOSD("Windowed mode"); -#endif - - return false; - } - - // Alt-S: Create a screenshot - if (event.kbd.hasFlags(Common::KBD_ALT) && ev.key.keysym.sym == 's') { - char filename[20]; - - for (int n = 0;; n++) { - SDL_RWops *file; - - sprintf(filename, "scummvm%05d.bmp", n); - file = SDL_RWFromFile(filename, "r"); - if (!file) - break; - SDL_RWclose(file); - } - if (saveScreenshot(filename)) - printf("Saved '%s'\n", filename); - else - printf("Could not save screenshot!\n"); - return false; - } - // Ctrl-m toggles mouse capture if (event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'm') { toggleMouseGrab(); @@ -309,12 +302,6 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) { return true; } - // Ctrl-Alt-<key> will change the GFX mode - if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { - if (handleScalerHotkeys(ev.key)) - return false; - } - if (remapKey(ev, event)) return true; @@ -325,7 +312,7 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_SDL::handleKeyUp(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleKeyUp(SDL_Event &ev, Common::Event &event) { if (remapKey(ev, event)) return true; @@ -340,22 +327,17 @@ bool OSystem_SDL::handleKeyUp(SDL_Event &ev, Common::Event &event) { if (_scrollLock) event.kbd.flags |= Common::KBD_SCRL; - if (isScalerHotkey(event)) - // Swallow these key up events - return false; - return true; } -bool OSystem_SDL::handleMouseMotion(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleMouseMotion(SDL_Event &ev, Common::Event &event) { event.type = Common::EVENT_MOUSEMOVE; fillMouseEvent(event, ev.motion.x, ev.motion.y); - setMousePos(event.mouse.x, event.mouse.y); return true; } -bool OSystem_SDL::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.button.button == SDL_BUTTON_LEFT) event.type = Common::EVENT_LBUTTONDOWN; else if (ev.button.button == SDL_BUTTON_RIGHT) @@ -378,7 +360,7 @@ bool OSystem_SDL::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_SDL::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.button.button == SDL_BUTTON_LEFT) event.type = Common::EVENT_LBUTTONUP; else if (ev.button.button == SDL_BUTTON_RIGHT) @@ -394,7 +376,7 @@ bool OSystem_SDL::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_SDL::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONDOWN; fillMouseEvent(event, _km.x, _km.y); @@ -425,7 +407,7 @@ bool OSystem_SDL::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_SDL::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONUP; fillMouseEvent(event, _km.x, _km.y); @@ -456,7 +438,7 @@ bool OSystem_SDL::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_SDL::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { int axis = ev.jaxis.value; if ( axis > JOY_DEADZONE) { axis -= JOY_DEADZONE; @@ -469,7 +451,7 @@ bool OSystem_SDL::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { if ( ev.jaxis.axis == JOY_XAXIS) { #ifdef JOY_ANALOG - _km.x_vel = axis/2000; + _km.x_vel = axis / 2000; _km.x_down_count = 0; #else if (axis != 0) { @@ -504,7 +486,7 @@ bool OSystem_SDL::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { return true; } -bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) { +bool SdlEventManager::remapKey(SDL_Event &ev, Common::Event &event) { #ifdef LINUPY // On Yopy map the End button to quit if ((ev.key.keysym.sym == 293)) { @@ -571,3 +553,19 @@ bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) { #endif return false; } + +void SdlEventManager::toggleMouseGrab() { + if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) + SDL_WM_GrabInput(SDL_GRAB_ON); + else + SDL_WM_GrabInput(SDL_GRAB_OFF); +} + +void SdlEventManager::resetKeyboadEmulation(int16 x_max, int16 y_max) { + _km.x_max = x_max; + _km.y_max = y_max; + _km.delay_time = 25; + _km.last_time = 0; +} + +#endif diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h new file mode 100644 index 0000000000..4bc2277fcd --- /dev/null +++ b/backends/events/sdl/sdl-events.h @@ -0,0 +1,138 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(BACKEND_EVENTS_SDL_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_SDL_H + +#include "backends/events/default/default-events.h" + +#if defined(__SYMBIAN32__) +#include <esdl\SDL.h> +#else +#include <SDL.h> +#endif + +/** + * The SDL event manager class. + */ +class SdlEventManager : public DefaultEventManager { +public: + SdlEventManager(Common::EventSource *boss); + virtual ~SdlEventManager(); + + /** + * Gets and proccess SDL events + */ + virtual bool pollSdlEvent(Common::Event &event); + + /** + * Resets keyboard emulation after a video screen change + */ + virtual void resetKeyboadEmulation(int16 x_max, int16 y_max); + + /** + * Toggles mouse input grab + */ + virtual void toggleMouseGrab(); + +protected: + /** @name Keyboard mouse emulation + * Disabled by fingolfin 2004-12-18. + * I am keeping the rest of the code in for now, since the joystick + * code (or rather, "hack") uses it, too. + */ + //@{ + + struct KbdMouse { + int16 x, y, x_vel, y_vel, x_max, y_max, x_down_count, y_down_count; + uint32 last_time, delay_time, x_down_time, y_down_time; + }; + KbdMouse _km; + + //@} + + /** Scroll lock state - since SDL doesn't track it */ + bool _scrollLock; + + /** Joystick */ + SDL_Joystick *_joystick; + + /** Last screen id for checking if it was modified */ + int _lastScreenID; + + /** + * Pre process an event before it is dispatched. + */ + virtual void preprocessEvents(SDL_Event *event) {} + + /** + * Dispatchs SDL events for each handler. + */ + virtual bool dispatchSDLEvent(SDL_Event &ev, Common::Event &event); + + + /** @name Event Handlers + * Handlers for specific SDL events, called by SdlEventManager::dispatchSDLEvent(). + * This way, if a managers inherits fromt this SDL events manager, it can + * change the behavior of only a single event, without having to override all + * of SdlEventManager::dispatchSDLEvent(). + */ + //@{ + + virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event); + virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event); + virtual void handleKbdMouse(); + + //@} + + /** + * Assigns the mouse coords to the mouse event + */ + virtual void fillMouseEvent(Common::Event &event, int x, int y); + + /** + * Remaps key events. This allows platforms to configure + * their custom keys. + */ + virtual bool remapKey(SDL_Event &ev, Common::Event &event); + + /** + * Maps the ASCII value of key + */ + virtual int mapKey(SDLKey key, SDLMod mod, Uint16 unicode); + + /** + * Configures the key modifiers flags status + */ + virtual void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event); +}; + +#endif diff --git a/backends/events/symbiansdl/symbiansdl-events.cpp b/backends/events/symbiansdl/symbiansdl-events.cpp new file mode 100644 index 0000000000..2d144f9ad9 --- /dev/null +++ b/backends/events/symbiansdl/symbiansdl-events.cpp @@ -0,0 +1,201 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef __SYMBIAN32__ + +#include "backends/events/symbiansdl/symbiansdl-events.h" +#include "backends/platform/symbian/src/SymbianActions.h" +#include "gui/message.h" +#include "common/translation.h" + +#include <bautils.h> + +SymbianSdlEventManager::zoneDesc SymbianSdlEventManager::_zones[TOTAL_ZONES] = { + { 0, 0, 320, 145 }, + { 0, 145, 150, 55 }, + { 150, 145, 170, 55 } +}; + +SymbianSdlEventManager::SymbianSdlEventManager(Common::EventSource *boss) + : + _currentZone(0), + SdlEventManager(boss) { + for (int i = 0; i < TOTAL_ZONES; i++) { + _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)); + _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)); + } +} + +bool SymbianSdlEventManager::remapKey(SDL_Event &ev, Common::Event &event) { + if (GUI::Actions::Instance()->mappingActive() || ev.key.keysym.sym <= SDLK_UNKNOWN) + return false; + + for (TInt loop = 0; loop < GUI::ACTION_LAST; loop++) { + if (GUI::Actions::Instance()->getMapping(loop) == (uint)ev.key.keysym.sym && + GUI::Actions::Instance()->isEnabled(loop)) { + // Create proper event instead + switch (loop) { + case GUI::ACTION_UP: + if (ev.type == SDL_KEYDOWN) { + _km.y_vel = -1; + _km.y_down_count = 1; + } else { + _km.y_vel = 0; + _km.y_down_count = 0; + } + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + + return true; + + case GUI::ACTION_DOWN: + if (ev.type == SDL_KEYDOWN) { + _km.y_vel = 1; + _km.y_down_count = 1; + } else { + _km.y_vel = 0; + _km.y_down_count = 0; + } + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + + return true; + + case GUI::ACTION_LEFT: + if (ev.type == SDL_KEYDOWN) { + _km.x_vel = -1; + _km.x_down_count = 1; + } else { + _km.x_vel = 0; + _km.x_down_count = 0; + } + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + + return true; + + case GUI::ACTION_RIGHT: + if (ev.type == SDL_KEYDOWN) { + _km.x_vel = 1; + _km.x_down_count = 1; + } else { + _km.x_vel = 0; + _km.x_down_count = 0; + } + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + + return true; + + case GUI::ACTION_LEFTCLICK: + event.type = (ev.type == SDL_KEYDOWN ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP); + fillMouseEvent(event, _km.x, _km.y); + + return true; + + case GUI::ACTION_RIGHTCLICK: + event.type = (ev.type == SDL_KEYDOWN ? Common::EVENT_RBUTTONDOWN : Common::EVENT_RBUTTONUP); + fillMouseEvent(event, _km.x, _km.y); + + return true; + + case GUI::ACTION_ZONE: + if (ev.type == SDL_KEYDOWN) { + for (int i = 0; i < TOTAL_ZONES; i++) + if (_km.x >= _zones[i].x && _km.y >= _zones[i].y && + _km.x <= _zones[i].x + _zones[i].width && _km.y <= _zones[i].y + _zones[i].height + ) { + _mouseXZone[i] = _km.x; + _mouseYZone[i] = _km.y; + break; + } + _currentZone++; + if (_currentZone >= TOTAL_ZONES) + _currentZone = 0; + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _mouseXZone[_currentZone], _mouseYZone[_currentZone]); + SDL_WarpMouse(event.mouse.x, event.mouse.y); + } + + return true; + case GUI::ACTION_MULTI: { + GUI::Key &key = GUI::Actions::Instance()->getKeyAction(loop); + // if key code is pause, then change event to interactive or just fall through + if (key.keycode() == SDLK_PAUSE) { + event.type = Common::EVENT_PREDICTIVE_DIALOG; + return true; + } + } + case GUI::ACTION_SAVE: + case GUI::ACTION_SKIP: + case GUI::ACTION_SKIP_TEXT: + case GUI::ACTION_PAUSE: + case GUI::ACTION_SWAPCHAR: + case GUI::ACTION_FASTMODE: + case GUI::ACTION_DEBUGGER: + case GUI::ACTION_MAINMENU: + case GUI::ACTION_VKB: + case GUI::ACTION_KEYMAPPER:{ + GUI::Key &key = GUI::Actions::Instance()->getKeyAction(loop); + ev.key.keysym.sym = (SDLKey) key.keycode(); + ev.key.keysym.scancode = 0; + ev.key.keysym.mod = (SDLMod) key.flags(); + + // Translate from SDL keymod event to Scummvm Key Mod Common::Event. + // This codes is also present in GP32 backend and in SDL backend as a static function + // Perhaps it should be shared. + if (key.flags() != 0) { + event.kbd.flags = 0; + + if (ev.key.keysym.mod & KMOD_SHIFT) + event.kbd.flags |= Common::KBD_SHIFT; + + if (ev.key.keysym.mod & KMOD_ALT) + event.kbd.flags |= Common::KBD_ALT; + + if (ev.key.keysym.mod & KMOD_CTRL) + event.kbd.flags |= Common::KBD_CTRL; + } + + return false; + } + + case GUI::ACTION_QUIT: + { + GUI::MessageDialog alert(_("Do you want to quit ?"), _("Yes"), _("No")); + if (alert.runModal() == GUI::kMessageOK) + g_system->quit(); + + return true; + } + } + } + } + + return false; +} + +#endif + diff --git a/backends/events/symbiansdl/symbiansdl-events.h b/backends/events/symbiansdl/symbiansdl-events.h new file mode 100644 index 0000000000..fa1c066cae --- /dev/null +++ b/backends/events/symbiansdl/symbiansdl-events.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(BACKEND_EVENTS_SYMBIAN_SDL_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER) +#define BACKEND_EVENTS_SYMBIAN_SDL_H + +#include "backends/events/sdl/sdl-events.h" + +#define TOTAL_ZONES 3 + +/** + * SDL events manager for Symbian + */ +class SymbianSdlEventManager : public SdlEventManager { +public: + SymbianSdlEventManager(Common::EventSource *boss); + +protected: + // Used to handle joystick navi zones + int _mouseXZone[TOTAL_ZONES]; + int _mouseYZone[TOTAL_ZONES]; + int _currentZone; + + struct zoneDesc { + int x; + int y; + int width; + int height; + }; + + static zoneDesc _zones[TOTAL_ZONES]; + + virtual bool remapKey(SDL_Event &ev, Common::Event &event); +}; + +#endif + diff --git a/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp new file mode 100644 index 0000000000..a1e351251a --- /dev/null +++ b/backends/graphics/gp2xsdl/gp2xsdl-graphics.cpp @@ -0,0 +1,183 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef GP2X + +#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" +#include "graphics/scaler/aspect.h" +#include <SDL_gp2x.h> + +static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { + {"Fullscreen", "1x", GFX_NORMAL}, + {0, 0, 0} +}; + +GP2XSdlGraphicsManager::GP2XSdlGraphicsManager() + : + _adjustZoomOnMouse(false) { + +} + +const OSystem::GraphicsMode *GP2XSdlGraphicsManager::getSupportedGraphicsModes() const { + return s_supportedGraphicsModes; +} + +int GP2XSdlGraphicsManager::getDefaultGraphicsMode() const { + return GFX_NORMAL; +} + + +bool GP2XSdlGraphicsManager::hasFeature(OSystem::Feature f) { + if (f == OSystem::kFeatureIconifyWindow) + return false; + + return SdlGraphicsManager::hasFeature(f); +} + +void GP2XSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + if (f != OSystem::kFeatureIconifyWindow) + SdlGraphicsManager::setFeatureState(f, enable); +} + +void GP2XSdlGraphicsManager::drawMouse() { + if (!_mouseVisible || !_mouseSurface) { + _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; + return; + } + + SDL_Rect zoomdst; + SDL_Rect dst; + int scale; + int hotX, hotY; + int tmpScreenWidth, tmpScreenHeight; + + // Temp vars to ensure we zoom to the LCD resolution or greater. + tmpScreenWidth = _videoMode.screenWidth; + tmpScreenHeight = _videoMode.screenHeight; + + if (_videoMode.screenHeight <= 240) { + tmpScreenHeight = 240; + } + + if (_videoMode.screenWidth <= 320) { + tmpScreenWidth = 320; + } + + dst.x = _mouseCurState.x; + dst.y = _mouseCurState.y; + + if (!_overlayVisible) { + scale = _videoMode.scaleFactor; + dst.w = _mouseCurState.vW; + dst.h = _mouseCurState.vH; + hotX = _mouseCurState.vHotX; + hotY = _mouseCurState.vHotY; + } else { + scale = 1; + dst.w = _mouseCurState.rW; + dst.h = _mouseCurState.rH; + hotX = _mouseCurState.rHotX; + hotY = _mouseCurState.rHotY; + } + + // The mouse is undrawn using virtual coordinates, i.e. they may be + // scaled and aspect-ratio corrected. + + _mouseBackup.x = dst.x - hotX; + _mouseBackup.y = dst.y - hotY; + _mouseBackup.w = dst.w; + _mouseBackup.h = dst.h; + + // We draw the pre-scaled cursor image, so now we need to adjust for + // scaling, shake position and aspect ratio correction manually. + + if (!_overlayVisible) { + dst.y += _currentShakePos; + } + + if (_videoMode.aspectRatioCorrection && !_overlayVisible) + dst.y = real2Aspect(dst.y); + + dst.x = scale * dst.x - _mouseCurState.rHotX; + dst.y = scale * dst.y - _mouseCurState.rHotY; + dst.w = _mouseCurState.rW; + dst.h = _mouseCurState.rH; + + // Hacking about with the zoom around mouse pointer stuff. + if (_adjustZoomOnMouse){ + + zoomdst.w = (tmpScreenWidth / 2); + zoomdst.h = (tmpScreenHeight / 2); + + // Create a zoomed rect centered on the mouse pointer. + // Will pan 1/4 of the screen. + + if (dst.x > ((tmpScreenWidth / 4) * 3)) { + zoomdst.x = (tmpScreenWidth / 2); + } else { + zoomdst.x = (dst.x - (tmpScreenWidth / 4)); + if (zoomdst.x < 0) { + zoomdst.x = 0; + } + } + + if (dst.y > ((tmpScreenHeight / 4) * 3)) { + zoomdst.y = (tmpScreenHeight / 2); + } else { + zoomdst.y = (dst.y - (tmpScreenHeight / 4)); + if (zoomdst.y < 0) { + zoomdst.y = 0; + } + } + SDL_GP2X_Display(&zoomdst); + } else { + + // Make sure we are looking at the whole screen otherwise. + + zoomdst.x = 0; + zoomdst.y = 0; + zoomdst.w = (tmpScreenWidth); + zoomdst.h = (tmpScreenHeight); + + SDL_GP2X_Display(&zoomdst); + }; + + // Note that SDL_BlitSurface() and addDirtyRect() will both perform any + // clipping necessary + + if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0) + error("SDL_BlitSurface failed: %s", SDL_GetError()); + + // The screen will be updated using real surface coordinates, i.e. + // they will not be scaled or aspect-ratio corrected. + + addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); +} + +void GP2XSdlGraphicsManager::toggleZoomOnMouse() { + _adjustZoomOnMouse = !_adjustZoomOnMouse; +} + +#endif diff --git a/backends/graphics/gp2xsdl/gp2xsdl-graphics.h b/backends/graphics/gp2xsdl/gp2xsdl-graphics.h new file mode 100644 index 0000000000..776a9b1a0f --- /dev/null +++ b/backends/graphics/gp2xsdl/gp2xsdl-graphics.h @@ -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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_SDL_GP2X_H +#define BACKENDS_GRAPHICS_SDL_GP2X_H + +#include "backends/graphics/sdl/sdl-graphics.h" + +class GP2XSdlGraphicsManager : public SdlGraphicsManager { +public: + + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual void drawMouse(); + + virtual bool hasFeature(OSystem::Feature f); + virtual void setFeatureState(OSystem::Feature f, bool enable); + + // Toggles zoom adjust on mouse + void toggleZoomOnMouse(); + +protected: + bool _adjustZoomOnMouse; +}; + +#endif diff --git a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp b/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.cpp index f6ad226d42..8cb3eed083 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp +++ b/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.cpp @@ -23,15 +23,14 @@ * */ -#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" +#ifdef GP2XWIZ + +#include "backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h" +#include "backends/events/gp2xsdl/gp2xsdl-events.h" #include "common/mutex.h" -#include "graphics/font.h" -#include "graphics/fontman.h" -#include "graphics/scaler.h" #include "graphics/scaler/aspect.h" #include "graphics/scaler/downscaler.h" -#include "graphics/surface.h" static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {"1x", "Fullscreen", GFX_NORMAL}, @@ -39,16 +38,15 @@ static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {0, 0, 0} }; - -const OSystem::GraphicsMode *OSystem_GP2XWIZ::getSupportedGraphicsModes() const { +const OSystem::GraphicsMode *GP2XWIZSdlGraphicsManager::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } -int OSystem_GP2XWIZ::getDefaultGraphicsMode() const { +int GP2XWIZSdlGraphicsManager::getDefaultGraphicsMode() const { return GFX_NORMAL; } -bool OSystem_GP2XWIZ::setGraphicsMode(int mode) { +bool GP2XWIZSdlGraphicsManager::setGraphicsMode(int mode) { Common::StackLock lock(_graphicsMutex); assert(_transactionMode == kTransactionActive); @@ -82,7 +80,7 @@ bool OSystem_GP2XWIZ::setGraphicsMode(int mode) { return true; } -void OSystem_GP2XWIZ::setGraphicsModeIntern() { +void GP2XWIZSdlGraphicsManager::setGraphicsModeIntern() { Common::StackLock lock(_graphicsMutex); ScalerProc *newScalerProc = 0; @@ -111,8 +109,7 @@ void OSystem_GP2XWIZ::setGraphicsModeIntern() { blitCursor(); } - -void OSystem_GP2XWIZ::initSize(uint w, uint h) { +void GP2XWIZSdlGraphicsManager::initSize(uint w, uint h) { assert(_transactionMode == kTransactionActive); // Avoid redundant res changes @@ -124,13 +121,13 @@ void OSystem_GP2XWIZ::initSize(uint w, uint h) { if (w > 320 || h > 240){ setGraphicsMode(GFX_HALF); setGraphicsModeIntern(); - toggleMouseGrab(); + ((GP2XSdlEventManager *)g_system->getEventManager())->toggleMouseGrab(); } _transactionDetails.sizeChanged = true; } -bool OSystem_GP2XWIZ::loadGFXMode() { +bool GP2XWIZSdlGraphicsManager::loadGFXMode() { _videoMode.overlayWidth = 320; _videoMode.overlayHeight = 240; _videoMode.fullscreen = true; @@ -138,10 +135,10 @@ bool OSystem_GP2XWIZ::loadGFXMode() { if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) _videoMode.aspectRatioCorrection = false; - return OSystem_SDL::loadGFXMode(); + return SdlGraphicsManager::loadGFXMode(); } -void OSystem_GP2XWIZ::drawMouse() { +void GP2XWIZSdlGraphicsManager::drawMouse() { if (!_mouseVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; @@ -207,7 +204,7 @@ void OSystem_GP2XWIZ::drawMouse() { addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); } -void OSystem_GP2XWIZ::undrawMouse() { +void GP2XWIZSdlGraphicsManager::undrawMouse() { const int x = _mouseBackup.x; const int y = _mouseBackup.y; @@ -225,7 +222,7 @@ void OSystem_GP2XWIZ::undrawMouse() { } } -void OSystem_GP2XWIZ::internUpdateScreen() { +void GP2XWIZSdlGraphicsManager::internUpdateScreen() { SDL_Surface *srcSurf, *origSurf; int height, width; ScalerProc *scalerProc; @@ -419,28 +416,30 @@ void OSystem_GP2XWIZ::internUpdateScreen() { _mouseNeedsRedraw = false; } -void OSystem_GP2XWIZ::showOverlay() { +void GP2XWIZSdlGraphicsManager::showOverlay() { if (_videoMode.mode == GFX_HALF){ _mouseCurState.x = _mouseCurState.x / 2; _mouseCurState.y = _mouseCurState.y / 2; } - OSystem_SDL::showOverlay(); + SdlGraphicsManager::showOverlay(); } -void OSystem_GP2XWIZ::hideOverlay() { +void GP2XWIZSdlGraphicsManager::hideOverlay() { if (_videoMode.mode == GFX_HALF){ _mouseCurState.x = _mouseCurState.x * 2; _mouseCurState.y = _mouseCurState.y * 2; } - OSystem_SDL::hideOverlay(); + SdlGraphicsManager::hideOverlay(); } -void OSystem_GP2XWIZ::warpMouse(int x, int y) { +void GP2XWIZSdlGraphicsManager::warpMouse(int x, int y) { if (_mouseCurState.x != x || _mouseCurState.y != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible){ x = x / 2; y = y / 2; } } - OSystem_SDL::warpMouse(x, y); + SdlGraphicsManager::warpMouse(x, y); } + +#endif diff --git a/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h b/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h new file mode 100644 index 0000000000..5f0c739379 --- /dev/null +++ b/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_SDL_GP2XWIZ_H +#define BACKENDS_GRAPHICS_SDL_GP2XWIZ_H + +#include "backends/graphics/sdl/sdl-graphics.h" + +// FIXME: For now keep hacks in this header to save polluting the SDL backend. +enum { + GFX_HALF = 12 +}; + +class GP2XWIZSdlGraphicsManager : public SdlGraphicsManager { +public: + virtual void setGraphicsModeIntern(); + virtual bool setGraphicsMode(int mode); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + + virtual void initSize(uint w, uint h); + + virtual void internUpdateScreen(); + + virtual bool loadGFXMode(); + + virtual void drawMouse(); + virtual void undrawMouse(); + + virtual void showOverlay(); + virtual void hideOverlay(); + + virtual void warpMouse(int x, int y); +}; + +#endif diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h new file mode 100644 index 0000000000..d2ce6534e1 --- /dev/null +++ b/backends/graphics/graphics.h @@ -0,0 +1,91 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_ABSTRACT_H +#define BACKENDS_GRAPHICS_ABSTRACT_H + +#include "common/system.h" +#include "common/noncopyable.h" +#include "common/keyboard.h" + +/** + * Abstract class for graphics manager. Subclasses + * implement the real functionality. + */ +class GraphicsManager : Common::NonCopyable { +public: + virtual ~GraphicsManager() {} + + virtual bool hasFeature(OSystem::Feature f) = 0; + virtual void setFeatureState(OSystem::Feature f, bool enable) = 0; + virtual bool getFeatureState(OSystem::Feature f) = 0; + + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const = 0; + virtual int getDefaultGraphicsMode() const = 0; + virtual bool setGraphicsMode(int mode) = 0; + virtual void resetGraphicsScale() = 0; + virtual int getGraphicsMode() const = 0; +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const = 0; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; +#endif + virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0; + virtual int getScreenChangeID() const = 0; + + virtual void beginGFXTransaction() = 0; + virtual OSystem::TransactionError endGFXTransaction() = 0; + + virtual int16 getHeight() = 0; + virtual int16 getWidth() = 0; + virtual void setPalette(const byte *colors, uint start, uint num) = 0; + virtual void grabPalette(byte *colors, uint start, uint num) = 0; + virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0; + virtual Graphics::Surface *lockScreen() = 0; + virtual void unlockScreen() = 0; + virtual void fillScreen(uint32 col) = 0; + virtual void updateScreen() = 0; + virtual void setShakePos(int shakeOffset) = 0; + virtual void setFocusRectangle(const Common::Rect& rect) = 0; + virtual void clearFocusRectangle() = 0; + + virtual void showOverlay() = 0; + virtual void hideOverlay() = 0; + virtual Graphics::PixelFormat getOverlayFormat() const = 0; + virtual void clearOverlay() = 0; + virtual void grabOverlay(OverlayColor *buf, int pitch) = 0; + virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h)= 0; + virtual int16 getOverlayHeight() = 0; + virtual int16 getOverlayWidth() = 0; + + virtual bool showMouse(bool visible) = 0; + virtual void warpMouse(int x, int y) = 0; + virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL) = 0; + virtual void setCursorPalette(const byte *colors, uint start, uint num) = 0; + virtual void disableCursorPalette(bool disable) = 0; + + virtual void displayMessageOnOSD(const char *msg) {} +}; + +#endif diff --git a/backends/platform/linuxmoto/linuxmoto-graphics.cpp b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp index a39416ebc4..dbedb2e1a7 100644 --- a/backends/platform/linuxmoto/linuxmoto-graphics.cpp +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp @@ -23,8 +23,10 @@ * */ -#include "backends/platform/linuxmoto/linuxmoto-sdl.h" +#ifdef LINUXMOTO +#include "backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h" +#include "backends/events/linuxmotosdl/linuxmotosdl-events.h" #include "common/mutex.h" #include "graphics/font.h" #include "graphics/fontman.h" @@ -33,22 +35,25 @@ #include "graphics/scaler/downscaler.h" #include "graphics/surface.h" +enum { + GFX_HALF = 12 +}; + static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {"1x", "Fullscreen", GFX_NORMAL}, {"½x", "Downscale", GFX_HALF}, {0, 0, 0} }; - -const OSystem::GraphicsMode *OSystem_LINUXMOTO::getSupportedGraphicsModes() const { +const OSystem::GraphicsMode *LinuxmotoSdlGraphicsManager::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } -int OSystem_LINUXMOTO::getDefaultGraphicsMode() const { +int LinuxmotoSdlGraphicsManager::getDefaultGraphicsMode() const { return GFX_NORMAL; } -bool OSystem_LINUXMOTO::setGraphicsMode(int mode) { +bool LinuxmotoSdlGraphicsManager::setGraphicsMode(int mode) { Common::StackLock lock(_graphicsMutex); assert(_transactionMode == kTransactionActive); @@ -82,7 +87,7 @@ bool OSystem_LINUXMOTO::setGraphicsMode(int mode) { return true; } -void OSystem_LINUXMOTO::setGraphicsModeIntern() { +void LinuxmotoSdlGraphicsManager::setGraphicsModeIntern() { Common::StackLock lock(_graphicsMutex); ScalerProc *newScalerProc = 0; @@ -112,7 +117,7 @@ void OSystem_LINUXMOTO::setGraphicsModeIntern() { } -void OSystem_LINUXMOTO::initSize(uint w, uint h) { +void LinuxmotoSdlGraphicsManager::initSize(uint w, uint h) { assert(_transactionMode == kTransactionActive); // Avoid redundant res changes @@ -125,13 +130,13 @@ void OSystem_LINUXMOTO::initSize(uint w, uint h) { if (w > 320 || h > 240) { setGraphicsMode(GFX_HALF); setGraphicsModeIntern(); - toggleMouseGrab(); + ((LinuxmotoSdlEventManager *)g_system->getEventManager())->toggleMouseGrab(); } _transactionDetails.sizeChanged = true; } -bool OSystem_LINUXMOTO::loadGFXMode() { +bool LinuxmotoSdlGraphicsManager::loadGFXMode() { printf("Game ScreenMode = %d*%d\n",_videoMode.screenWidth, _videoMode.screenHeight); if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) { _videoMode.aspectRatioCorrection = false; @@ -157,10 +162,10 @@ bool OSystem_LINUXMOTO::loadGFXMode() { _videoMode.hardwareHeight = effectiveScreenHeight(); } - return OSystem_SDL::loadGFXMode(); + return SdlGraphicsManager::loadGFXMode(); } -void OSystem_LINUXMOTO::drawMouse() { +void LinuxmotoSdlGraphicsManager::drawMouse() { if (!_mouseVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; @@ -226,7 +231,7 @@ void OSystem_LINUXMOTO::drawMouse() { addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); } -void OSystem_LINUXMOTO::undrawMouse() { +void LinuxmotoSdlGraphicsManager::undrawMouse() { const int x = _mouseBackup.x; const int y = _mouseBackup.y; @@ -244,13 +249,13 @@ void OSystem_LINUXMOTO::undrawMouse() { } } -void OSystem_LINUXMOTO::internUpdateScreen() { +void LinuxmotoSdlGraphicsManager::internUpdateScreen() { SDL_Surface *srcSurf, *origSurf; int height, width; ScalerProc *scalerProc; int scale1; -#if defined (DEBUG) && ! defined(_WIN32_WCE) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) +#if defined (DEBUG) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) assert(_hwscreen != NULL); assert(_hwscreen->map->sw_data != NULL); #endif @@ -443,28 +448,48 @@ void OSystem_LINUXMOTO::internUpdateScreen() { _mouseNeedsRedraw = false; } -void OSystem_LINUXMOTO::showOverlay() { +void LinuxmotoSdlGraphicsManager::showOverlay() { if (_videoMode.mode == GFX_HALF) { _mouseCurState.x = _mouseCurState.x / 2; _mouseCurState.y = _mouseCurState.y / 2; } - OSystem_SDL::showOverlay(); + SdlGraphicsManager::showOverlay(); } -void OSystem_LINUXMOTO::hideOverlay() { +void LinuxmotoSdlGraphicsManager::hideOverlay() { if (_videoMode.mode == GFX_HALF) { _mouseCurState.x = _mouseCurState.x * 2; _mouseCurState.y = _mouseCurState.y * 2; } - OSystem_SDL::hideOverlay(); + SdlGraphicsManager::hideOverlay(); } -void OSystem_LINUXMOTO::warpMouse(int x, int y) { +void LinuxmotoSdlGraphicsManager::warpMouse(int x, int y) { if (_mouseCurState.x != x || _mouseCurState.y != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible) { x = x / 2; y = y / 2; } } - OSystem_SDL::warpMouse(x, y); + SdlGraphicsManager::warpMouse(x, y); +} + +void LinuxmotoSdlGraphicsManager::adjustMouseEvent(const Common::Event &event) { + if (!event.synthetic) { + Common::Event newEvent(event); + newEvent.synthetic = true; + if (!_overlayVisible) { + if (_videoMode.mode == GFX_HALF) { + event.mouse.x *= 2; + event.mouse.y *= 2; + } + newEvent.mouse.x /= _videoMode.scaleFactor; + newEvent.mouse.y /= _videoMode.scaleFactor; + if (_videoMode.aspectRatioCorrection) + newEvent.mouse.y = aspect2Real(newEvent.mouse.y); + } + g_system->getEventManager()->pushEvent(newEvent); + } } + +#endif diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h new file mode 100644 index 0000000000..1b387ca189 --- /dev/null +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_SDL_LINUXMOTO_H +#define BACKENDS_GRAPHICS_SDL_LINUXMOTO_H + +#include "backends/graphics/sdl/sdl-graphics.h" + +class LinuxmotoSdlGraphicsManager : public SdlGraphicsManager { +public: + virtual void initSize(uint w, uint h); + virtual void setGraphicsModeIntern(); + virtual bool setGraphicsMode(int mode); + virtual void internUpdateScreen(); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual bool loadGFXMode(); + virtual void drawMouse(); + virtual void undrawMouse(); + virtual void showOverlay(); + virtual void hideOverlay(); + virtual void warpMouse(int x, int y); + +protected: + virtual void adjustMouseEvent(const Common::Event &event); +}; + +#endif diff --git a/backends/graphics/null/null-graphics.h b/backends/graphics/null/null-graphics.h new file mode 100644 index 0000000000..4c75a9faba --- /dev/null +++ b/backends/graphics/null/null-graphics.h @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_NULL_H +#define BACKENDS_GRAPHICS_NULL_H + +#include "backends/graphics/graphics.h" + +static const OSystem::GraphicsMode s_noGraphicsModes[] = { {0, 0, 0} }; + +class NullGraphicsManager : GraphicsManager { +public: + virtual ~NullGraphicsManager() {} + + bool hasFeature(OSystem::Feature f) { return false; } + void setFeatureState(OSystem::Feature f, bool enable) {} + bool getFeatureState(OSystem::Feature f) { return false; } + + const OSystem::GraphicsMode *getSupportedGraphicsModes() const { return s_noGraphicsModes; } + int getDefaultGraphicsMode() const { return 0; } + bool setGraphicsMode(int mode) { return true; } + int getGraphicsMode() const { return 0; } + inline Graphics::PixelFormat getScreenFormat() const { + return Graphics::PixelFormat::createFormatCLUT8(); + }; + inline Common::List<Graphics::PixelFormat> getSupportedFormats() { + Common::List<Graphics::PixelFormat> list; + list.push_back(Graphics::PixelFormat::createFormatCLUT8()); + return list; + }; + void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) {} + virtual int getScreenChangeID() const { return 0; } + + void beginGFXTransaction() {} + OSystem::TransactionError endGFXTransaction() { return OSystem::kTransactionSuccess; } + + int16 getHeight() { return 0; } + int16 getWidth() { return 0; } + void setPalette(const byte *colors, uint start, uint num) {} + void grabPalette(byte *colors, uint start, uint num) {} + void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {} + Graphics::Surface *lockScreen() { return NULL; } + void unlockScreen() {} + void fillScreen(uint32 col) {} + void updateScreen() {} + void setShakePos(int shakeOffset) {} + void setFocusRectangle(const Common::Rect& rect) {} + void clearFocusRectangle() {} + + void showOverlay() {} + void hideOverlay() {} + Graphics::PixelFormat getOverlayFormat() const { return Graphics::PixelFormat(); } + void clearOverlay() {} + void grabOverlay(OverlayColor *buf, int pitch) {} + void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {} + int16 getOverlayHeight() { return 0; } + int16 getOverlayWidth() { return 0; } + + bool showMouse(bool visible) { return !visible; } + void warpMouse(int x, int y) {} + void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL) {} + void setCursorPalette(const byte *colors, uint start, uint num) {} + void disableCursorPalette(bool disable) {} +}; + +#endif diff --git a/backends/graphics/opengl/glerrorcheck.cpp b/backends/graphics/opengl/glerrorcheck.cpp new file mode 100644 index 0000000000..ee177f0ac5 --- /dev/null +++ b/backends/graphics/opengl/glerrorcheck.cpp @@ -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. + * + * $URL$ + * $Id$ + * + */ + +#if defined(DEBUG) && defined(USE_OPENGL) + +#include "backends/graphics/opengl/glerrorcheck.h" +#include "common/debug.h" + +#ifdef WIN32 +#if defined(ARRAYSIZE) && !defined(_WINDOWS_) +#undef ARRAYSIZE +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef ARRAYSIZE +#endif + +#ifdef MACOSX +#include <gl.h> +#elif defined(USE_GLES) +#include <GLES/gl.h> +#else +#include <GL/gl.h> +#endif + +static const char *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"; + } + + static char buf[40]; + snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error); + return buf; +} + +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)); +} + +#endif diff --git a/backends/graphics/opengl/glerrorcheck.h b/backends/graphics/opengl/glerrorcheck.h new file mode 100644 index 0000000000..a94699ce1d --- /dev/null +++ b/backends/graphics/opengl/glerrorcheck.h @@ -0,0 +1,38 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(DEBUG) + +// If not in debug, do nothing +#define CHECK_GL_ERROR() do {} while (false) + +#else + +// If in debug, check for an error after a GL call +#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__) + +void checkGlError(const char *file, int line); + +#endif diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp new file mode 100644 index 0000000000..d7a1b0a236 --- /dev/null +++ b/backends/graphics/opengl/gltexture.cpp @@ -0,0 +1,188 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef 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 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() { + static bool inited = false; + + // Return if extensions already checked + if (inited) + return; + + // Get a string with all extensions + const char* ext_string = + reinterpret_cast<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; + } + + inited = true; +} + +GLTexture::GLTexture(byte bpp, GLenum format, GLenum type) + : + _bytesPerPixel(bpp), + _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 (w <= _textureWidth && h <= _textureHeight && !_refresh) + // Already allocated a sufficiently large buffer + 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, _glFormat, + _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) { + // Select this OpenGL texture + glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR(); + + // Check if the buffer has its data contiguously + /*if (static_cast<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 = static_cast<const byte *>(buf); + do { + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, + w, 1, _glFormat, _glType, src); CHECK_GL_ERROR(); + ++y; + src += pitch; + } while (--h); + //} +} + +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, + x + w, y, + x, y + h, + x + w, 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 new file mode 100644 index 0000000000..73771fda91 --- /dev/null +++ b/backends/graphics/opengl/gltexture.h @@ -0,0 +1,114 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef WIN32 +#if defined(ARRAYSIZE) && !defined(_WINDOWS_) +#undef ARRAYSIZE +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef ARRAYSIZE +#endif + +#if defined(USE_GLES) +#include <GLES/gl.h> +#include <GLES/glext.h> +#elif defined(MACOSX) +#include <gl.h> +#include <glext.h> +#else +#include <GL/gl.h> +#include <GL/glext.h> +#endif + +#include "graphics/surface.h" + +#include "common/rect.h" +#include "common/array.h" + +/** + * OpenGL texture manager class + */ +class GLTexture { +public: + /** + * Initialize OpenGL Extensions + */ + static void initGLExtensions(); + + GLTexture(byte bpp, GLenum format, GLenum type); + virtual ~GLTexture(); + + /** + * Refresh the texture after a context change. The + * process will be completed on next allocBuffer call. + */ + virtual void refresh(); + + /** + * Allocates memory needed for the given size. + */ + virtual void allocBuffer(GLuint width, GLuint height); + + /** + * Updates the texture pixels. + */ + virtual void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, + GLuint w, GLuint h); + + /** + * Draws the texture to the screen buffer. + */ + virtual 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; } + + /** + * Set the texture filter. + * GL_NEAREST or GL_LINEAR should be passed. + */ + void setFilter(GLint filter) { _filter = filter; } + +protected: + const byte _bytesPerPixel; + const GLenum _glFormat; + const GLenum _glType; + + GLuint _realWidth; + GLuint _realHeight; + GLuint _textureName; + GLuint _textureWidth; + GLuint _textureHeight; + GLint _filter; + bool _refresh; +}; diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp new file mode 100644 index 0000000000..f1436170b8 --- /dev/null +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -0,0 +1,1256 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef USE_OPENGL + +#include "backends/graphics/opengl/opengl-graphics.h" +#include "backends/graphics/opengl/glerrorcheck.h" +#include "common/file.h" +#include "common/mutex.h" +#include "common/translation.h" +#include "graphics/font.h" +#include "graphics/fontman.h" + +OpenGLGraphicsManager::OpenGLGraphicsManager() + : +#ifdef USE_OSD + _osdTexture(0), _osdAlpha(0), _osdFadeStartTime(0), +#endif + _gameTexture(0), _overlayTexture(0), _cursorTexture(0), + _screenChangeCount(0), _screenNeedsRedraw(false), + _shakePos(0), + _overlayVisible(false), _overlayNeedsRedraw(false), + _transactionMode(kTransactionNone), + _cursorNeedsRedraw(false), _cursorPaletteDisabled(true), + _cursorVisible(false), _cursorKeyColor(0), + _cursorTargetScale(1), + _formatBGR(false), + _aspectX(0), _aspectY(0), _aspectWidth(0), _aspectHeight(0) { + + memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); + memset(&_videoMode, 0, sizeof(_videoMode)); + memset(&_transactionDetails, 0, sizeof(_transactionDetails)); + + _videoMode.mode = OpenGL::GFX_DOUBLESIZE; + _videoMode.scaleFactor = 2; + _videoMode.fullscreen = false; + _videoMode.antialiasing = false; + _videoMode.aspectRatioCorrection = 0; + + _gamePalette = (byte *)calloc(sizeof(byte) * 4, 256); + _cursorPalette = (byte *)calloc(sizeof(byte) * 4, 256); + + // Register the graphics manager as a event observer + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false); +} + +OpenGLGraphicsManager::~OpenGLGraphicsManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher() != NULL) + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + + free(_gamePalette); + free(_cursorPalette); + + if (_gameTexture != NULL) + delete _gameTexture; + if (_overlayTexture != NULL) + delete _overlayTexture; + if (_cursorTexture != NULL) + delete _cursorTexture; +} + +// +// Feature +// + +bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { + return + (f == OSystem::kFeatureAspectRatioCorrection) || + (f == OSystem::kFeatureCursorHasPalette); +} + +void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + setAspectRatioCorrection(enable ? -1 : 0); + break; + default: + break; + } +} + +bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { + return false; +} + +// +// Screen format and modes +// + +static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { + {"gl1x", _s("OpenGL Normal"), OpenGL::GFX_NORMAL}, +#ifdef USE_SCALERS + {"gl2x", "OpenGL 2x", OpenGL::GFX_DOUBLESIZE}, + {"gl3x", "OpenGL 3x", OpenGL::GFX_TRIPLESIZE}, +#endif + {0, 0, 0} +}; + +const OSystem::GraphicsMode *OpenGLGraphicsManager::supportedGraphicsModes() { + return s_supportedGraphicsModes; +} + +const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { + return s_supportedGraphicsModes; +} + +int OpenGLGraphicsManager::getDefaultGraphicsMode() const { + return OpenGL::GFX_NORMAL; +} + +bool OpenGLGraphicsManager::setGraphicsMode(int mode) { + assert(_transactionMode == kTransactionActive); + + if (_oldVideoMode.setup && _oldVideoMode.mode == mode) + return true; + + int newScaleFactor = 1; + + switch (mode) { + case OpenGL::GFX_NORMAL: + newScaleFactor = 1; + break; +#ifdef USE_SCALERS + case OpenGL::GFX_DOUBLESIZE: + newScaleFactor = 2; + break; + case OpenGL::GFX_TRIPLESIZE: + newScaleFactor = 3; + break; +#endif + default: + warning("unknown gfx mode %d", mode); + return false; + } + + if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) + _transactionDetails.needHotswap = true; + + _transactionDetails.needUpdatescreen = true; + + _videoMode.mode = mode; + _videoMode.scaleFactor = newScaleFactor; + + return true; +} + +int OpenGLGraphicsManager::getGraphicsMode() const { + assert (_transactionMode == kTransactionNone); + return _videoMode.mode; +} + +void OpenGLGraphicsManager::resetGraphicsScale() { + setScale(1); +} + +#ifdef USE_RGB_COLOR + +Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const { + return _screenFormat; +} + +#endif + +void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) { + assert(_transactionMode == kTransactionActive); + +#ifdef USE_RGB_COLOR + // Avoid redundant format changes + Graphics::PixelFormat newFormat; + if (!format) + newFormat = Graphics::PixelFormat::createFormatCLUT8(); + else + newFormat = *format; + + assert(newFormat.bytesPerPixel > 0); + + 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); + + _transactionMode = kTransactionActive; + _transactionDetails.sizeChanged = false; + _transactionDetails.needHotswap = false; + _transactionDetails.needUpdatescreen = false; + _transactionDetails.newContext = false; + _transactionDetails.filterChanged = false; +#ifdef USE_RGB_COLOR + _transactionDetails.formatChanged = false; +#endif + + _oldVideoMode = _videoMode; +} + +OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { + int errors = OSystem::kTransactionSuccess; + + assert(_transactionMode != kTransactionNone); + + if (_transactionMode == kTransactionRollback) { + if (_videoMode.fullscreen != _oldVideoMode.fullscreen) { + errors |= OSystem::kTransactionFullscreenFailed; + + _videoMode.fullscreen = _oldVideoMode.fullscreen; + } else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) { + errors |= OSystem::kTransactionAspectRatioFailed; + + _videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection; + } else if (_videoMode.mode != _oldVideoMode.mode) { + errors |= OSystem::kTransactionModeSwitchFailed; + + _videoMode.mode = _oldVideoMode.mode; + _videoMode.scaleFactor = _oldVideoMode.scaleFactor; +#ifdef USE_RGB_COLOR + } else if (_videoMode.format != _oldVideoMode.format) { + errors |= OSystem::kTransactionFormatNotSupported; + + _videoMode.format = _oldVideoMode.format; + _screenFormat = _videoMode.format; +#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 (_videoMode.fullscreen == _oldVideoMode.fullscreen && + _videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection && + _videoMode.mode == _oldVideoMode.mode && + _videoMode.screenWidth == _oldVideoMode.screenWidth && + _videoMode.screenHeight == _oldVideoMode.screenHeight) { + + _oldVideoMode.setup = false; + } + } + +#ifdef USE_RGB_COLOR + if (_transactionDetails.sizeChanged || _transactionDetails.formatChanged || _transactionDetails.needHotswap) { +#else + if (_transactionDetails.sizeChanged || _transactionDetails.needHotswap) { +#endif + unloadGFXMode(); + if (!loadGFXMode()) { + if (_oldVideoMode.setup) { + _transactionMode = kTransactionRollback; + errors |= endGFXTransaction(); + } + } else { + clearOverlay(); + + _videoMode.setup = true; + _screenChangeCount++; + } + } else if (_transactionDetails.filterChanged) { + loadTextures(); + internUpdateScreen(); + } else if (_transactionDetails.needUpdatescreen) { + internUpdateScreen(); + } + + _transactionMode = kTransactionNone; + return (OSystem::TransactionError)errors; +} + +// +// Screen +// + +int16 OpenGLGraphicsManager::getHeight() { + return _videoMode.screenHeight; +} + +int16 OpenGLGraphicsManager::getWidth() { + return _videoMode.screenWidth; +} + +void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { + assert(colors); + +#ifdef USE_RGB_COLOR + assert(_screenFormat.bytesPerPixel == 1); +#endif + + // Save the screen palette + memcpy(_gamePalette + start * 4, colors, num * 4); + + _screenNeedsRedraw = true; + + if (_cursorPaletteDisabled) + _cursorNeedsRedraw = true; +} + +void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { + assert(colors); + +#ifdef USE_RGB_COLOR + assert(_screenFormat.bytesPerPixel == 1); +#endif + + // Copies current palette to buffer + memcpy(colors, _gamePalette + start * 4, num * 4); +} + +void OpenGLGraphicsManager::copyRectToScreen(const byte *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 = buf; + byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch; + for (int i = 0; i < h; i++) { + memcpy(dst + x * _screenData.bytesPerPixel, src, w * _screenData.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); + } +} + +Graphics::Surface *OpenGLGraphicsManager::lockScreen() { + return &_screenData; +} + +void OpenGLGraphicsManager::unlockScreen() { + _screenNeedsRedraw = true; +} + +void OpenGLGraphicsManager::fillScreen(uint32 col) { + if (_gameTexture == NULL) + return; + + 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; + } + } else if (_screenFormat.bytesPerPixel == 4) { + uint32 *pixels = (uint32 *)_screenData.pixels; + for (int i = 0; i < _screenData.w * _screenData.h; i++) { + pixels[i] = col; + } + } + + _screenNeedsRedraw = true; +} + +void OpenGLGraphicsManager::updateScreen() { + assert (_transactionMode == kTransactionNone); + internUpdateScreen(); +} + +void OpenGLGraphicsManager::setShakePos(int shakeOffset) { + assert (_transactionMode == kTransactionNone); + _shakePos = shakeOffset; +} + +void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) { + +} + +void OpenGLGraphicsManager::clearFocusRectangle() { + +} + +// +// Overlay +// + +void OpenGLGraphicsManager::showOverlay() { + assert (_transactionMode == kTransactionNone); + + if (_overlayVisible) + return; + + _overlayVisible = true; + + clearOverlay(); +} + +void OpenGLGraphicsManager::hideOverlay() { + assert (_transactionMode == kTransactionNone); + + if (!_overlayVisible) + return; + + _overlayVisible = false; + + clearOverlay(); +} + +Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const { + return _overlayFormat; +} + +void OpenGLGraphicsManager::clearOverlay() { + memset(_overlayData.pixels, 0, _overlayData.h * _overlayData.pitch); + _overlayNeedsRedraw = true; +} + +void OpenGLGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) { + assert(_overlayData.bytesPerPixel == sizeof(buf[0])); + const byte *src = (byte *)_overlayData.pixels; + for (int i = 0; i < _overlayData.h; i++) { + memcpy(buf, src, _overlayData.pitch); + buf += pitch; + src += _overlayData.pitch; + } +} + +void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + assert (_transactionMode == kTransactionNone); + + if (_overlayTexture == NULL) + return; + + // Clip the coordinates + if (x < 0) { + w += x; + buf -= x; + x = 0; + } + + if (y < 0) { + h += y; buf -= y * pitch; + y = 0; + } + + if (w > _overlayData.w - x) + w = _overlayData.w - x; + + if (h > _overlayData.h - y) + h = _overlayData.h - y; + + if (w <= 0 || h <= 0) + return; + + if (_overlayFormat.aBits() == 1) { + // Copy buffer with the alpha bit on for all pixels for correct + // overlay drawing. + const uint16 *src = (const uint16 *)buf; + uint16 *dst = (uint16 *)_overlayData.pixels + y * _overlayData.w + x; + for (int i = 0; i < h; i++) { + for (int e = 0; e < w; e++) + dst[e] = src[e] | 0x1; + src += pitch; + dst += _overlayData.w; + } + } else { + // Copy buffer data to internal overlay surface + const byte *src = (const byte *)buf; + byte *dst = (byte *)_overlayData.pixels + y * _overlayData.pitch; + for (int i = 0; i < h; i++) { + memcpy(dst + x * _overlayData.bytesPerPixel, src, w * _overlayData.bytesPerPixel); + src += pitch * sizeof(buf[0]); + dst += _overlayData.pitch; + } + } + + // 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); + } +} + +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::setMousePos(int x, int y) { + _cursorState.x = x; + _cursorState.y = y; +} + +void OpenGLGraphicsManager::warpMouse(int x, int y) { + setMousePos(x, y); +} + +void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { +#ifdef USE_RGB_COLOR + if (!format) + _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); + else + _cursorFormat = *format; +#else + assert(keycolor <= 255); +#endif + + // Allocate space for cursor data + if (_cursorData.w != w || _cursorData.h != h) + _cursorData.create(w, h, _cursorFormat.bytesPerPixel); + + // Save cursor data + memcpy(_cursorData.pixels, buf, h * _cursorData.pitch); + + // Set cursor info + _cursorState.w = w; + _cursorState.h = h; + _cursorState.hotX = hotspotX; + _cursorState.hotY = hotspotY; + _cursorKeyColor = keycolor; + _cursorTargetScale = cursorTargetScale; + _cursorNeedsRedraw = true; + + refreshCursorScale(); +} + +void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { + assert(colors); + + // Save the cursor palette + memcpy(_cursorPalette + start * 4, colors, num * 4); + + _cursorPaletteDisabled = false; + _cursorNeedsRedraw = true; +} + +void OpenGLGraphicsManager::disableCursorPalette(bool disable) { + _cursorPaletteDisabled = disable; + _cursorNeedsRedraw = true; +} + +// +// Misc +// + +void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { + assert (_transactionMode == kTransactionNone); + assert(msg); + + // The font we are going to use: + const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont); + + if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight()) + _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), 2); + else + // Clear everything + memset(_osdSurface.pixels, 0, _osdSurface.h * _osdSurface.pitch); + + // Split the message into separate lines. + Common::Array<Common::String> lines; + const char *ptr; + for (ptr = msg; *ptr; ++ptr) { + if (*ptr == '\n') { + lines.push_back(Common::String(msg, ptr - msg)); + msg = ptr + 1; + } + } + lines.push_back(Common::String(msg, ptr - msg)); + + // Determine a rect which would contain the message string (clipped to the + // screen dimensions). + const int vOffset = 6; + const int lineSpacing = 1; + const int lineHeight = font->getFontHeight() + 2 * lineSpacing; + int width = 0; + int height = lineHeight * lines.size() + 2 * vOffset; + for (uint i = 0; i < lines.size(); i++) { + width = MAX(width, font->getStringWidth(lines[i]) + 14); + } + + // Clip the rect + if (width > _osdSurface.w) + width = _osdSurface.w; + if (height > _osdSurface.h) + height = _osdSurface.h; + + int dstX = (_osdSurface.w - width) / 2; + int dstY = (_osdSurface.h - height) / 2; + + // Draw a dark gray rect + uint16 color = 0x294B; + uint16 *dst = (uint16 *)_osdSurface.pixels + dstY * _osdSurface.w + dstX; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) + dst[j] = color; + dst += _osdSurface.w; + } + + // Render the message, centered, and in white + for (uint i = 0; i < lines.size(); i++) { + font->drawString(&_osdSurface, lines[i], + dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, + 0xFFFF, Graphics::kTextAlignCenter); + } + + // Update the texture + _osdTexture->updateBuffer(_osdSurface.pixels, _osdSurface.pitch, 0, 0, + _osdSurface.w, _osdSurface.h); + + // Init the OSD display parameters, and the fade out + _osdAlpha = kOSDInitialAlpha; + _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; +} + +// +// Intern +// + +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.bytesPerPixel == 1) { + // Create a temporary RGB888 surface + byte *surface = new byte[w * h * 3]; + + // Convert the paletted buffer to RGB888 + const byte *src = (byte *)_screenData.pixels + y * _screenData.pitch; + src += x * _screenData.bytesPerPixel; + byte *dst = surface; + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + dst[0] = _gamePalette[src[j] * 4]; + dst[1] = _gamePalette[src[j] * 4 + 1]; + dst[2] = _gamePalette[src[j] * 4 + 2]; + dst += 3; + } + src += _screenData.pitch; + } + + // Update the texture + _gameTexture->updateBuffer(surface, w * 3, x, y, w, h); + + // Free the temp surface + delete[] surface; + } else { + // Update the texture + _gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch + + x * _screenData.bytesPerPixel, _screenData.pitch, x, y, w, h); + } + + _screenNeedsRedraw = false; + _screenDirtyRect = Common::Rect(); +} + +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.bytesPerPixel == 1) { + // Create a temporary RGB888 surface + byte *surface = new byte[w * h * 3]; + + // Convert the paletted buffer to RGB888 + const byte *src = (byte *)_overlayData.pixels + y * _overlayData.pitch; + src += x * _overlayData.bytesPerPixel; + byte *dst = surface; + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + dst[0] = _gamePalette[src[j] * 4]; + dst[1] = _gamePalette[src[j] * 4 + 1]; + dst[2] = _gamePalette[src[j] * 4 + 2]; + dst += 3; + } + src += _screenData.pitch; + } + + // Update the texture + _overlayTexture->updateBuffer(surface, w * 3, x, y, w, h); + + // Free the temp surface + delete[] surface; + } else { + // Update the texture + _overlayTexture->updateBuffer((byte *)_overlayData.pixels + y * _overlayData.pitch + + x * _overlayData.bytesPerPixel, _overlayData.pitch, x, y, w, h); + } + + _overlayNeedsRedraw = false; + _overlayDirtyRect = Common::Rect(); +} + +void OpenGLGraphicsManager::refreshCursor() { + _cursorNeedsRedraw = false; + + if (_cursorFormat.bytesPerPixel == 1) { + // Create a temporary RGBA8888 surface + byte *surface = new byte[_cursorState.w * _cursorState.h * 4]; + memset(surface, 0, _cursorState.w * _cursorState.h * 4); + + // Select palette + byte *palette; + if (_cursorPaletteDisabled) + palette = _gamePalette; + else + palette = _cursorPalette; + + // Convert the paletted cursor to RGBA8888 + const byte *src = (byte *)_cursorData.pixels; + byte *dst = surface; + for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { + // Check for keycolor + if (src[i] != _cursorKeyColor) { + dst[0] = palette[src[i] * 4]; + dst[1] = palette[src[i] * 4 + 1]; + dst[2] = palette[src[i] * 4 + 2]; + dst[3] = 255; + } + dst += 4; + } + + // Allocate a texture big enough for cursor + _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); + + // Update the texture with new cursor + _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h); + + // Free the temp surface + delete[] surface; + } +} + +void OpenGLGraphicsManager::refreshCursorScale() { + // Get the window minimum scale factor. The cursor will mantain its original aspect + // ratio, and we do not want it to get too big if only one dimension is resized + float screenScaleFactor = MIN((float)_videoMode.hardwareWidth / _videoMode.screenWidth, + (float)_videoMode.hardwareHeight / _videoMode.screenHeight); + + if (_cursorTargetScale >= screenScaleFactor && _videoMode.scaleFactor >= screenScaleFactor) { + // If the cursor target scale and the video mode scale factor are bigger than + // the current window scale, do not scale the cursor for the overlay + _cursorState.rW = _cursorState.w; + _cursorState.rH = _cursorState.h; + _cursorState.rHotX = _cursorState.hotX; + _cursorState.rHotY = _cursorState.hotY; + } else { + // Otherwise, scale the cursor for the overlay + float targetScaleFactor = MIN(_cursorTargetScale, _videoMode.scaleFactor); + float actualFactor = (screenScaleFactor - targetScaleFactor + 1); + _cursorState.rW = (int16)(_cursorState.w * actualFactor); + _cursorState.rH = (int16)(_cursorState.h * actualFactor); + _cursorState.rHotX = (int16)(_cursorState.hotX * actualFactor); + _cursorState.rHotY = (int16)(_cursorState.hotY * actualFactor); + } + + // Always scale the cursor for the game + _cursorState.vW = (int16)(_cursorState.w * screenScaleFactor); + _cursorState.vH = (int16)(_cursorState.h * screenScaleFactor); + _cursorState.vHotX = (int16)(_cursorState.hotX * screenScaleFactor); + _cursorState.vHotY = (int16)(_cursorState.hotY * screenScaleFactor); +} + +void OpenGLGraphicsManager::refreshAspectRatio() { + _aspectWidth = _videoMode.hardwareWidth; + _aspectHeight = _videoMode.hardwareHeight; + + float aspectRatio = (float)_videoMode.hardwareWidth / _videoMode.hardwareHeight; + float desiredAspectRatio = getAspectRatio(); + + if (aspectRatio < desiredAspectRatio) + _aspectHeight = (int)(_aspectWidth / desiredAspectRatio + 0.5f); + else if (aspectRatio > desiredAspectRatio) + _aspectWidth = (int)(_aspectHeight * desiredAspectRatio + 0.5f); + + _aspectX = (_videoMode.hardwareWidth - _aspectWidth) / 2; + _aspectY = (_videoMode.hardwareHeight - _aspectHeight) / 2; +} + +void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &gltype) { + if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 + bpp = 4; + glFormat = GL_RGBA; + gltype = GL_UNSIGNED_BYTE; + } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)) { // RGB888 + bpp = 3; + glFormat = GL_RGB; + gltype = GL_UNSIGNED_BYTE; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 + bpp = 2; + 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; + glFormat = GL_RGBA; + gltype = GL_UNSIGNED_SHORT_5_5_5_1; + } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 + bpp = 2; + 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; + glFormat = GL_RGB; + gltype = GL_UNSIGNED_BYTE; + } else { + error("OpenGLGraphicsManager: Pixel format not supported"); + } +} + +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(); + + glTranslatef(0, _shakePos * scaleFactor, 0); CHECK_GL_ERROR(); + + // Draw the game screen + _gameTexture->drawTexture(_aspectX, _aspectY, _aspectWidth, _aspectHeight); + + glPopMatrix(); + + if (_overlayVisible) { + if (_overlayNeedsRedraw || !_overlayDirtyRect.isEmpty()) + // Refresh texture if dirty + refreshOverlay(); + + // Draw the overlay + _overlayTexture->drawTexture(_aspectX, _aspectY, _aspectWidth, _aspectHeight); + } + + if (_cursorVisible) { + if (_cursorNeedsRedraw) + // Refresh texture if dirty + refreshCursor(); + + glPushMatrix(); + 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(); + } + +#ifdef USE_OSD + if (_osdAlpha > 0) { + // 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(); + glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR(); + glMatrixMode(GL_MODELVIEW); CHECK_GL_ERROR(); + glLoadIdentity(); CHECK_GL_ERROR(); +} + +void OpenGLGraphicsManager::loadTextures() { +#ifdef USE_RGB_COLOR + if (_transactionDetails.formatChanged && _gameTexture) + delete _gameTexture; +#endif + + if (!_gameTexture) { + byte bpp; + GLenum format; + GLenum type; +#ifdef USE_RGB_COLOR + getGLPixelFormat(_screenFormat, bpp, format, type); +#else + getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, format, type); +#endif + _gameTexture = new GLTexture(bpp, format, type); + } + + _overlayFormat = Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0); + + if (!_overlayTexture) { + byte bpp; + GLenum format; + GLenum type; + getGLPixelFormat(_overlayFormat, bpp, format, type); + _overlayTexture = new GLTexture(bpp, format, type); + } + + if (!_cursorTexture) + _cursorTexture = new GLTexture(4, GL_RGBA, GL_UNSIGNED_BYTE); + + GLint filter = _videoMode.antialiasing ? GL_LINEAR : GL_NEAREST; + _gameTexture->setFilter(filter); + _overlayTexture->setFilter(filter); + _cursorTexture->setFilter(filter); + + if (_transactionDetails.newContext || _transactionDetails.filterChanged) { + // If the context was destroyed or it is needed to change the texture filter + // we need to recreate the textures + _gameTexture->refresh(); + _overlayTexture->refresh(); + _cursorTexture->refresh(); + } + + // 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 (_transactionDetails.formatChanged || + _oldVideoMode.screenWidth != _videoMode.screenWidth || + _oldVideoMode.screenHeight != _videoMode.screenHeight) + _screenData.create(_videoMode.screenWidth, _videoMode.screenHeight, + _screenFormat.bytesPerPixel); + + if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth || + _oldVideoMode.overlayHeight != _videoMode.overlayHeight) + _overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight, + _overlayFormat.bytesPerPixel); + + _screenNeedsRedraw = true; + _overlayNeedsRedraw = true; + _cursorNeedsRedraw = true; + +#ifdef USE_OSD + if (!_osdTexture) + _osdTexture = new GLTexture(2, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1); + + if (_transactionDetails.newContext || _transactionDetails.filterChanged) + _osdTexture->refresh(); + _osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); +#endif +} + +bool OpenGLGraphicsManager::loadGFXMode() { + // Initialize OpenGL settings + initGL(); + + loadTextures(); + + refreshCursorScale(); + + refreshAspectRatio(); + + internUpdateScreen(); + + return true; +} + +void OpenGLGraphicsManager::unloadGFXMode() { + +} + +void OpenGLGraphicsManager::setScale(int newScale) { + if (newScale == _videoMode.scaleFactor) + return; + + switch (newScale - 1) { + case OpenGL::GFX_NORMAL: + _videoMode.mode = OpenGL::GFX_NORMAL; + break; + case OpenGL::GFX_DOUBLESIZE: + _videoMode.mode = OpenGL::GFX_DOUBLESIZE; + break; + case OpenGL::GFX_TRIPLESIZE: + _videoMode.mode = OpenGL::GFX_TRIPLESIZE; + break; + } + + _videoMode.scaleFactor = newScale; + _transactionDetails.sizeChanged = true; +} + +void OpenGLGraphicsManager::setAspectRatioCorrection(int ratio) { + if (_oldVideoMode.setup && _oldVideoMode.aspectRatioCorrection == ratio) + return; + + if (_transactionMode == kTransactionActive) { + if (ratio == -1) + _videoMode.aspectRatioCorrection = (_videoMode.aspectRatioCorrection + 1) % 5; + else + _videoMode.aspectRatioCorrection = ratio; + _transactionDetails.needHotswap = true; + } +} + +Common::String OpenGLGraphicsManager::getAspectRatioName() { + switch (_videoMode.aspectRatioCorrection) { + case kAspectRatioNone: + return "None"; + case kAspectRatioConserve: + return "Conserve"; + case kAspectRatio4_3: + return "4/3"; + case kAspectRatio16_9: + return "16/9"; + case kAspectRatio16_10: + return "16/10"; + } + return ""; +} + +float OpenGLGraphicsManager::getAspectRatio() { + switch (_videoMode.aspectRatioCorrection) { + case kAspectRatioConserve: + return (float)_videoMode.screenWidth / _videoMode.screenHeight; + case kAspectRatio4_3: + return 4.0f / 3.0f; + case kAspectRatio16_9: + return 16.0f / 9.0f; + case kAspectRatio16_10: + return 16.0f / 10.0f; + default: + return (float)_videoMode.hardwareWidth / _videoMode.hardwareHeight; + } +} + +void OpenGLGraphicsManager::adjustMouseEvent(const Common::Event &event) { + if (!event.synthetic) { + Common::Event newEvent(event); + newEvent.synthetic = true; + + if (!_videoMode.aspectRatioCorrection) { + if (_videoMode.hardwareWidth != _videoMode.overlayWidth) + newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _videoMode.hardwareWidth; + if (_videoMode.hardwareHeight != _videoMode.overlayHeight) + newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _videoMode.hardwareHeight; + + if (!_overlayVisible) { + newEvent.mouse.x /= _videoMode.scaleFactor; + newEvent.mouse.y /= _videoMode.scaleFactor; + } + + } else { + newEvent.mouse.x -= _aspectX; + newEvent.mouse.y -= _aspectY; + + if (_overlayVisible) { + if (_aspectWidth != _videoMode.overlayWidth) + newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _aspectWidth; + if (_aspectHeight != _videoMode.overlayHeight) + newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _aspectHeight; + } else { + if (_aspectWidth != _videoMode.screenWidth) + newEvent.mouse.x = newEvent.mouse.x * _videoMode.screenWidth / _aspectWidth; + if (_aspectHeight != _videoMode.screenHeight) + newEvent.mouse.y = newEvent.mouse.y * _videoMode.screenHeight / _aspectHeight; + } + } + + g_system->getEventManager()->pushEvent(newEvent); + } +} + +bool OpenGLGraphicsManager::notifyEvent(const Common::Event &event) { + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + if (!event.synthetic) + setMousePos(event.mouse.x, event.mouse.y); + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_WHEELUP: + case Common::EVENT_WHEELDOWN: + case Common::EVENT_MBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + case Common::EVENT_MBUTTONUP: + adjustMouseEvent(event); + return !event.synthetic; + + default: + break; + } + + return false; +} + +bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { + int width = _videoMode.hardwareWidth; + int height = _videoMode.hardwareHeight; + + // Allocate space for screenshot + uint8 *pixels = new uint8[width * height * 3]; + + // Get pixel data from opengl buffer + 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(); + } + + // Open file + Common::DumpFile out; + out.open(filename); + + // Write BMP header + out.writeByte('B'); + out.writeByte('M'); + out.writeUint32LE(height * width * 3 + 52); + out.writeUint32LE(0); + out.writeUint32LE(52); + out.writeUint32LE(40); + out.writeUint32LE(width); + out.writeUint32LE(height); + out.writeUint16LE(1); + out.writeUint16LE(24); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + + // Write pixel data to BMP + out.write(pixels, width * height * 3); + + delete[] pixels; + + return true; +} + +#endif diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h new file mode 100644 index 0000000000..166009c04d --- /dev/null +++ b/backends/graphics/opengl/opengl-graphics.h @@ -0,0 +1,276 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_H +#define BACKENDS_GRAPHICS_OPENGL_H + +#include "backends/graphics/opengl/gltexture.h" +#include "backends/graphics/graphics.h" +#include "common/events.h" + +// Uncomment this to enable the 'on screen display' code. +#define USE_OSD 1 + +namespace OpenGL { + +enum { + GFX_NORMAL = 0, + GFX_DOUBLESIZE = 1, + GFX_TRIPLESIZE = 2 +}; + +} + +/** + * Open GL graphics manager + */ +class OpenGLGraphicsManager : public GraphicsManager, public Common::EventObserver { +public: + OpenGLGraphicsManager(); + virtual ~OpenGLGraphicsManager(); + + 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(); +#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 int16 getWidth(); + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + virtual void copyRectToScreen(const byte *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 clearFocusRectangle(); + + virtual void showOverlay(); + virtual void hideOverlay(); + virtual Graphics::PixelFormat getOverlayFormat() const; + virtual void clearOverlay(); + virtual void grabOverlay(OverlayColor *buf, int pitch); + virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); + virtual int16 getOverlayHeight(); + virtual int16 getOverlayWidth(); + + virtual bool showMouse(bool visible); + virtual void warpMouse(int x, int y); + virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL); + virtual void setCursorPalette(const byte *colors, uint start, uint num); + virtual void disableCursorPalette(bool disable); + + virtual void displayMessageOnOSD(const char *msg); + + // Override from Common::EventObserver + bool notifyEvent(const Common::Event &event); + +protected: + + virtual void initGL(); + virtual void loadTextures(); + + // + // GFX and video + // + enum { + kTransactionNone = 0, + kTransactionActive = 1, + kTransactionRollback = 2 + }; + + struct TransactionDetails { + bool sizeChanged; + bool needHotswap; + bool needUpdatescreen; + bool newContext; + bool filterChanged; +#ifdef USE_RGB_COLOR + bool formatChanged; +#endif + }; + TransactionDetails _transactionDetails; + int _transactionMode; + + enum { + kAspectRatioNone, + kAspectRatioConserve, + kAspectRatio4_3, + kAspectRatio16_9, + kAspectRatio16_10 + }; + + struct VideoState { + bool setup; + + bool fullscreen; + int activeFullscreenMode; + int aspectRatioCorrection; + + int mode; + int scaleFactor; + bool antialiasing; + + int screenWidth, screenHeight; + int overlayWidth, overlayHeight; + int hardwareWidth, hardwareHeight; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat format; +#endif + }; + VideoState _videoMode, _oldVideoMode; + + virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &type); + + virtual void internUpdateScreen(); + virtual bool loadGFXMode(); + virtual void unloadGFXMode(); + + virtual void setScale(int newScale); + + int _aspectX; + int _aspectY; + int _aspectWidth; + int _aspectHeight; + + virtual void setAspectRatioCorrection(int mode); + virtual void refreshAspectRatio(); + virtual Common::String getAspectRatioName(); + virtual float getAspectRatio(); + + bool _formatBGR; + + // + // Game screen + // + GLTexture* _gameTexture; + Graphics::Surface _screenData; + int _screenChangeCount; + bool _screenNeedsRedraw; + Common::Rect _screenDirtyRect; + +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _screenFormat; +#endif + byte *_gamePalette; + + virtual void refreshGameScreen(); + + // Shake mode + int _shakePos; + + // + // Overlay + // + GLTexture* _overlayTexture; + Graphics::Surface _overlayData; + Graphics::PixelFormat _overlayFormat; + bool _overlayVisible; + bool _overlayNeedsRedraw; + Common::Rect _overlayDirtyRect; + + virtual void refreshOverlay(); + + // + // Mouse + // + struct MousePos { + // The mouse position, using either virtual (game) or real + // (overlay) coordinates. + int16 x, y; + + // The size and hotspot of the original cursor image. + int16 w, h; + int16 hotX, hotY; + + // The size and hotspot of the scaled cursor, in real + // coordinates. + int16 rW, rH; + int16 rHotX, rHotY; + + // The size and hotspot of the scaled cursor, in game + // coordinates. + int16 vW, vH; + int16 vHotX, vHotY; + + 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) {} + }; + + GLTexture* _cursorTexture; + Graphics::Surface _cursorData; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _cursorFormat; +#endif + byte *_cursorPalette; + bool _cursorPaletteDisabled; + MousePos _cursorState; + bool _cursorVisible; + uint32 _cursorKeyColor; + int _cursorTargetScale; + bool _cursorNeedsRedraw; + + virtual void refreshCursor(); + virtual void refreshCursorScale(); + virtual void adjustMouseEvent(const Common::Event &event); + virtual void setMousePos(int x, int y); + + // + // Misc + // + virtual bool saveScreenshot(const char *filename); + +#ifdef USE_OSD + GLTexture *_osdTexture; + Graphics::Surface _osdSurface; + uint8 _osdAlpha; + uint32 _osdFadeStartTime; + enum { + kOSDFadeOutDelay = 2 * 1000, + kOSDFadeOutDuration = 500, + kOSDInitialAlpha = 80 + }; +#endif +}; + +#endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp new file mode 100644 index 0000000000..4dac109a01 --- /dev/null +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -0,0 +1,452 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef USE_OPENGL + +#include "backends/graphics/openglsdl/openglsdl-graphics.h" +#include "backends/platform/sdl/sdl.h" + +OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager() + : + _hwscreen(0), + _screenResized(false) { + + if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + SDL_ShowCursor(SDL_DISABLE); +} + +OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { + +} + + +bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { + return + (f == OSystem::kFeatureFullscreenMode) || + (f == OSystem::kFeatureIconifyWindow) || + OpenGLGraphicsManager::hasFeature(f); +} + +void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + setFullscreenMode(enable); + break; + case OSystem::kFeatureIconifyWindow: + if (enable) + SDL_WM_IconifyWindow(); + break; + default: + OpenGLGraphicsManager::setFeatureState(f, enable); + } +} + +#ifdef USE_RGB_COLOR + +const Graphics::PixelFormat RGBList[] = { +#if defined(ENABLE_32BIT) + Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), // RGBA8888 + 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, 0, 10, 5, 0, 0), // RGB555 + Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444 +}; + +Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const { + static Common::List<Graphics::PixelFormat> list; + static bool inited = false; + + if (inited) + return list; + + int listLength = ARRAYSIZE(RGBList); + + 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 MacOSX SDL not providing an accurate Aloss value. + if (_hwscreen->format->Amask == 0) + format.aLoss = 8; + + // Push it first, as the prefered format. + for (int i = 0; i < listLength; i++) { + if (RGBList[i] == format) { + list.push_back(format); + break; + } + } + + // Mark that we don't need to do this any more. + inited = true; + } + + for (int i = 0; i < listLength; i++) { + if (inited && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) + continue; + if (RGBList[i] != format) + list.push_back(RGBList[i]); + } + list.push_back(Graphics::PixelFormat::createFormatCLUT8()); + return list; +} + +#endif + +void OpenGLSdlGraphicsManager::warpMouse(int x, int y) { + if (_cursorState.x != x || _cursorState.y != y) { + if (!_overlayVisible) + SDL_WarpMouse(x * _videoMode.scaleFactor, y * _videoMode.scaleFactor); + else + SDL_WarpMouse(x, y); + + setMousePos(x, y); + } +} + + +// +// Intern +// + +bool OpenGLSdlGraphicsManager::loadGFXMode() { + _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; + _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; + + // If the screen was resized, do not change its size + if (!_screenResized) { + _videoMode.hardwareWidth = _videoMode.overlayWidth; + _videoMode.hardwareHeight = _videoMode.overlayHeight; + + float screenAspectRatio = (float)_videoMode.screenWidth / _videoMode.screenHeight; + float desiredAspectRatio = getAspectRatio(); + + // Do not downscale dimensions, only enlarge them if needed + if (screenAspectRatio > desiredAspectRatio) + _videoMode.hardwareHeight = (int)(_videoMode.overlayWidth / desiredAspectRatio + 0.5f); + else if (screenAspectRatio < desiredAspectRatio) + _videoMode.hardwareWidth = (int)(_videoMode.overlayHeight * desiredAspectRatio + 0.5f); + + // Only adjust the overlay height if it is bigger than original one. If + // the width is modified it can break the overlay. + if (_videoMode.hardwareHeight > _videoMode.overlayHeight) + _videoMode.overlayHeight = _videoMode.hardwareHeight; + } + + _screenResized = false; + + // 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); + + // Find the best mode for fullscreen + if (_videoMode.fullscreen) { + SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL); + + if (_videoMode.activeFullscreenMode == -1) { + 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++) { + if (mode->w < _videoMode.hardwareWidth) + continue; + if (mode->h < _videoMode.hardwareHeight) + continue; + + uint metric = mode->w * mode->h - _videoMode.hardwareWidth * _videoMode.hardwareHeight; + if (metric > bestMetric) + continue; + + bestMode = mode; + bestMetric = metric; + bestModeIndex = i; + } + + if (bestMode) { + // If there is a suiting mode, use it + _videoMode.hardwareWidth = bestMode->w; + _videoMode.hardwareHeight = bestMode->h; + + _videoMode.activeFullscreenMode = bestModeIndex; + } + } else { + if (!availableModes[_videoMode.activeFullscreenMode]) + _videoMode.activeFullscreenMode = 0; + + if (availableModes[_videoMode.activeFullscreenMode]) { + _videoMode.hardwareWidth = availableModes[_videoMode.activeFullscreenMode]->w; + _videoMode.hardwareHeight = availableModes[_videoMode.activeFullscreenMode]->h; + } else { + return false; + } + } + } + + // If changing to any fullscreen mode or from fullscreen, + // the OpenGL context is destroyed + if (_oldVideoMode.fullscreen || _videoMode.fullscreen) + _transactionDetails.newContext = true; + + // Create our window + _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 32, + _videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_OPENGL) : (SDL_OPENGL | SDL_RESIZABLE) + ); + 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; + } + + // Check if the screen is BGR format + _formatBGR = _hwscreen->format->Rshift != 0; + + // Call and return parent implementation of this method + return OpenGLGraphicsManager::loadGFXMode(); +} + +void OpenGLSdlGraphicsManager::unloadGFXMode() { + if (_hwscreen) { + SDL_FreeSurface(_hwscreen); + _hwscreen = NULL; + } +} + +void OpenGLSdlGraphicsManager::internUpdateScreen() { + // Call to parent implementation of this method + OpenGLGraphicsManager::internUpdateScreen(); + + // Swap OpenGL buffers + SDL_GL_SwapBuffers(); +} + +bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { + + // Ctrl-Alt-a toggles aspect ratio correction + if (key == 'a') { + beginGFXTransaction(); + setAspectRatioCorrection(-1); + endGFXTransaction(); +#ifdef USE_OSD + char buffer[128]; + sprintf(buffer, "Current aspect ratio mode: %s\n%d x %d -> %d x %d", + getAspectRatioName().c_str(), + _videoMode.screenWidth, _videoMode.screenHeight, + _hwscreen->w, _hwscreen->h + ); + displayMessageOnOSD(buffer); +#endif + internUpdateScreen(); + return true; + } + + // Ctrl-Alt-f toggles antialiasing + if (key == 'f') { + beginGFXTransaction(); + _videoMode.antialiasing = !_videoMode.antialiasing; + _transactionDetails.filterChanged = true; + endGFXTransaction(); +#ifdef USE_OSD + if (_videoMode.antialiasing) + displayMessageOnOSD("Active filter mode: Linear"); + else + displayMessageOnOSD("Active filter mode: Nearest"); +#endif + return true; + } + + SDLKey sdlKey = (SDLKey)key; + + // Increase/decrease the scale factor + if (sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS || + sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS) { + int factor = _videoMode.scaleFactor; + factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1; + if (0 < factor && factor < 4) { + beginGFXTransaction(); + setScale(factor); + endGFXTransaction(); +#ifdef USE_OSD + const char *newScalerName = 0; + const OSystem::GraphicsMode *g = getSupportedGraphicsModes(); + while (g->name) { + if (g->id == _videoMode.mode) { + newScalerName = g->description; + break; + } + g++; + } + if (newScalerName) { + char buffer[128]; + sprintf(buffer, "Active graphics mode: %s\n%d x %d -> %d x %d", + newScalerName, + _videoMode.screenWidth, _videoMode.screenHeight, + _hwscreen->w, _hwscreen->h + ); + displayMessageOnOSD(buffer); + } +#endif + return true; + } + } + return false; +} + +void OpenGLSdlGraphicsManager::setFullscreenMode(bool enable) { + if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable && + _oldVideoMode.activeFullscreenMode == _videoMode.activeFullscreenMode) + return; + + if (_transactionMode == kTransactionActive) { + _videoMode.fullscreen = enable; + _transactionDetails.needHotswap = true; + } +} + +bool OpenGLSdlGraphicsManager::isScalerHotkey(const Common::Event &event) { + if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { + const bool isScaleKey = (event.kbd.keycode == Common::KEYCODE_EQUALS || 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); + + return (isScaleKey || event.kbd.keycode == 'a' || event.kbd.keycode == 'f'); + } + return false; +} + +void OpenGLSdlGraphicsManager::toggleFullScreen(bool loop) { + beginGFXTransaction(); + if (_videoMode.fullscreen && loop) { + _videoMode.activeFullscreenMode += 1; + setFullscreenMode(true); + } else { + _videoMode.activeFullscreenMode = -1; + setFullscreenMode(!_videoMode.fullscreen); + } + endGFXTransaction(); +#ifdef USE_OSD + char buffer[128]; + if (_videoMode.fullscreen) + sprintf(buffer, "Fullscreen mode\n%d x %d", + _hwscreen->w, _hwscreen->h + ); + else + sprintf(buffer, "Windowed mode\n%d x %d", + _hwscreen->w, _hwscreen->h + ); + displayMessageOnOSD(buffer); +#endif +} + +bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { + switch ((int)event.type) { + case Common::EVENT_KEYDOWN: + // Alt-Return and Alt-Enter toggle full screen mode + if (event.kbd.hasFlags(Common::KBD_ALT) && + (event.kbd.keycode == Common::KEYCODE_RETURN || + event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER)) { + toggleFullScreen(false); + return true; + } + + // Ctrl-Alt-Return and Ctrl-Alt-Enter switches between full screen modes + if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT) && + (event.kbd.keycode == Common::KEYCODE_RETURN || + event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER)) { + toggleFullScreen(true); + return true; + } + + // Alt-S: Create a screenshot + if (event.kbd.hasFlags(Common::KBD_ALT) && event.kbd.keycode == 's') { + char filename[20]; + + for (int n = 0;; n++) { + SDL_RWops *file; + + sprintf(filename, "scummvm%05d.bmp", n); + file = SDL_RWFromFile(filename, "r"); + if (!file) + break; + SDL_RWclose(file); + } + if (saveScreenshot(filename)) + printf("Saved '%s'\n", filename); + else + printf("Could not save screenshot!\n"); + return true; + } + + // Ctrl-Alt-<key> will change the GFX mode + if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) { + if (handleScalerHotkeys(event.kbd.keycode)) + return true; + } + case Common::EVENT_KEYUP: + return isScalerHotkey(event); + /*case OSystem_SDL::kSdlEventExpose: + break;*/ + // HACK: Handle special SDL event + case OSystem_SDL::kSdlEventResize: + beginGFXTransaction(); + // Set the new screen size. It is saved on the mouse event as part of HACK, + // there is no common resize event + _videoMode.hardwareWidth = event.mouse.x; + _videoMode.hardwareHeight = event.mouse.y; + _screenResized = true; + _transactionDetails.sizeChanged = true; + // The OpenGL context is not always destroyed during resizing, + // however it is better to waste some time recreating it than + // getting a blank screen + _transactionDetails.newContext = true; + endGFXTransaction(); + return true; + + default: + break; + } + + return OpenGLGraphicsManager::notifyEvent(event); +} + +#endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h new file mode 100644 index 0000000000..2db9c2dbe6 --- /dev/null +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -0,0 +1,74 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGLSDL_H +#define BACKENDS_GRAPHICS_OPENGLSDL_H + +#include <SDL.h> +#if defined(ARRAYSIZE) && !defined(_WINDOWS_) +#undef ARRAYSIZE +#endif +#include <SDL_opengl.h> + +#include "backends/graphics/opengl/opengl-graphics.h" + +/** + * SDL OpenGL graphics manager + */ +class OpenGLSdlGraphicsManager : public OpenGLGraphicsManager { +public: + OpenGLSdlGraphicsManager(); + virtual ~OpenGLSdlGraphicsManager(); + + virtual bool hasFeature(OSystem::Feature f); + virtual void setFeatureState(OSystem::Feature f, bool enable); + +#ifdef USE_RGB_COLOR + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; +#endif + + virtual void warpMouse(int x, int y); + + virtual bool notifyEvent(const Common::Event &event); + +protected: + virtual void internUpdateScreen(); + + virtual bool loadGFXMode(); + virtual void unloadGFXMode(); + + virtual void setFullscreenMode(bool enable); + + virtual bool handleScalerHotkeys(Common::KeyCode key); + virtual bool isScalerHotkey(const Common::Event &event); + virtual void toggleFullScreen(bool loop); + + // Hardware screen + SDL_Surface *_hwscreen; + + bool _screenResized; +}; + +#endif diff --git a/backends/platform/sdl/graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index a97a153f3c..5eb6e6e693 100644 --- a/backends/platform/sdl/graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -23,7 +23,12 @@ * */ +#if defined(WIN32) || defined(UNIX) || defined(MACOSX) + +#include "backends/graphics/sdl/sdl-graphics.h" +#include "backends/events/sdl/sdl-events.h" #include "backends/platform/sdl/sdl.h" +#include "common/config-manager.h" #include "common/mutex.h" #include "common/translation.h" #include "common/util.h" @@ -85,15 +90,173 @@ static const int s_gfxModeSwitchTable[][4] = { static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY); #endif -const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const { +AspectRatio::AspectRatio(int w, int h) { + // TODO : Validation and so on... + // Currently, we just ensure the program don't instantiate non-supported aspect ratios + _kw = w; + _kh = h; +} + +#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS) +static AspectRatio getDesiredAspectRatio() { + const size_t AR_COUNT = 4; + const char *desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" }; + const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) }; + + //TODO : We could parse an arbitrary string, if we code enough proper validation + Common::String desiredAspectRatio = ConfMan.get("desired_screen_aspect_ratio"); + + for (size_t i = 0; i < AR_COUNT; i++) { + assert(desiredAspectRatioAsStrings[i] != NULL); + + if (!scumm_stricmp(desiredAspectRatio.c_str(), desiredAspectRatioAsStrings[i])) { + return desiredAspectRatios[i]; + } + } + // TODO : Report a warning + return AspectRatio(0, 0); +} +#endif + +SdlGraphicsManager::SdlGraphicsManager() + : +#ifdef USE_OSD + _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0), +#endif + _hwscreen(0), _screen(0), _tmpscreen(0), +#ifdef USE_RGB_COLOR + _screenFormat(Graphics::PixelFormat::createFormatCLUT8()), + _cursorFormat(Graphics::PixelFormat::createFormatCLUT8()), +#endif + _overlayVisible(false), + _overlayscreen(0), _tmpscreen2(0), + _scalerProc(0), _screenChangeCount(0), + _mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0), + _mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true), + _currentShakePos(0), _newShakePos(0), + _paletteDirtyStart(0), _paletteDirtyEnd(0), + _screenIsLocked(false), + _graphicsMutex(0), _transactionMode(kTransactionNone) { + + if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + // allocate palette storage + _currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); + _cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); + + _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; + + memset(&_mouseCurState, 0, sizeof(_mouseCurState)); + + _graphicsMutex = g_system->createMutex(); + +#ifdef _WIN32_WCE + if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) { + SDL_VideoInit("windib", 0); + sdlFlags ^= SDL_INIT_VIDEO; + } +#endif + + SDL_ShowCursor(SDL_DISABLE); + + memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); + memset(&_videoMode, 0, sizeof(_videoMode)); + memset(&_transactionDetails, 0, sizeof(_transactionDetails)); + +#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS) + _videoMode.mode = GFX_DOUBLESIZE; + _videoMode.scaleFactor = 2; + _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); + _videoMode.desiredAspectRatio = getDesiredAspectRatio(); + _scalerProc = Normal2x; +#else // for small screen platforms + _videoMode.mode = GFX_NORMAL; + _videoMode.scaleFactor = 1; + _videoMode.aspectRatioCorrection = false; + _scalerProc = Normal1x; +#endif + _scalerType = 0; + +#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) + _videoMode.fullscreen = ConfMan.getBool("fullscreen"); +#else + _videoMode.fullscreen = true; +#endif + + // Register the graphics manager as a event observer + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false); +} + +SdlGraphicsManager::~SdlGraphicsManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher() != NULL) + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + + unloadGFXMode(); + g_system->deleteMutex(_graphicsMutex); + + free(_currentPalette); + free(_cursorPalette); + free(_mouseData); +} + +bool SdlGraphicsManager::hasFeature(OSystem::Feature f) { + return + (f == OSystem::kFeatureFullscreenMode) || + (f == OSystem::kFeatureAspectRatioCorrection) || + (f == OSystem::kFeatureCursorHasPalette) || + (f == OSystem::kFeatureIconifyWindow); +} + +void SdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + setFullscreenMode(enable); + break; + case OSystem::kFeatureAspectRatioCorrection: + setAspectRatioCorrection(enable); + break; + case OSystem::kFeatureIconifyWindow: + if (enable) + SDL_WM_IconifyWindow(); + break; + default: + break; + } +} + +bool SdlGraphicsManager::getFeatureState(OSystem::Feature f) { + assert (_transactionMode == kTransactionNone); + + switch (f) { + case OSystem::kFeatureFullscreenMode: + return _videoMode.fullscreen; + case OSystem::kFeatureAspectRatioCorrection: + return _videoMode.aspectRatioCorrection; + default: + return false; + } +} + +const OSystem::GraphicsMode *SdlGraphicsManager::supportedGraphicsModes() { return s_supportedGraphicsModes; } -int OSystem_SDL::getDefaultGraphicsMode() const { +const OSystem::GraphicsMode *SdlGraphicsManager::getSupportedGraphicsModes() const { + return s_supportedGraphicsModes; +} + +int SdlGraphicsManager::getDefaultGraphicsMode() const { return GFX_DOUBLESIZE; } -void OSystem_SDL::beginGFXTransaction() { +void SdlGraphicsManager::resetGraphicsScale() { + setGraphicsMode(s_gfxModeSwitchTable[_scalerType][0]); +} + +void SdlGraphicsManager::beginGFXTransaction() { assert(_transactionMode == kTransactionNone); _transactionMode = kTransactionActive; @@ -111,34 +274,34 @@ void OSystem_SDL::beginGFXTransaction() { _oldVideoMode = _videoMode; } -OSystem::TransactionError OSystem_SDL::endGFXTransaction() { - int errors = kTransactionSuccess; +OSystem::TransactionError SdlGraphicsManager::endGFXTransaction() { + int errors = OSystem::kTransactionSuccess; assert(_transactionMode != kTransactionNone); if (_transactionMode == kTransactionRollback) { if (_videoMode.fullscreen != _oldVideoMode.fullscreen) { - errors |= kTransactionFullscreenFailed; + errors |= OSystem::kTransactionFullscreenFailed; _videoMode.fullscreen = _oldVideoMode.fullscreen; } else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) { - errors |= kTransactionAspectRatioFailed; + errors |= OSystem::kTransactionAspectRatioFailed; _videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection; } else if (_videoMode.mode != _oldVideoMode.mode) { - errors |= kTransactionModeSwitchFailed; + errors |= OSystem::kTransactionModeSwitchFailed; _videoMode.mode = _oldVideoMode.mode; _videoMode.scaleFactor = _oldVideoMode.scaleFactor; #ifdef USE_RGB_COLOR } else if (_videoMode.format != _oldVideoMode.format) { - errors |= kTransactionFormatNotSupported; + errors |= OSystem::kTransactionFormatNotSupported; _videoMode.format = _oldVideoMode.format; _screenFormat = _videoMode.format; #endif } else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) { - errors |= kTransactionSizeChangeFailed; + errors |= OSystem::kTransactionSizeChangeFailed; _videoMode.screenWidth = _oldVideoMode.screenWidth; _videoMode.screenHeight = _oldVideoMode.screenHeight; @@ -150,7 +313,7 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction() { _videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection && _videoMode.mode == _oldVideoMode.mode && _videoMode.screenWidth == _oldVideoMode.screenWidth && - _videoMode.screenHeight == _oldVideoMode.screenHeight) { + _videoMode.screenHeight == _oldVideoMode.screenHeight) { // Our new video mode would now be exactly the same as the // old one. Since we still can not assume SDL_SetVideoMode @@ -176,7 +339,6 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction() { clearOverlay(); _videoMode.setup = true; - _modeChanged = true; // OSystem_SDL::pollEvent used to update the screen change count, // but actually it gives problems when a video mode was changed // but OSystem_SDL::pollEvent was not called. This for example @@ -193,7 +355,6 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction() { } } else { _videoMode.setup = true; - _modeChanged = true; // OSystem_SDL::pollEvent used to update the screen change count, // but actually it gives problems when a video mode was changed // but OSystem_SDL::pollEvent was not called. This for example @@ -210,17 +371,16 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction() { } _transactionMode = kTransactionNone; - return (TransactionError)errors; + return (OSystem::TransactionError)errors; } #ifdef USE_RGB_COLOR - -Common::List<Graphics::PixelFormat> OSystem_SDL::getSupportedFormats() const { +Common::List<Graphics::PixelFormat> SdlGraphicsManager::getSupportedFormats() const { assert(!_supportedFormats.empty()); return _supportedFormats; } -void OSystem_SDL::detectSupportedFormats() { +void SdlGraphicsManager::detectSupportedFormats() { // Clear old list _supportedFormats.clear(); @@ -302,10 +462,9 @@ void OSystem_SDL::detectSupportedFormats() { // Finally, we always supposed 8 bit palette graphics _supportedFormats.push_back(Graphics::PixelFormat::createFormatCLUT8()); } - #endif -bool OSystem_SDL::setGraphicsMode(int mode) { +bool SdlGraphicsManager::setGraphicsMode(int mode) { Common::StackLock lock(_graphicsMutex); assert(_transactionMode == kTransactionActive); @@ -375,7 +534,7 @@ bool OSystem_SDL::setGraphicsMode(int mode) { return true; } -void OSystem_SDL::setGraphicsModeIntern() { +void SdlGraphicsManager::setGraphicsModeIntern() { Common::StackLock lock(_graphicsMutex); ScalerProc *newScalerProc = 0; @@ -448,12 +607,12 @@ void OSystem_SDL::setGraphicsModeIntern() { blitCursor(); } -int OSystem_SDL::getGraphicsMode() const { +int SdlGraphicsManager::getGraphicsMode() const { assert (_transactionMode == kTransactionNone); return _videoMode.mode; } -void OSystem_SDL::initSize(uint w, uint h, const Graphics::PixelFormat *format) { +void SdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) { assert(_transactionMode == kTransactionActive); #ifdef USE_RGB_COLOR @@ -483,7 +642,7 @@ void OSystem_SDL::initSize(uint w, uint h, const Graphics::PixelFormat *format) _transactionDetails.sizeChanged = true; } -int OSystem_SDL::effectiveScreenHeight() const { +int SdlGraphicsManager::effectiveScreenHeight() const { return _videoMode.scaleFactor * (_videoMode.aspectRatioCorrection ? real2Aspect(_videoMode.screenHeight) @@ -533,8 +692,7 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w height = bestMode->h; } -bool OSystem_SDL::loadGFXMode() { - assert(_inited); +bool SdlGraphicsManager::loadGFXMode() { _forceFull = true; #if !defined(__MAEMO__) && !defined(GP2XWIZ) && !defined(LINUXMOTO) @@ -594,7 +752,7 @@ bool OSystem_SDL::loadGFXMode() { if (!_oldVideoMode.setup) { warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError()); - quit(); + g_system->quit(); } else { return false; } @@ -661,11 +819,9 @@ bool OSystem_SDL::loadGFXMode() { SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey); #endif - // keyboard cursor control, some other better place for it? - _km.x_max = _videoMode.screenWidth * _videoMode.scaleFactor - 1; - _km.y_max = effectiveScreenHeight() - 1; - _km.delay_time = 25; - _km.last_time = 0; + ((SdlEventManager *)g_system->getEventManager())->resetKeyboadEmulation( + _videoMode.screenWidth * _videoMode.scaleFactor - 1, + effectiveScreenHeight() - 1); // Distinguish 555 and 565 mode if (_hwscreen->format->Rmask == 0x7C00) @@ -676,7 +832,7 @@ bool OSystem_SDL::loadGFXMode() { return true; } -void OSystem_SDL::unloadGFXMode() { +void SdlGraphicsManager::unloadGFXMode() { if (_screen) { SDL_FreeSurface(_screen); _screen = NULL; @@ -711,7 +867,7 @@ void OSystem_SDL::unloadGFXMode() { DestroyScalers(); } -bool OSystem_SDL::hotswapGFXMode() { +bool SdlGraphicsManager::hotswapGFXMode() { if (!_screen) return false; @@ -763,7 +919,7 @@ bool OSystem_SDL::hotswapGFXMode() { return true; } -void OSystem_SDL::updateScreen() { +void SdlGraphicsManager::updateScreen() { assert (_transactionMode == kTransactionNone); Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends @@ -771,13 +927,14 @@ void OSystem_SDL::updateScreen() { internUpdateScreen(); } -void OSystem_SDL::internUpdateScreen() { +void SdlGraphicsManager::internUpdateScreen() { SDL_Surface *srcSurf, *origSurf; int height, width; ScalerProc *scalerProc; int scale1; -#if defined (DEBUG) && ! defined(_WIN32_WCE) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) + // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) +#if defined (DEBUG) && !defined(WIN32) && !defined(_WIN32_WCE) assert(_hwscreen != NULL); assert(_hwscreen->map->sw_data != NULL); #endif @@ -901,7 +1058,7 @@ void OSystem_SDL::internUpdateScreen() { assert(scalerProc != NULL); scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); + (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); } r->x = rx1; @@ -940,14 +1097,14 @@ void OSystem_SDL::internUpdateScreen() { _mouseNeedsRedraw = false; } -bool OSystem_SDL::saveScreenshot(const char *filename) { +bool SdlGraphicsManager::saveScreenshot(const char *filename) { assert(_hwscreen != NULL); Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends return SDL_SaveBMP(_hwscreen, filename) == 0; } -void OSystem_SDL::setFullscreenMode(bool enable) { +void SdlGraphicsManager::setFullscreenMode(bool enable) { Common::StackLock lock(_graphicsMutex); if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable) @@ -959,7 +1116,7 @@ void OSystem_SDL::setFullscreenMode(bool enable) { } } -void OSystem_SDL::setAspectRatioCorrection(bool enable) { +void SdlGraphicsManager::setAspectRatioCorrection(bool enable) { Common::StackLock lock(_graphicsMutex); if (_oldVideoMode.setup && _oldVideoMode.aspectRatioCorrection == enable) @@ -971,12 +1128,12 @@ void OSystem_SDL::setAspectRatioCorrection(bool enable) { } } -void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) { +void SdlGraphicsManager::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) { assert (_transactionMode == kTransactionNone); assert(src); if (_screen == NULL) { - warning("OSystem_SDL::copyRectToScreen: _screen == NULL"); + warning("SdlGraphicsManager::copyRectToScreen: _screen == NULL"); return; } @@ -1021,11 +1178,11 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int SDL_UnlockSurface(_screen); } -Graphics::Surface *OSystem_SDL::lockScreen() { +Graphics::Surface *SdlGraphicsManager::lockScreen() { assert (_transactionMode == kTransactionNone); // Lock the graphics mutex - lockMutex(_graphicsMutex); + g_system->lockMutex(_graphicsMutex); // paranoia check assert(!_screenIsLocked); @@ -1048,7 +1205,7 @@ Graphics::Surface *OSystem_SDL::lockScreen() { return &_framebuffer; } -void OSystem_SDL::unlockScreen() { +void SdlGraphicsManager::unlockScreen() { assert (_transactionMode == kTransactionNone); // paranoia check @@ -1062,10 +1219,17 @@ void OSystem_SDL::unlockScreen() { _forceFull = true; // Finally unlock the graphics mutex - unlockMutex(_graphicsMutex); + g_system->unlockMutex(_graphicsMutex); +} + +void SdlGraphicsManager::fillScreen(uint32 col) { + Graphics::Surface *screen = lockScreen(); + if (screen && screen->pixels) + memset(screen->pixels, col, screen->h * screen->pitch); + unlockScreen(); } -void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) { +void SdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) { if (_forceFull) return; @@ -1133,15 +1297,15 @@ void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) } } -int16 OSystem_SDL::getHeight() { +int16 SdlGraphicsManager::getHeight() { return _videoMode.screenHeight; } -int16 OSystem_SDL::getWidth() { +int16 SdlGraphicsManager::getWidth() { return _videoMode.screenWidth; } -void OSystem_SDL::setPalette(const byte *colors, uint start, uint num) { +void SdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) { assert(colors); #ifdef USE_RGB_COLOR @@ -1153,7 +1317,7 @@ void OSystem_SDL::setPalette(const byte *colors, uint start, uint num) { // But it could indicate a programming error, so let's warn about it. if (!_screen) - warning("OSystem_SDL::setPalette: _screen == NULL"); + warning("SdlGraphicsManager::setPalette: _screen == NULL"); const byte *b = colors; uint i; @@ -1176,7 +1340,7 @@ void OSystem_SDL::setPalette(const byte *colors, uint start, uint num) { blitCursor(); } -void OSystem_SDL::grabPalette(byte *colors, uint start, uint num) { +void SdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) { assert(colors); #ifdef USE_RGB_COLOR @@ -1193,7 +1357,7 @@ void OSystem_SDL::grabPalette(byte *colors, uint start, uint num) { } } -void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) { +void SdlGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { assert(colors); const byte *b = colors; uint i; @@ -1209,8 +1373,12 @@ void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) { blitCursor(); } +void SdlGraphicsManager::disableCursorPalette(bool disable) { + _cursorPaletteDisabled = disable; + blitCursor(); +} -void OSystem_SDL::setShakePos(int shake_pos) { +void SdlGraphicsManager::setShakePos(int shake_pos) { assert (_transactionMode == kTransactionNone); _newShakePos = shake_pos; @@ -1221,7 +1389,7 @@ void OSystem_SDL::setShakePos(int shake_pos) { #pragma mark --- Overlays --- #pragma mark - -void OSystem_SDL::showOverlay() { +void SdlGraphicsManager::showOverlay() { assert (_transactionMode == kTransactionNone); int x, y; @@ -1244,7 +1412,7 @@ void OSystem_SDL::showOverlay() { clearOverlay(); } -void OSystem_SDL::hideOverlay() { +void SdlGraphicsManager::hideOverlay() { assert (_transactionMode == kTransactionNone); if (!_overlayVisible) @@ -1268,7 +1436,7 @@ void OSystem_SDL::hideOverlay() { _forceFull = true; } -void OSystem_SDL::clearOverlay() { +void SdlGraphicsManager::clearOverlay() { //assert (_transactionMode == kTransactionNone); Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends @@ -1301,7 +1469,7 @@ void OSystem_SDL::clearOverlay() { _forceFull = true; } -void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) { +void SdlGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) { assert (_transactionMode == kTransactionNone); if (_overlayscreen == NULL) @@ -1321,7 +1489,7 @@ void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) { SDL_UnlockSurface(_overlayscreen); } -void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { +void SdlGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { assert (_transactionMode == kTransactionNone); if (_overlayscreen == NULL) @@ -1371,7 +1539,7 @@ void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, i #pragma mark --- Mouse --- #pragma mark - -bool OSystem_SDL::showMouse(bool visible) { +bool SdlGraphicsManager::showMouse(bool visible) { if (_mouseVisible == visible) return visible; @@ -1382,7 +1550,7 @@ bool OSystem_SDL::showMouse(bool visible) { return last; } -void OSystem_SDL::setMousePos(int x, int y) { +void SdlGraphicsManager::setMousePos(int x, int y) { if (x != _mouseCurState.x || y != _mouseCurState.y) { _mouseNeedsRedraw = true; _mouseCurState.x = x; @@ -1390,7 +1558,7 @@ void OSystem_SDL::setMousePos(int x, int y) { } } -void OSystem_SDL::warpMouse(int x, int y) { +void SdlGraphicsManager::warpMouse(int x, int y) { int y1 = y; // Don't change mouse position, when mouse is outside of our window (in case of windowed mode) @@ -1417,7 +1585,7 @@ void OSystem_SDL::warpMouse(int x, int y) { } } -void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { +void SdlGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { #ifdef USE_RGB_COLOR if (!format) _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); @@ -1474,7 +1642,7 @@ void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, blitCursor(); } -void OSystem_SDL::blitCursor() { +void SdlGraphicsManager::blitCursor() { byte *dstPtr; const byte *srcPtr = _mouseData; #ifdef USE_RGB_COLOR @@ -1665,14 +1833,7 @@ static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height } #endif -void OSystem_SDL::toggleMouseGrab() { - if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) - SDL_WM_GrabInput(SDL_GRAB_ON); - else - SDL_WM_GrabInput(SDL_GRAB_OFF); -} - -void OSystem_SDL::undrawMouse() { +void SdlGraphicsManager::undrawMouse() { const int x = _mouseBackup.x; const int y = _mouseBackup.y; @@ -1685,7 +1846,7 @@ void OSystem_SDL::undrawMouse() { addDirtyRect(x, y - _currentShakePos, _mouseBackup.w, _mouseBackup.h); } -void OSystem_SDL::drawMouse() { +void SdlGraphicsManager::drawMouse() { if (!_mouseVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; @@ -1693,6 +1854,7 @@ void OSystem_SDL::drawMouse() { SDL_Rect dst; int scale; + int width, height; int hotX, hotY; dst.x = _mouseCurState.x; @@ -1700,12 +1862,16 @@ void OSystem_SDL::drawMouse() { if (!_overlayVisible) { scale = _videoMode.scaleFactor; + width = _videoMode.screenWidth; + height = _videoMode.screenHeight; dst.w = _mouseCurState.vW; dst.h = _mouseCurState.vH; hotX = _mouseCurState.vHotX; hotY = _mouseCurState.vHotY; } else { scale = 1; + width = _videoMode.overlayWidth; + height = _videoMode.overlayHeight; dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; hotX = _mouseCurState.rHotX; @@ -1752,7 +1918,7 @@ void OSystem_SDL::drawMouse() { #pragma mark - #ifdef USE_OSD -void OSystem_SDL::displayMessageOnOSD(const char *msg) { +void SdlGraphicsManager::displayMessageOnOSD(const char *msg) { assert (_transactionMode == kTransactionNone); assert(msg); @@ -1826,7 +1992,7 @@ void OSystem_SDL::displayMessageOnOSD(const char *msg) { SDL_UnlockSurface(_osdSurface); // Init the OSD display parameters, and the fade out - _osdAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; + _osdAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; _osdFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay; SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha); @@ -1835,16 +2001,12 @@ void OSystem_SDL::displayMessageOnOSD(const char *msg) { } #endif +bool SdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { -#pragma mark - -#pragma mark --- Misc --- -#pragma mark - - -bool OSystem_SDL::handleScalerHotkeys(const SDL_KeyboardEvent &key) { // Ctrl-Alt-a toggles aspect ratio correction - if (key.keysym.sym == 'a') { + if (key == 'a') { beginGFXTransaction(); - setFeatureState(kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection); + setFeatureState(OSystem::kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection); endGFXTransaction(); #ifdef USE_OSD char buffer[128]; @@ -1866,20 +2028,21 @@ bool OSystem_SDL::handleScalerHotkeys(const SDL_KeyboardEvent &key) { int newMode = -1; int factor = _videoMode.scaleFactor - 1; + SDLKey sdlKey = (SDLKey)key; // Increase/decrease the scale factor - if (key.keysym.sym == SDLK_EQUALS || key.keysym.sym == SDLK_PLUS || key.keysym.sym == SDLK_MINUS || - key.keysym.sym == SDLK_KP_PLUS || key.keysym.sym == SDLK_KP_MINUS) { - factor += (key.keysym.sym == SDLK_MINUS || key.keysym.sym == SDLK_KP_MINUS) ? -1 : +1; + if (sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS || + sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS) { + factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1; if (0 <= factor && factor <= 3) { newMode = s_gfxModeSwitchTable[_scalerType][factor]; } } - const bool isNormalNumber = (SDLK_1 <= key.keysym.sym && key.keysym.sym <= SDLK_9); - const bool isKeypadNumber = (SDLK_KP1 <= key.keysym.sym && key.keysym.sym <= SDLK_KP9); + const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_9); + const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP9); if (isNormalNumber || isKeypadNumber) { - _scalerType = key.keysym.sym - (isNormalNumber ? SDLK_1 : SDLK_KP1); + _scalerType = sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1); if (_scalerType >= ARRAYSIZE(s_gfxModeSwitchTable)) return false; @@ -1897,7 +2060,7 @@ bool OSystem_SDL::handleScalerHotkeys(const SDL_KeyboardEvent &key) { #ifdef USE_OSD if (_osdSurface) { const char *newScalerName = 0; - const GraphicsMode *g = getSupportedGraphicsModes(); + const OSystem::GraphicsMode *g = getSupportedGraphicsModes(); while (g->name) { if (g->id == _videoMode.mode) { newScalerName = g->description; @@ -1924,7 +2087,7 @@ bool OSystem_SDL::handleScalerHotkeys(const SDL_KeyboardEvent &key) { } } -bool OSystem_SDL::isScalerHotkey(const Common::Event &event) { +bool SdlGraphicsManager::isScalerHotkey(const Common::Event &event) { if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { const bool isNormalNumber = (Common::KEYCODE_1 <= event.kbd.keycode && event.kbd.keycode <= Common::KEYCODE_9); const bool isKeypadNumber = (Common::KEYCODE_KP1 <= event.kbd.keycode && event.kbd.keycode <= Common::KEYCODE_KP9); @@ -1940,3 +2103,94 @@ bool OSystem_SDL::isScalerHotkey(const Common::Event &event) { } return false; } + +void SdlGraphicsManager::adjustMouseEvent(const Common::Event &event) { + if (!event.synthetic) { + Common::Event newEvent(event); + newEvent.synthetic = true; + if (!_overlayVisible) { + newEvent.mouse.x /= _videoMode.scaleFactor; + newEvent.mouse.y /= _videoMode.scaleFactor; + if (_videoMode.aspectRatioCorrection) + newEvent.mouse.y = aspect2Real(newEvent.mouse.y); + } + g_system->getEventManager()->pushEvent(newEvent); + } +} + +void SdlGraphicsManager::toggleFullScreen() { + beginGFXTransaction(); + setFullscreenMode(!_videoMode.fullscreen); + endGFXTransaction(); +#ifdef USE_OSD + if (_videoMode.fullscreen) + displayMessageOnOSD("Fullscreen mode"); + else + displayMessageOnOSD("Windowed mode"); +#endif +} + +bool SdlGraphicsManager::notifyEvent(const Common::Event &event) { + switch ((int)event.type) { + case Common::EVENT_KEYDOWN: + // Alt-Return and Alt-Enter toggle full screen mode + if (event.kbd.hasFlags(Common::KBD_ALT) && + (event.kbd.keycode == Common::KEYCODE_RETURN || + event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER)) { + toggleFullScreen(); + return true; + } + + // Alt-S: Create a screenshot + if (event.kbd.hasFlags(Common::KBD_ALT) && event.kbd.keycode == 's') { + char filename[20]; + + for (int n = 0;; n++) { + SDL_RWops *file; + + sprintf(filename, "scummvm%05d.bmp", n); + file = SDL_RWFromFile(filename, "r"); + if (!file) + break; + SDL_RWclose(file); + } + if (saveScreenshot(filename)) + printf("Saved '%s'\n", filename); + else + printf("Could not save screenshot!\n"); + return true; + } + + // Ctrl-Alt-<key> will change the GFX mode + if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) { + if (handleScalerHotkeys(event.kbd.keycode)) + return true; + } + case Common::EVENT_KEYUP: + return isScalerHotkey(event); + case Common::EVENT_MOUSEMOVE: + if (event.synthetic) + setMousePos(event.mouse.x, event.mouse.y); + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_WHEELUP: + case Common::EVENT_WHEELDOWN: + case Common::EVENT_MBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + case Common::EVENT_MBUTTONUP: + adjustMouseEvent(event); + return !event.synthetic; + + // HACK: Handle special SDL event + case OSystem_SDL::kSdlEventExpose: + _forceFull = true; + return false; + default: + break; + } + + return false; +} + +#endif diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h new file mode 100644 index 0000000000..01ae44222a --- /dev/null +++ b/backends/graphics/sdl/sdl-graphics.h @@ -0,0 +1,323 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_SDL_H +#define BACKENDS_GRAPHICS_SDL_H + +#include "backends/graphics/graphics.h" +#include "graphics/scaler.h" +#include "common/events.h" +#include "common/system.h" + +#if defined(__SYMBIAN32__) +#include <esdl\SDL.h> +#else +#include <SDL.h> +#endif + +#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) +// Uncomment this to enable the 'on screen display' code. +#define USE_OSD 1 +#endif + +enum { + GFX_NORMAL = 0, + GFX_DOUBLESIZE = 1, + GFX_TRIPLESIZE = 2, + GFX_2XSAI = 3, + GFX_SUPER2XSAI = 4, + GFX_SUPEREAGLE = 5, + GFX_ADVMAME2X = 6, + GFX_ADVMAME3X = 7, + GFX_HQ2X = 8, + GFX_HQ3X = 9, + GFX_TV2X = 10, + GFX_DOTMATRIX = 11 +}; + + +class AspectRatio { + int _kw, _kh; +public: + AspectRatio() { _kw = _kh = 0; } + AspectRatio(int w, int h); + + bool isAuto() const { return (_kw | _kh) == 0; } + + int kw() const { return _kw; } + int kh() const { return _kh; } +}; + +/** + * SDL graphics manager + */ +class SdlGraphicsManager : public GraphicsManager, public Common::EventObserver { +public: + SdlGraphicsManager(); + virtual ~SdlGraphicsManager(); + + 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(); +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; } + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; +#endif + virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); + virtual int getScreenChangeID() const { return _screenChangeCount; } + + virtual void beginGFXTransaction(); + virtual OSystem::TransactionError endGFXTransaction(); + + virtual int16 getHeight(); + virtual int16 getWidth(); + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + virtual void copyRectToScreen(const byte *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 clearFocusRectangle() {} + + virtual void showOverlay(); + virtual void hideOverlay(); + virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; } + virtual void clearOverlay(); + virtual void grabOverlay(OverlayColor *buf, int pitch); + virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); + virtual int16 getOverlayHeight() { return _videoMode.overlayHeight; } + virtual int16 getOverlayWidth() { return _videoMode.overlayWidth; } + + virtual bool showMouse(bool visible); + virtual void warpMouse(int x, int y); + virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL); + virtual void setCursorPalette(const byte *colors, uint start, uint num); + virtual void disableCursorPalette(bool disable); + +#ifdef USE_OSD + virtual void displayMessageOnOSD(const char *msg); +#endif + + // Override from Common::EventObserver + bool notifyEvent(const Common::Event &event); + +protected: +#ifdef USE_OSD + /** Surface containing the OSD message */ + SDL_Surface *_osdSurface; + /** Transparency level of the OSD */ + uint8 _osdAlpha; + /** When to start the fade out */ + uint32 _osdFadeStartTime; + /** Enum with OSD options */ + enum { + kOSDFadeOutDelay = 2 * 1000, /** < Delay before the OSD is faded out (in milliseconds) */ + kOSDFadeOutDuration = 500, /** < Duration of the OSD fade out (in milliseconds) */ + kOSDColorKey = 1, /** < Transparent color key */ + kOSDInitialAlpha = 80 /** < Initial alpha level, in percent */ + }; +#endif + + /** Hardware screen */ + SDL_Surface *_hwscreen; + + /** Unseen game screen */ + SDL_Surface *_screen; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _screenFormat; + Graphics::PixelFormat _cursorFormat; + Common::List<Graphics::PixelFormat> _supportedFormats; + + /** + * Update the list of supported pixel formats. + * This method is invoked by loadGFXMode(). + */ + void detectSupportedFormats(); +#endif + + /** Temporary screen (for scalers) */ + SDL_Surface *_tmpscreen; + /** Temporary screen (for scalers) */ + SDL_Surface *_tmpscreen2; + + SDL_Surface *_overlayscreen; + bool _overlayVisible; + Graphics::PixelFormat _overlayFormat; + + enum { + kTransactionNone = 0, + kTransactionActive = 1, + kTransactionRollback = 2 + }; + + struct TransactionDetails { + bool sizeChanged; + bool needHotswap; + bool needUpdatescreen; + bool normal1xScaler; +#ifdef USE_RGB_COLOR + bool formatChanged; +#endif + }; + TransactionDetails _transactionDetails; + + struct VideoState { + bool setup; + + bool fullscreen; + bool aspectRatioCorrection; + AspectRatio desiredAspectRatio; + + int mode; + int scaleFactor; + + int screenWidth, screenHeight; + int overlayWidth, overlayHeight; + int hardwareWidth, hardwareHeight; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat format; +#endif + }; + VideoState _videoMode, _oldVideoMode; + + /** Force full redraw on next updateScreen */ + bool _forceFull; + + ScalerProc *_scalerProc; + int _scalerType; + int _transactionMode; + + bool _screenIsLocked; + Graphics::Surface _framebuffer; + + int _screenChangeCount; + + enum { + NUM_DIRTY_RECT = 100, + MAX_SCALING = 3 + }; + + // Dirty rect management + SDL_Rect _dirtyRectList[NUM_DIRTY_RECT]; + int _numDirtyRects; + + struct MousePos { + // The mouse position, using either virtual (game) or real + // (overlay) coordinates. + int16 x, y; + + // The size and hotspot of the original cursor image. + int16 w, h; + int16 hotX, hotY; + + // The size and hotspot of the pre-scaled cursor image, in real + // coordinates. + int16 rW, rH; + int16 rHotX, rHotY; + + // The size and hotspot of the pre-scaled cursor image, in game + // coordinates. + int16 vW, vH; + int16 vHotX, vHotY; + + 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) + { } + }; + + bool _mouseVisible; + bool _mouseNeedsRedraw; + byte *_mouseData; + SDL_Rect _mouseBackup; + MousePos _mouseCurState; +#ifdef USE_RGB_COLOR + uint32 _mouseKeyColor; +#else + byte _mouseKeyColor; +#endif + int _cursorTargetScale; + bool _cursorPaletteDisabled; + SDL_Surface *_mouseOrigSurface; + SDL_Surface *_mouseSurface; + enum { + kMouseColorKey = 1 + }; + + // Shake mode + int _currentShakePos; + int _newShakePos; + + // Palette data + SDL_Color *_currentPalette; + uint _paletteDirtyStart, _paletteDirtyEnd; + + // Cursor palette data + SDL_Color *_cursorPalette; + + /** + * Mutex which prevents multiple threads from interfering with each other + * when accessing the screen. + */ + OSystem::MutexRef _graphicsMutex; + + virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); + + virtual void drawMouse(); + virtual void undrawMouse(); + virtual void blitCursor(); + + virtual void internUpdateScreen(); + + virtual bool loadGFXMode(); + virtual void unloadGFXMode(); + virtual bool hotswapGFXMode(); + + virtual void setFullscreenMode(bool enable); + virtual void setAspectRatioCorrection(bool enable); + + virtual int effectiveScreenHeight() const; + + virtual void setGraphicsModeIntern(); + + virtual bool handleScalerHotkeys(Common::KeyCode key); + virtual bool isScalerHotkey(const Common::Event &event); + virtual void adjustMouseEvent(const Common::Event &event); + virtual void setMousePos(int x, int y); + virtual void toggleFullScreen(); + virtual bool saveScreenshot(const char *filename); +}; + +#endif diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp new file mode 100644 index 0000000000..c89c46ddd8 --- /dev/null +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef __SYMBIAN32__ + +#include "backends/graphics/symbiansdl/symbiansdl-graphics.h" +#include "backends/platform/symbian/src/SymbianActions.h" + +int SymbianSdlGraphicsManager::getDefaultGraphicsMode() const { + return GFX_NORMAL; +} + +static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { + {"1x", "Fullscreen", GFX_NORMAL}, + {0, 0, 0} +}; + +const OSystem::GraphicsMode *SymbianSdlGraphicsManager::getSupportedGraphicsModes() const { + return s_supportedGraphicsModes; +} + +// make sure we always go to normal, even if the string might be set wrong! +bool SymbianSdlGraphicsManager::setGraphicsMode(int /*name*/) { + // let parent OSystem_SDL handle it + return SdlGraphicsManager::setGraphicsMode(getDefaultGraphicsMode()); +} + +bool SymbianSdlGraphicsManager::hasFeature(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + case OSystem::kFeatureAspectRatioCorrection: + case OSystem::kFeatureCursorHasPalette: +#ifdef USE_VIBRA_SE_PXXX + case OSystem::kFeatureVibration: +#endif + return true; + default: + return false; + } +} + +void SymbianSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureVirtualKeyboard: + break; + case OSystem::kFeatureDisableKeyFiltering: + GUI::Actions::Instance()->beginMapping(enable); + break; + default: + SdlGraphicsManager::setFeatureState(f, enable); + } +} + +#endif + diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.h b/backends/graphics/symbiansdl/symbiansdl-graphics.h new file mode 100644 index 0000000000..b0e87c8025 --- /dev/null +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.h @@ -0,0 +1,42 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_SYMBIAN_SDL_H +#define BACKENDS_GRAPHICS_SYMBIAN_SDL_H + +#include "backends/graphics/sdl/sdl-graphics.h" + +class SymbianSdlGraphicsManager : public SdlGraphicsManager { +public: + virtual bool hasFeature(OSystem::Feature f); + virtual void setFeatureState(OSystem::Feature f, bool enable); + + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual bool setGraphicsMode(int mode); +}; + +#endif + diff --git a/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp b/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp new file mode 100644 index 0000000000..6b0074862e --- /dev/null +++ b/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.cpp @@ -0,0 +1,129 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(MACOSX) || defined(GP2X) + +#include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h" + +DoubleBufferSDLMixerManager::DoubleBufferSDLMixerManager() + : + _soundMutex(0), _soundCond(0), _soundThread(0), + _soundThreadIsRunning(false), _soundThreadShouldQuit(false) { + +} + +DoubleBufferSDLMixerManager::~DoubleBufferSDLMixerManager() { + deinitThreadedMixer(); +} + +void DoubleBufferSDLMixerManager::startAudio() { + _soundThreadIsRunning = false; + _soundThreadShouldQuit = false; + + // Create mutex and condition variable + _soundMutex = SDL_CreateMutex(); + _soundCond = SDL_CreateCond(); + + // Create two sound buffers + _activeSoundBuf = 0; + uint bufSize = _obtainedRate.samples * 4; + _soundBufSize = bufSize; + _soundBuffers[0] = (byte *)calloc(1, bufSize); + _soundBuffers[1] = (byte *)calloc(1, bufSize); + + _soundThreadIsRunning = true; + + // Finally start the thread + _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this); + + SdlMixerManager::startAudio(); +} + +void DoubleBufferSDLMixerManager::mixerProducerThread() { + byte nextSoundBuffer; + + SDL_LockMutex(_soundMutex); + while (true) { + // Wait till we are allowed to produce data + SDL_CondWait(_soundCond, _soundMutex); + + if (_soundThreadShouldQuit) + break; + + // Generate samples and put them into the next buffer + nextSoundBuffer = _activeSoundBuf ^ 1; + _mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize); + + // Swap buffers + _activeSoundBuf = nextSoundBuffer; + } + SDL_UnlockMutex(_soundMutex); +} + +int SDLCALL DoubleBufferSDLMixerManager::mixerProducerThreadEntry(void *arg) { + DoubleBufferSDLMixerManager *mixer = (DoubleBufferSDLMixerManager *)arg; + assert(mixer); + mixer->mixerProducerThread(); + return 0; +} + +void DoubleBufferSDLMixerManager::deinitThreadedMixer() { + // Kill thread?? _soundThread + + if (_soundThreadIsRunning) { + // Signal the producer thread to end, and wait for it to actually finish. + _soundThreadShouldQuit = true; + SDL_CondBroadcast(_soundCond); + SDL_WaitThread(_soundThread, NULL); + + // Kill the mutex & cond variables. + // Attention: AT this point, the mixer callback must not be running + // anymore, else we will crash! + SDL_DestroyMutex(_soundMutex); + SDL_DestroyCond(_soundCond); + + _soundThreadIsRunning = false; + + free(_soundBuffers[0]); + free(_soundBuffers[1]); + } +} + +void DoubleBufferSDLMixerManager::callbackHandler(byte *samples, int len) { + assert(_mixer); + assert((int)_soundBufSize == len); + + // Lock mutex, to ensure our data is not overwritten by the producer thread + SDL_LockMutex(_soundMutex); + + // Copy data from the current sound buffer + memcpy(samples, _soundBuffers[_activeSoundBuf], len); + + // Unlock mutex and wake up the produced thread + SDL_UnlockMutex(_soundMutex); + SDL_CondSignal(_soundCond); +} + +#endif diff --git a/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h b/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h new file mode 100644 index 0000000000..6304c287df --- /dev/null +++ b/backends/mixer/doublebuffersdl/doublebuffersdl-mixer.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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MIXER_DOUBLEBUFFERSDL_H +#define BACKENDS_MIXER_DOUBLEBUFFERSDL_H + +#include "backends/mixer/sdl/sdl-mixer.h" + +/** + * SDL mixer manager with double buffering support. + */ +class DoubleBufferSDLMixerManager : public SdlMixerManager { +public: + DoubleBufferSDLMixerManager(); + virtual ~DoubleBufferSDLMixerManager(); + +protected: + SDL_mutex *_soundMutex; + SDL_cond *_soundCond; + SDL_Thread *_soundThread; + bool _soundThreadIsRunning; + bool _soundThreadShouldQuit; + + byte _activeSoundBuf; + uint _soundBufSize; + byte *_soundBuffers[2]; + + /** + * Handles and swap the sound buffers + */ + void mixerProducerThread(); + + /** + * Finish the mixer manager + */ + void deinitThreadedMixer(); + + /** + * Callback entry point for the sound thread + */ + static int SDLCALL mixerProducerThreadEntry(void *arg); + + virtual void startAudio(); + virtual void callbackHandler(byte *samples, int len); +}; + +#endif diff --git a/backends/mixer/sdl/sdl-mixer.cpp b/backends/mixer/sdl/sdl-mixer.cpp new file mode 100644 index 0000000000..b9e04532f8 --- /dev/null +++ b/backends/mixer/sdl/sdl-mixer.cpp @@ -0,0 +1,143 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(WIN32) || defined(UNIX) || defined(MACOSX) + +#include "backends/mixer/sdl/sdl-mixer.h" +#include "common/system.h" +#include "common/config-manager.h" + +#ifdef GP2X +#define SAMPLES_PER_SEC 11025 +#else +#define SAMPLES_PER_SEC 22050 +#endif +//#define SAMPLES_PER_SEC 44100 + +SdlMixerManager::SdlMixerManager() + : + _mixer(0), + _audioSuspended(false) { + +} + +SdlMixerManager::~SdlMixerManager() { + _mixer->setReady(false); + + SDL_CloseAudio(); + + delete _mixer; +} + +void SdlMixerManager::init() { + // Start SDL Audio subsystem + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + // Get the desired audio specs + SDL_AudioSpec desired = getAudioSpec(); + + // Start SDL audio with the desired specs + if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) { + warning("Could not open audio device: %s", SDL_GetError()); + + _mixer = new Audio::MixerImpl(g_system, desired.freq); + assert(_mixer); + _mixer->setReady(false); + } else { + debug(1, "Output sample rate: %d Hz", _obtainedRate.freq); + + _mixer = new Audio::MixerImpl(g_system, _obtainedRate.freq); + assert(_mixer); + _mixer->setReady(true); + + startAudio(); + } +} + +SDL_AudioSpec SdlMixerManager::getAudioSpec() { + SDL_AudioSpec desired; + + // Determine the desired output sampling frequency. + uint32 samplesPerSec = 0; + if (ConfMan.hasKey("output_rate")) + samplesPerSec = ConfMan.getInt("output_rate"); + if (samplesPerSec <= 0) + samplesPerSec = SAMPLES_PER_SEC; + + // Determine the sample buffer size. We want it to store enough data for + // at least 1/16th of a second (though at most 8192 samples). Note + // that it must be a power of two. So e.g. at 22050 Hz, we request a + // sample buffer size of 2048. + uint32 samples = 8192; + while (samples * 16 > samplesPerSec * 2) + samples >>= 1; + + memset(&desired, 0, sizeof(desired)); + desired.freq = samplesPerSec; + desired.format = AUDIO_S16SYS; + desired.channels = 2; + desired.samples = (uint16)samples; + desired.callback = sdlCallback; + desired.userdata = this; + + return desired; +} + +void SdlMixerManager::startAudio() { + // Start the sound system + SDL_PauseAudio(0); +} + +void SdlMixerManager::callbackHandler(byte *samples, int len) { + assert(_mixer); + _mixer->mixCallback(samples, len); +} + +void SdlMixerManager::sdlCallback(void *this_, byte *samples, int len) { + SdlMixerManager *manager = (SdlMixerManager *)this_; + assert(manager); + + manager->callbackHandler(samples, len); +} + +void SdlMixerManager::suspendAudio() { + SDL_CloseAudio(); + _audioSuspended = true; +} + +int SdlMixerManager::resumeAudio() { + if (!_audioSuspended) + return -2; + if (SDL_OpenAudio(&_obtainedRate, NULL) < 0){ + return -1; + } + SDL_PauseAudio(0); + _audioSuspended = false; + return 0; +} + +#endif diff --git a/backends/mixer/sdl/sdl-mixer.h b/backends/mixer/sdl/sdl-mixer.h new file mode 100644 index 0000000000..1b3a3543dc --- /dev/null +++ b/backends/mixer/sdl/sdl-mixer.h @@ -0,0 +1,105 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MIXER_SDL_H +#define BACKENDS_MIXER_SDL_H + +#if defined(__SYMBIAN32__) +#include <esdl\SDL.h> +#else +#include <SDL.h> +#endif + +#include "sound/mixer_intern.h" + +/** + * SDL mixer manager. It wraps the actual implementation + * of the Audio:Mixer used by the engine, and setups + * the SDL audio subsystem and the callback for the + * audio mixer implementation. + */ +class SdlMixerManager { +public: + SdlMixerManager(); + virtual ~SdlMixerManager(); + + /** + * Initialize and setups the mixer + */ + virtual void init(); + + /** + * Get the audio mixer implementation + */ + Audio::Mixer *getMixer() { return (Audio::Mixer *)_mixer; } + + // Used by LinuxMoto Port + + /** + * Pauses the audio system + */ + virtual void suspendAudio(); + + /** + * Resumes the audio system + */ + virtual int resumeAudio(); + +protected: + /** The mixer implementation */ + Audio::MixerImpl *_mixer; + + /** + * The obtained audio specification after opening the + * audio system. + */ + SDL_AudioSpec _obtainedRate; + + /** State of the audio system */ + bool _audioSuspended; + + /** + * Returns the desired audio specification + */ + virtual SDL_AudioSpec getAudioSpec(); + + /** + * Starts SDL audio + */ + virtual void startAudio(); + + /** + * Handles the audio callback + */ + virtual void callbackHandler(byte *samples, int len); + + /** + * The mixer callback entry point. Static functions can't be overrided + * by subclasses, so it invokes the non-static function callbackHandler() + */ + static void sdlCallback(void *this_, byte *samples, int len); +}; + +#endif diff --git a/backends/mixer/symbiansdl/symbiansdl-mixer.cpp b/backends/mixer/symbiansdl/symbiansdl-mixer.cpp new file mode 100644 index 0000000000..0cbae85cb9 --- /dev/null +++ b/backends/mixer/symbiansdl/symbiansdl-mixer.cpp @@ -0,0 +1,102 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef __SYMBIAN32__ + +#include "backends/mixer/symbiansdl/symbiansdl-mixer.h" +#include "common/system.h" + +#ifdef SAMPLES_PER_SEC_8000 // the GreanSymbianMMP format cannot handle values for defines :( + #define SAMPLES_PER_SEC 8000 +#else + #define SAMPLES_PER_SEC 16000 +#endif + +SymbianSdlMixerManager::SymbianSdlMixerManager() + : + _stereo_mix_buffer(0) { + +} + +SymbianSdlMixerManager::~SymbianSdlMixerManager() { + delete[] _stereo_mix_buffer; +} + +void SymbianSdlMixerManager::init() { + // Start SDL Audio subsystem + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + // Get the desired audio specs + SDL_AudioSpec desired = getAudioSpec(); + + // Start SDL audio with the desired specs + if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) { + warning("Could not open audio device: %s", SDL_GetError()); + + _mixer = new Audio::MixerImpl(g_system, desired.freq); + assert(_mixer); + _mixer->setReady(false); + } else { + debug(1, "Output sample rate: %d Hz", _obtainedRate.freq); + + _channels = _obtainedRate.channels; + + // Need to create mixbuffer for stereo mix to downmix + if (_channels != 2) { + _stereo_mix_buffer = new byte [_obtainedRate.size * 2]; // * 2 for stereo values + } + + _mixer = new Audio::MixerImpl(g_system, _obtainedRate.freq); + assert(_mixer); + _mixer->setReady(true); + + startAudio(); + } +} + +void SymbianSdlMixerManager::callbackHandler(byte *samples, int len) { +#if defined (S60) && !defined(S60V3) + // If not stereo then we need to downmix + if (_mixer->_channels != 2) { + _mixer->mixCallback(_stereo_mix_buffer, len * 2); + + int16 *bitmixDst = (int16 *)samples; + int16 *bitmixSrc = (int16 *)_stereo_mix_buffer; + + for (int loop = len / 2; loop >= 0; loop --) { + *bitmixDst = (*bitmixSrc + *(bitmixSrc + 1)) >> 1; + bitmixDst++; + bitmixSrc += 2; + } + } else +#else + _mixer->mixCallback(samples, len); +#endif +} + +#endif + diff --git a/backends/mixer/symbiansdl/symbiansdl-mixer.h b/backends/mixer/symbiansdl/symbiansdl-mixer.h new file mode 100644 index 0000000000..6a0d281b1a --- /dev/null +++ b/backends/mixer/symbiansdl/symbiansdl-mixer.h @@ -0,0 +1,49 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MIXER_SYMBIAN_SDL_H +#define BACKENDS_MIXER_SYMBIAN_SDL_H + +#include "backends/mixer/sdl/sdl-mixer.h" + +/** + * SDL mixer manager for Symbian + */ +class SymbianSdlMixerManager : public SdlMixerManager { +public: + SymbianSdlMixerManager(); + virtual ~SymbianSdlMixerManager(); + + virtual void init(); + +protected: + int _channels; + byte *_stereo_mix_buffer; + + virtual void callbackHandler(byte *samples, int len); +}; + +#endif + diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp new file mode 100644 index 0000000000..be488f0190 --- /dev/null +++ b/backends/modular-backend.cpp @@ -0,0 +1,282 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/modular-backend.h" +#include "gui/message.h" + +ModularBackend::ModularBackend() + : + _fsFactory(0), + _eventManager(0), + _savefileManager(0), + _timerManager(0), + _mutexManager(0), + _graphicsManager(0), + _mixer(0), + _audiocdManager(0) { + +} + +ModularBackend::~ModularBackend() { + // Delete all managers if they have not been already + // freed by a subclass + if (_eventManager != 0) + delete _eventManager; + if (_graphicsManager != 0) + delete _graphicsManager; + if (_mixer != 0) + delete _mixer; + if (_audiocdManager != 0) + delete _audiocdManager; + if (_savefileManager != 0) + delete _savefileManager; + if (_timerManager != 0) + delete _timerManager; + if (_mutexManager != 0) + delete _mutexManager; +} + +bool ModularBackend::hasFeature(Feature f) { + return _graphicsManager->hasFeature(f); +} + +void ModularBackend::setFeatureState(Feature f, bool enable) { + return _graphicsManager->setFeatureState(f, enable); +} + +bool ModularBackend::getFeatureState(Feature f) { + return _graphicsManager->getFeatureState(f); +} + +GraphicsManager *ModularBackend::getGraphicsManager() { + assert(_graphicsManager); + return (GraphicsManager *)_graphicsManager; +} + +const OSystem::GraphicsMode *ModularBackend::getSupportedGraphicsModes() const { + return _graphicsManager->getSupportedGraphicsModes(); +} + +int ModularBackend::getDefaultGraphicsMode() const { + return _graphicsManager->getDefaultGraphicsMode(); +} + +bool ModularBackend::setGraphicsMode(int mode) { + return _graphicsManager->setGraphicsMode(mode); +} + +int ModularBackend::getGraphicsMode() const { + return _graphicsManager->getGraphicsMode(); +} + +void ModularBackend::resetGraphicsScale() { + _graphicsManager->resetGraphicsScale(); +} + +#ifdef USE_RGB_COLOR + +Graphics::PixelFormat ModularBackend::getScreenFormat() const { + return _graphicsManager->getScreenFormat(); +} + +Common::List<Graphics::PixelFormat> ModularBackend::getSupportedFormats() const { + return _graphicsManager->getSupportedFormats(); +} + +#endif + +void ModularBackend::initSize(uint w, uint h, const Graphics::PixelFormat *format ) { + _graphicsManager->initSize(w, h, format); +} + +int ModularBackend::getScreenChangeID() const { + return _graphicsManager->getScreenChangeID(); +} + +void ModularBackend::beginGFXTransaction() { + _graphicsManager->beginGFXTransaction(); +} + +OSystem::TransactionError ModularBackend::endGFXTransaction() { + return _graphicsManager->endGFXTransaction(); +} + +int16 ModularBackend::getHeight() { + return _graphicsManager->getHeight(); +} + +int16 ModularBackend::getWidth() { + return _graphicsManager->getWidth(); +} + +void ModularBackend::setPalette(const byte *colors, uint start, uint num) { + _graphicsManager->setPalette(colors, start, num); +} + +void ModularBackend::grabPalette(byte *colors, uint start, uint num) { + _graphicsManager->grabPalette(colors, start, num); +} + +void ModularBackend::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { + _graphicsManager->copyRectToScreen(buf, pitch, x, y, w, h); +} + +Graphics::Surface *ModularBackend::lockScreen() { + return _graphicsManager->lockScreen(); +} + +void ModularBackend::unlockScreen() { + _graphicsManager->unlockScreen(); +} + +void ModularBackend::fillScreen(uint32 col) { + _graphicsManager->fillScreen(col); +} + +void ModularBackend::updateScreen() { + _graphicsManager->updateScreen(); +} + +void ModularBackend::setShakePos(int shakeOffset) { + _graphicsManager->setShakePos(shakeOffset); +} +void ModularBackend::setFocusRectangle(const Common::Rect& rect) { + _graphicsManager->setFocusRectangle(rect); +} + +void ModularBackend::clearFocusRectangle() { + _graphicsManager->clearFocusRectangle(); +} + +void ModularBackend::showOverlay() { + _graphicsManager->showOverlay(); +} + +void ModularBackend::hideOverlay() { + _graphicsManager->hideOverlay(); +} + +Graphics::PixelFormat ModularBackend::getOverlayFormat() const { + return _graphicsManager->getOverlayFormat(); +} + +void ModularBackend::clearOverlay() { + _graphicsManager->clearOverlay(); +} + +void ModularBackend::grabOverlay(OverlayColor *buf, int pitch) { + _graphicsManager->grabOverlay(buf, pitch); +} + +void ModularBackend::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + _graphicsManager->copyRectToOverlay(buf, pitch, x, y, w, h); +} + +int16 ModularBackend::getOverlayHeight() { + return _graphicsManager->getOverlayHeight(); +} + +int16 ModularBackend::getOverlayWidth() { + return _graphicsManager->getOverlayWidth(); +} + +bool ModularBackend::showMouse(bool visible) { + return _graphicsManager->showMouse(visible); +} + +void ModularBackend::warpMouse(int x, int y) { + _graphicsManager->warpMouse(x, y); +} + +void ModularBackend::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { + _graphicsManager->setMouseCursor(buf, w, h, hotspotX, hotspotY, keycolor, cursorTargetScale, format); +} + +void ModularBackend::setCursorPalette(const byte *colors, uint start, uint num) { + _graphicsManager->setCursorPalette(colors, start, num); +} + +void ModularBackend::disableCursorPalette(bool disable) { + _graphicsManager->disableCursorPalette(disable); +} + +Common::TimerManager *ModularBackend::getTimerManager() { + assert(_timerManager); + return _timerManager; +} + +Common::EventManager *ModularBackend::getEventManager() { + assert(_eventManager); + return _eventManager; +} + +OSystem::MutexRef ModularBackend::createMutex() { + assert(_mutexManager); + return _mutexManager->createMutex(); +} + +void ModularBackend::lockMutex(MutexRef mutex) { + assert(_mutexManager); + _mutexManager->lockMutex(mutex); +} + +void ModularBackend::unlockMutex(MutexRef mutex) { + assert(_mutexManager); + _mutexManager->unlockMutex(mutex); +} + +void ModularBackend::deleteMutex(MutexRef mutex) { + assert(_mutexManager); + _mutexManager->deleteMutex(mutex); +} + +Audio::Mixer *ModularBackend::getMixer() { + assert(_mixer); + return (Audio::Mixer *)_mixer; +} + +AudioCDManager *ModularBackend::getAudioCDManager() { + assert(_audiocdManager); + return _audiocdManager; +} + +void ModularBackend::displayMessageOnOSD(const char *msg) { +#ifdef USE_OSD + _graphicsManager->displayMessageOnOSD(msg); +#else + GUI::TimedMessageDialog dialog(msg, 1500); + dialog.runModal(); +#endif +} + +Common::SaveFileManager *ModularBackend::getSavefileManager() { + assert(_savefileManager); + return _savefileManager; +} + +FilesystemFactory *ModularBackend::getFilesystemFactory() { + assert(_fsFactory); + return _fsFactory; +} diff --git a/backends/modular-backend.h b/backends/modular-backend.h new file mode 100644 index 0000000000..b7920d9d71 --- /dev/null +++ b/backends/modular-backend.h @@ -0,0 +1,178 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MODULAR_BACKEND_H +#define BACKENDS_MODULAR_BACKEND_H + +#include "common/system.h" +#include "common/timer.h" +#include "common/savefile.h" +#include "backends/events/default/default-events.h" +#include "backends/audiocd/default/default-audiocd.h" +#include "backends/mutex/null/null-mutex.h" +#include "backends/graphics/null/null-graphics.h" + +/** + * Base class for modular backends. + * + * It wraps most functions to their manager equivalent, but not + * all OSystem functions are implemented here. + * + * A backend derivated from this class, will need to implement + * these functions on its own: + * OSystem::pollEvent() + * OSystem::createConfigReadStream() + * OSystem::createConfigWriteStream() + * OSystem::getMillis() + * OSystem::delayMillis() + * OSystem::getTimeAndDate() + * + * And, it should also initialize all the managers variables + * declared in this class, or override their related functions. + */ +class ModularBackend : public OSystem, public Common::EventSource { +public: + ModularBackend(); + virtual ~ModularBackend(); + + /** @name Features */ + //@{ + + virtual bool hasFeature(Feature f); + virtual void setFeatureState(Feature f, bool enable); + virtual bool getFeatureState(Feature f); + + //@} + + /** @name Graphics */ + //@{ + + virtual GraphicsManager *getGraphicsManager(); + virtual const GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual bool setGraphicsMode(int mode); + virtual int getGraphicsMode() const; + virtual void resetGraphicsScale(); +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; +#endif + virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); + virtual int getScreenChangeID() const; + + virtual void beginGFXTransaction(); + virtual OSystem::TransactionError endGFXTransaction(); + + virtual int16 getHeight(); + virtual int16 getWidth(); + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + virtual void copyRectToScreen(const byte *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 clearFocusRectangle(); + + virtual void showOverlay(); + virtual void hideOverlay(); + virtual Graphics::PixelFormat getOverlayFormat() const; + virtual void clearOverlay(); + virtual void grabOverlay(OverlayColor *buf, int pitch); + virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); + virtual int16 getOverlayHeight(); + virtual int16 getOverlayWidth(); + + virtual bool showMouse(bool visible); + virtual void warpMouse(int x, int y); + virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL); + virtual void setCursorPalette(const byte *colors, uint start, uint num); + virtual void disableCursorPalette(bool disable); + + //@} + + /** @name Events and Time */ + //@{ + + virtual Common::TimerManager *getTimerManager(); + virtual Common::EventManager *getEventManager(); + virtual Common::HardwareKeySet *getHardwareKeySet() { return 0; } + + //@} + + /** @name Mutex handling */ + //@{ + + virtual MutexRef createMutex(); + virtual void lockMutex(MutexRef mutex); + virtual void unlockMutex(MutexRef mutex); + virtual void deleteMutex(MutexRef mutex); + + //@} + + /** @name Sound */ + //@{ + + virtual Audio::Mixer *getMixer(); + + //@} + + /** @name Audio CD */ + //@{ + + virtual AudioCDManager *getAudioCDManager(); + + //@} + + /** @name Miscellaneous */ + //@{ + + virtual Common::SaveFileManager *getSavefileManager(); + virtual FilesystemFactory *getFilesystemFactory(); + virtual void quit() { exit(0); } + virtual void setWindowCaption(const char *caption) {} + virtual void displayMessageOnOSD(const char *msg); + + //@} + +protected: + /** @name Managers variables */ + //@{ + + FilesystemFactory *_fsFactory; + Common::EventManager *_eventManager; + Common::SaveFileManager *_savefileManager; + Common::TimerManager *_timerManager; + MutexManager *_mutexManager; + GraphicsManager *_graphicsManager; + Audio::Mixer *_mixer; + AudioCDManager *_audiocdManager; + + //@} +}; + +#endif diff --git a/backends/module.mk b/backends/module.mk index e0a3f4c683..f5677ed470 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -2,13 +2,30 @@ MODULE := backends MODULE_OBJS := \ base-backend.o \ + modular-backend.o \ + audiocd/default/default-audiocd.o \ + audiocd/sdl/sdl-audiocd.o \ events/default/default-events.o \ + events/gp2xsdl/gp2xsdl-events.o \ + events/linuxmotosdl/linuxmotosdl-events.o \ + events/samsungtvsdl/samsungtvsdl-events.o \ + events/sdl/sdl-events.o \ + events/symbiansdl/symbiansdl-events.o \ fs/abstract-fs.o \ fs/stdiostream.o \ fs/amigaos4/amigaos4-fs-factory.o \ fs/posix/posix-fs-factory.o \ fs/symbian/symbian-fs-factory.o \ fs/windows/windows-fs-factory.o \ + graphics/gp2xsdl/gp2xsdl-graphics.o \ + graphics/gp2xwizsdl/gp2xwizsdl-graphics.o \ + graphics/linuxmotosdl/linuxmotosdl-graphics.o \ + graphics/opengl/glerrorcheck.o \ + graphics/opengl/gltexture.o \ + graphics/opengl/opengl-graphics.o \ + graphics/openglsdl/openglsdl-graphics.o \ + graphics/sdl/sdl-graphics.o \ + graphics/symbiansdl/symbiansdl-graphics.o \ keymapper/action.o \ keymapper/keymap.o \ keymapper/keymapper.o \ @@ -22,6 +39,11 @@ MODULE_OBJS := \ midi/timidity.o \ midi/dmedia.o \ midi/windows.o \ + mixer/doublebuffersdl/doublebuffersdl-mixer.o \ + mixer/sdl/sdl-mixer.o \ + mixer/symbiansdl/symbiansdl-mixer.o \ + mutex/sdl/sdl-mutex.o \ + plugins/dc/dc-provider.o \ plugins/posix/posix-provider.o \ plugins/sdl/sdl-provider.o \ plugins/win32/win32-provider.o \ @@ -29,6 +51,7 @@ MODULE_OBJS := \ saves/default/default-saves.o \ saves/posix/posix-saves.o \ timer/default/default-timer.o \ + timer/sdl/sdl-timer.o \ vkeybd/image-map.o \ vkeybd/polygon.o \ vkeybd/virtual-keyboard.o \ diff --git a/backends/mutex/mutex.h b/backends/mutex/mutex.h new file mode 100644 index 0000000000..ddf27d5932 --- /dev/null +++ b/backends/mutex/mutex.h @@ -0,0 +1,46 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MUTEX_ABSTRACT_H +#define BACKENDS_MUTEX_ABSTRACT_H + +#include "common/system.h" +#include "common/noncopyable.h" + +/** + * Abstract class for mutex manager. Subclasses + * implement the real functionality. + */ +class MutexManager : Common::NonCopyable { +public: + virtual ~MutexManager() {} + + virtual OSystem::MutexRef createMutex() = 0; + virtual void lockMutex(OSystem::MutexRef mutex) = 0; + virtual void unlockMutex(OSystem::MutexRef mutex) = 0; + virtual void deleteMutex(OSystem::MutexRef mutex) = 0; +}; + +#endif diff --git a/backends/mutex/null/null-mutex.h b/backends/mutex/null/null-mutex.h new file mode 100644 index 0000000000..54b8f5ce96 --- /dev/null +++ b/backends/mutex/null/null-mutex.h @@ -0,0 +1,42 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MUTEX_NULL_H +#define BACKENDS_MUTEX_NULL_H + +#include "backends/mutex/mutex.h" + +/** + * Null mutex manager + */ +class NullMutexManager : MutexManager { +public: + virtual OSystem::MutexRef createMutex() { return OSystem::MutexRef(); } + virtual void lockMutex(OSystem::MutexRef mutex) {} + virtual void unlockMutex(OSystem::MutexRef mutex) {} + virtual void deleteMutex(OSystem::MutexRef mutex) {} +}; + +#endif diff --git a/backends/mutex/sdl/sdl-mutex.cpp b/backends/mutex/sdl/sdl-mutex.cpp new file mode 100644 index 0000000000..53529c155a --- /dev/null +++ b/backends/mutex/sdl/sdl-mutex.cpp @@ -0,0 +1,52 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(WIN32) || defined(UNIX) || defined(MACOSX) + +#include "backends/mutex/sdl/sdl-mutex.h" + +#if defined(__SYMBIAN32__) +#include <esdl\SDL.h> +#else +#include <SDL.h> +#endif + +OSystem::MutexRef SdlMutexManager::createMutex() { + return (OSystem::MutexRef) SDL_CreateMutex(); +} + +void SdlMutexManager::lockMutex(OSystem::MutexRef mutex) { + SDL_mutexP((SDL_mutex *) mutex); +} + +void SdlMutexManager::unlockMutex(OSystem::MutexRef mutex) { + SDL_mutexV((SDL_mutex *) mutex); +} + +void SdlMutexManager::deleteMutex(OSystem::MutexRef mutex) { + SDL_DestroyMutex((SDL_mutex *) mutex); +} + +#endif diff --git a/backends/mutex/sdl/sdl-mutex.h b/backends/mutex/sdl/sdl-mutex.h new file mode 100644 index 0000000000..88a19d398a --- /dev/null +++ b/backends/mutex/sdl/sdl-mutex.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_MUTEX_SDL_H +#define BACKENDS_MUTEX_SDL_H + +#include "backends/mutex/mutex.h" + +/** + * SDL mutex manager + */ +class SdlMutexManager : public MutexManager { +public: + virtual OSystem::MutexRef createMutex(); + virtual void lockMutex(OSystem::MutexRef mutex); + virtual void unlockMutex(OSystem::MutexRef mutex); + virtual void deleteMutex(OSystem::MutexRef mutex); +}; + + +#endif diff --git a/backends/platform/gp2x/events.cpp b/backends/platform/gp2x/events.cpp deleted file mode 100644 index a40967743c..0000000000 --- a/backends/platform/gp2x/events.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * GP2X: Common::Event Handling. - * - */ - -#include "backends/platform/gp2x/gp2x-common.h" -#include "backends/platform/gp2x/gp2x-hw.h" -#include "backends/keymapper/keymapper.h" -#include "common/util.h" -#include "common/events.h" -#include "graphics/scaler/aspect.h" // for aspect2Real - -// FIXME move joystick defines out and replace with confile file options -// we should really allow users to map any key to a joystick button using the keymapper. -#define JOY_DEADZONE 2200 - -#define JOY_XAXIS 0 -#define JOY_YAXIS 1 - -/* GP2X Wiz: Main Joystick Mappings */ -enum { - GP2X_BUTTON_UP = 0, - GP2X_BUTTON_UPLEFT = 1, - GP2X_BUTTON_LEFT = 2, - GP2X_BUTTON_DOWNLEFT = 3, - GP2X_BUTTON_DOWN = 4, - GP2X_BUTTON_DOWNRIGHT = 5, - GP2X_BUTTON_RIGHT = 6, - GP2X_BUTTON_UPRIGHT = 7, - GP2X_BUTTON_START = 8, - GP2X_BUTTON_SELECT = 9, - GP2X_BUTTON_L = 10, - GP2X_BUTTON_R = 11, - GP2X_BUTTON_A = 12, - GP2X_BUTTON_B = 13, - GP2X_BUTTON_X = 14, - GP2X_BUTTON_Y = 15, - GP2X_BUTTON_VOLUP = 16, - GP2X_BUTTON_VOLDOWN = 17, - GP2X_BUTTON_CLICK = 18 -}; - -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { - if (key >= SDLK_F1 && key <= SDLK_F9) { - return key - SDLK_F1 + Common::ASCII_F1; - } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { - return key - SDLK_KP0 + '0'; - } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { - return key; - } else if (unicode) { - return unicode; - } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { - return key & ~0x20; - } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { - return 0; - } - return key; -} - -void OSystem_GP2X::fillMouseEvent(Common::Event &event, int x, int y) { - event.mouse.x = x; - event.mouse.y = y; - - // Update the "keyboard mouse" coords - _km.x = x; - _km.y = y; - - // Adjust for the screen scaling - if (!_overlayVisible) { - event.mouse.x /= _videoMode.scaleFactor; - event.mouse.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - event.mouse.y = aspect2Real(event.mouse.y); - } -} - -void OSystem_GP2X::handleKbdMouse() { - uint32 curTime = getMillis(); - if (curTime >= _km.last_time + _km.delay_time) { - _km.last_time = curTime; - if (_km.x_down_count == 1) { - _km.x_down_time = curTime; - _km.x_down_count = 2; - } - if (_km.y_down_count == 1) { - _km.y_down_time = curTime; - _km.y_down_count = 2; - } - - if (_km.x_vel || _km.y_vel) { - if (_km.x_down_count) { - if (curTime > _km.x_down_time + _km.delay_time * 12) { - if (_km.x_vel > 0) - _km.x_vel++; - else - _km.x_vel--; - } else if (curTime > _km.x_down_time + _km.delay_time * 8) { - if (_km.x_vel > 0) - _km.x_vel = 5; - else - _km.x_vel = -5; - } - } - if (_km.y_down_count) { - if (curTime > _km.y_down_time + _km.delay_time * 12) { - if (_km.y_vel > 0) - _km.y_vel++; - else - _km.y_vel--; - } else if (curTime > _km.y_down_time + _km.delay_time * 8) { - if (_km.y_vel > 0) - _km.y_vel = 5; - else - _km.y_vel = -5; - } - } - - _km.x += _km.x_vel; - _km.y += _km.y_vel; - - if (_km.x < 0) { - _km.x = 0; - _km.x_vel = -1; - _km.x_down_count = 1; - } else if (_km.x > _km.x_max) { - _km.x = _km.x_max; - _km.x_vel = 1; - _km.x_down_count = 1; - } - - if (_km.y < 0) { - _km.y = 0; - _km.y_vel = -1; - _km.y_down_count = 1; - } else if (_km.y > _km.y_max) { - _km.y = _km.y_max; - _km.y_vel = 1; - _km.y_down_count = 1; - } - - SDL_WarpMouse((Uint16)_km.x, (Uint16)_km.y); - } - } -} - -static byte SDLModToOSystemKeyFlags(SDLMod mod) { - byte b = 0; - if (mod & KMOD_SHIFT) - b |= Common::KBD_SHIFT; - if (mod & KMOD_ALT) - b |= Common::KBD_ALT; - if (mod & KMOD_CTRL) - b |= Common::KBD_CTRL; - - return b; -} - -void OSystem_GP2X::moveStick() { - bool stickBtn[32]; - - memcpy(stickBtn, _stickBtn, sizeof(stickBtn)); - - if ((stickBtn[0])||(stickBtn[2])||(stickBtn[4])||(stickBtn[6])) - stickBtn[1] = stickBtn[3] = stickBtn[5] = stickBtn[7] = 0; - - if ((stickBtn[1])||(stickBtn[2])||(stickBtn[3])){ - if (_km.x_down_count!=2){ - _km.x_vel = -1; - _km.x_down_count = 1; - }else - _km.x_vel = -4; - } else if ((stickBtn[5])||(stickBtn[6])||(stickBtn[7])){ - if (_km.x_down_count!=2){ - _km.x_vel = 1; - _km.x_down_count = 1; - } else - _km.x_vel = 4; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - - if ((stickBtn[0])||(stickBtn[1])||(stickBtn[7])){ - if (_km.y_down_count!=2){ - _km.y_vel = -1; - _km.y_down_count = 1; - }else - _km.y_vel = -4; - } else if ((stickBtn[3])||(stickBtn[4])||(stickBtn[5])){ - if (_km.y_down_count!=2){ - _km.y_vel = 1; - _km.y_down_count = 1; - } else - _km.y_vel = 4; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -} - -/* Quick default button states for modifiers. */ -int GP2X_BUTTON_STATE_L = false; - -bool OSystem_GP2X::pollEvent(Common::Event &event) { - SDL_Event ev; - ev.type = SDL_NOEVENT; - int axis; - byte b = 0; - - handleKbdMouse(); - - // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED - if (_modeChanged) { - _modeChanged = false; - event.type = Common::EVENT_SCREEN_CHANGED; - return true; - } - - // GP2X Input mappings. - - /* - Single Button - - Movement: - - GP2X_BUTTON_UP Cursor Up - GP2X_BUTTON_DOWN Cursor Down - GP2X_BUTTON_LEFT Cursor Left - GP2X_BUTTON_RIGHT Cursor Right - - GP2X_BUTTON_UPLEFT Cursor Up Left - GP2X_BUTTON_UPRIGHT Cursor Up Right - GP2X_BUTTON_DOWNLEFT Cursor Down Left - GP2X_BUTTON_DOWNRIGHT Cursor Down Right - - Button Emulation: - - GP2X_BUTTON_CLICK Left Mouse Click - GP2X_BUTTON_A . (Period) - GP2X_BUTTON_B Left Mouse Click - GP2X_BUTTON_Y Space Bar - GP2X_BUTTON_X Right Mouse Click - GP2X_BUTTON_L Combo Modifier (Left Trigger) - GP2X_BUTTON_R Return (Right Trigger) - GP2X_BUTTON_START F5 (Game Menu) - GP2X_BUTTON_SELECT Escape - GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up - GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down - - Combos: - - GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) or Virtual Keyboard if enabled - GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) - GP2X_BUTTON_L & GP2X_BUTTON_Y Toggles setZoomOnMouse() for larger then 320*240 games to scale to the point + raduis. - GP2X_BUTTON_L & GP2X_BUTTON_START Common::EVENT_MAINMENU (ScummVM Global Main Menu) - GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) - */ - - while (SDL_PollEvent(&ev)) { - - switch (ev.type) { - case SDL_KEYDOWN:{ - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - - return true; - } - case SDL_KEYUP: - { - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - // Ctrl-Alt-<key> will change the GFX mode - if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { - // Swallow these key up events - break; - } - - return true; - } - case SDL_MOUSEMOTION: - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, ev.motion.x, ev.motion.y); - - setMousePos(event.mouse.x, event.mouse.y); - return true; - - case SDL_MOUSEBUTTONDOWN: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONDOWN; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONDOWN; -#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) - else if (ev.button.button == SDL_BUTTON_WHEELUP) - event.type = Common::EVENT_WHEELUP; - else if (ev.button.button == SDL_BUTTON_WHEELDOWN) - event.type = Common::EVENT_WHEELDOWN; -#endif -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONDOWN; -#endif - else - break; - - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - case SDL_MOUSEBUTTONUP: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONUP; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONUP; -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONUP; -#endif - else - break; - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - // GP2X Button mapings. Main code - - case SDL_JOYBUTTONDOWN: - _stickBtn[ev.jbutton.button] = 1; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (_stickBtn[GP2X_BUTTON_L] && (ev.jbutton.button == GP2X_BUTTON_SELECT)) { - event.type = Common::EVENT_QUIT; - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYDOWN; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = true; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_SELECT: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_QUIT; - } else { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_A: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_PREDICTIVE_DIALOG; - } else { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_Y: - if (GP2X_BUTTON_STATE_L == true) { - setZoomOnMouse(); - } else { - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_START: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - GP2X_HW::mixerMoveVolume(2); - if (GP2X_HW::volumeLevel == 100) { - displayMessageOnOSD("Maximum Volume"); - } else { - displayMessageOnOSD("Increasing Volume"); - } - break; - - case GP2X_BUTTON_VOLDOWN: - GP2X_HW::mixerMoveVolume(1); - if (GP2X_HW::volumeLevel == 0) { - displayMessageOnOSD("Minimal Volume"); - } else { - displayMessageOnOSD("Decreasing Volume"); - } - break; - } - } - return true; - - case SDL_JOYBUTTONUP: - _stickBtn[ev.jbutton.button] = 0; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYUP; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_SELECT: - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_A: - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_Y: - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_START: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = false; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - break; - case GP2X_BUTTON_VOLDOWN: - break; - } - } - return true; - - case SDL_JOYAXISMOTION: - axis = ev.jaxis.value; - if ( axis > JOY_DEADZONE) { - axis -= JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else if ( axis < -JOY_DEADZONE ) { - axis += JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else - axis = 0; - - if ( ev.jaxis.axis == JOY_XAXIS) { - if (axis != 0) { - _km.x_vel = (axis > 0) ? 1:-1; - _km.x_down_count = 1; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - } else if (ev.jaxis.axis == JOY_YAXIS) { -#ifndef JOY_INVERT_Y - axis = -axis; -#endif -#ifdef JOY_ANALOG - _km.y_vel = -axis / 2000; - _km.y_down_count = 0; -#else - if (axis != 0) { - _km.y_vel = (-axis > 0) ? 1: -1; - _km.y_down_count = 1; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -#endif - } - - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case SDL_VIDEOEXPOSE: - _forceFull = true; - break; - - case SDL_QUIT: - event.type = Common::EVENT_QUIT; - return true; - } - } - return false; -} - -bool OSystem_GP2X::remapKey(SDL_Event &ev,Common::Event &event) { - return false; -} - -void OSystem_GP2X::setupKeymapper() { -#ifdef ENABLE_KEYMAPPER - using namespace Common; - Keymapper *mapper = getEventManager()->getKeymapper(); - - HardwareKeySet *keySet = new HardwareKeySet(); - keySet->addHardwareKey(new HardwareKey( "a", KeyState(KEYCODE_a), "a", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "s", KeyState(KEYCODE_s), "s", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "d", KeyState(KEYCODE_d), "d", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "f", KeyState(KEYCODE_f), "f", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "n", KeyState(KEYCODE_n), "n (vk)", kTriggerLeftKeyType, kVirtualKeyboardActionType )); - keySet->addHardwareKey(new HardwareKey( "m", KeyState(KEYCODE_m), "m (remap)", kTriggerRightKeyType, kKeyRemapActionType )); - keySet->addHardwareKey(new HardwareKey( "[", KeyState(KEYCODE_LEFTBRACKET), "[ (select)", kSelectKeyType )); - keySet->addHardwareKey(new HardwareKey( "]", KeyState(KEYCODE_RIGHTBRACKET), "] (start)", kStartKeyType )); - mapper->registerHardwareKeySet(keySet); - - Keymap *globalMap = new Keymap("global"); - Keymap *guiMap = new Keymap("gui"); - Action *act; - Event evt ; - - act = new Action(globalMap, "MENU", "Menu", kGenericActionType, kSelectKeyType); - act->addKeyEvent(KeyState(KEYCODE_F5, ASCII_F5, 0)); - - act = new Action(globalMap, "SKCT", "Skip", kGenericActionType, kActionKeyType); - act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0)); - - act = new Action(globalMap, "PAUS", "Pause", kGenericActionType, kStartKeyType); - act->addKeyEvent(KeyState(KEYCODE_SPACE, ' ', 0)); - - act = new Action(globalMap, "SKLI", "Skip line", kGenericActionType, kActionKeyType); - act->addKeyEvent(KeyState(KEYCODE_PERIOD, '.', 0)); - - act = new Action(globalMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType); - act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0)); - - act = new Action(globalMap, "REMP", "Remap keys", kKeyRemapActionType); - act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - - mapper->addGlobalKeymap(globalMap); - - act = new Action(guiMap, "CLOS", "Close", kGenericActionType, kStartKeyType); - act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0)); - - act = new Action(guiMap, "CLIK", "Mouse click"); - act->addLeftClickEvent(); - - act = new Action(guiMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType); - act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0)); - - act = new Action(guiMap, "REMP", "Remap keys", kKeyRemapActionType); - act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - - mapper->addGlobalKeymap(guiMap); - - mapper->pushKeymap("global"); -#endif -} - diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h index b54e2d4d4f..4d2a9c33cc 100644 --- a/backends/platform/gp2x/gp2x-common.h +++ b/backends/platform/gp2x/gp2x-common.h @@ -23,361 +23,23 @@ * */ -#ifndef GP2X_COMMON_H -#define GP2X_COMMON_H +#ifndef PLATFORM_SDL_GP2X_H +#define PLATFORM_SDL_GP2X_H -#include <SDL.h> -#include <SDL_gp2x.h> - -#include "backends/base-backend.h" -#include "graphics/scaler.h" - -#define __GP2X__ -#define USE_OSD -#define MIXER_DOUBLE_BUFFERING 1 - -namespace Audio { - class MixerImpl; -} - -enum { - GFX_NORMAL = 0 -}; +#include "backends/platform/sdl/posix/posix.h" +#ifndef PATH_MAX + #define PATH_MAX 255 +#endif -class OSystem_GP2X : public BaseBackend { +class OSystem_GP2X : public OSystem_POSIX { public: - OSystem_GP2X(); - virtual ~OSystem_GP2X(); - virtual void initBackend(); - - void beginGFXTransaction(void); - TransactionError endGFXTransaction(void); - - // Set the size of the video bitmap. - // Typically, 320x200 - void initSize(uint w, uint h, const Graphics::PixelFormat *format); - - int getScreenChangeID() const { return _screenChangeCount; } - - // Set colors of the palette - void setPalette(const byte *colors, uint start, uint num); - - // Get colors of the palette - void grabPalette(byte *colors, uint start, uint num); - - // Draw a bitmap to screen. - // The screen will not be updated to reflect the new bitmap - void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); - - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - - // Update the dirty areas of the screen - void updateScreen(); - - // Either show or hide the mouse cursor - bool showMouse(bool visible); - - // Warp the mouse cursor. Where set_mouse_pos() only informs the - // backend of the mouse cursor's current position, this function - // actually moves the cursor to the specified position. - void warpMouse(int x, int y); - - // Set the bitmap that's used when drawing the cursor. - void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); - - // Set colors of cursor palette - void setCursorPalette(const byte *colors, uint start, uint num); - - // Disables or enables cursor palette - void disableCursorPalette(bool disable) { - _cursorPaletteDisabled = disable; - blitCursor(); - } - - // Shaking is used in SCUMM. Set current shake position. - void setShakePos(int shake_pos); - - // Get the number of milliseconds since the program was started. - uint32 getMillis(); - - // Delay for a specified amount of milliseconds - void delayMillis(uint msecs); - - // Get the next event. - // Returns true if an event was retrieved. - virtual bool pollEvent(Common::Event &event); // overloaded by CE backend - - // Sets up the keymapper with the backends hardware key set - void setupKeymapper(); - - // Set function that generates samples - void setupMixer(); - static void mixCallback(void *s, byte *samples, int len); - - void closeMixer(); - - virtual Audio::Mixer *getMixer(); - - // Quit - void quit(); - - void getTimeAndDate(TimeDate &t) const; - virtual Common::TimerManager *getTimerManager(); - - // Mutex handling - MutexRef createMutex(); - void lockMutex(MutexRef mutex); - void unlockMutex(MutexRef mutex); - void deleteMutex(MutexRef mutex); - - // Overlay - Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; } - void showOverlay(); - void hideOverlay(); - void clearOverlay(); - void grabOverlay(OverlayColor *buf, int pitch); - void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); - int16 getHeight(); - int16 getWidth(); - int16 getOverlayHeight() { return _videoMode.overlayHeight; } - int16 getOverlayWidth() { return _videoMode.overlayWidth; } - - const GraphicsMode *getSupportedGraphicsModes() const; - int getDefaultGraphicsMode() const; - bool setGraphicsMode(int mode); - int getGraphicsMode() const; - - bool hasFeature(Feature f); - void setFeatureState(Feature f, bool enable); - bool getFeatureState(Feature f); - - void displayMessageOnOSD(const char *msg); - - virtual Common::SaveFileManager *getSavefileManager(); - virtual FilesystemFactory *getFilesystemFactory(); + virtual void quit(); virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); - virtual Common::SeekableReadStream *createConfigReadStream(); - virtual Common::WriteStream *createConfigWriteStream(); - -protected: - bool _inited; - - SDL_Surface *_osdSurface; - Uint8 _osdAlpha; // Transparency level of the OSD - uint32 _osdFadeStartTime; // When to start the fade out - enum { - kOSDFadeOutDelay = 2 * 1000, // Delay before the OSD is faded out (in milliseconds) - kOSDFadeOutDuration = 500, // Duration of the OSD fade out (in milliseconds) - kOSDColorKey = 1, - kOSDInitialAlpha = 80 // Initial alpha level, in percent - }; - - // hardware screen - SDL_Surface *_hwscreen; - - // unseen game screen - SDL_Surface *_screen; - - // temporary screen (for scalers) - SDL_Surface *_tmpscreen; - SDL_Surface *_tmpscreen2; - - // overlay - SDL_Surface *_overlayscreen; - bool _overlayVisible; - Graphics::PixelFormat _overlayFormat; - - enum { - kTransactionNone = 0, - kTransactionActive = 1, - kTransactionRollback = 2 - }; - - struct TransactionDetails { - bool sizeChanged; - bool needHotswap; - bool needUpdatescreen; - bool normal1xScaler; - }; - TransactionDetails _transactionDetails; - - struct VideoState { - bool setup; - - bool fullscreen; - bool aspectRatioCorrection; - - int mode; - int scaleFactor; - - int screenWidth, screenHeight; - int overlayWidth, overlayHeight; - }; - VideoState _videoMode, _oldVideoMode; - - virtual void setGraphicsModeIntern(); // overloaded by CE backend - - /** Force full redraw on next updateScreen */ - bool _forceFull; - ScalerProc *_scalerProc; - int _scalerType; - int _transactionMode; - - bool _screenIsLocked; - Graphics::Surface _framebuffer; - - /** Current video mode flags (see DF_* constants) */ - bool _modeChanged; - int _screenChangeCount; - - /* True if zoom on mouse is enabled. (only set by > 240 high games) */ - bool _adjustZoomOnMouse; - - enum { - NUM_DIRTY_RECT = 100, - MAX_MOUSE_W = 80, - MAX_MOUSE_H = 80, - MAX_SCALING = 3 - }; - - // Dirty rect management - SDL_Rect _dirtyRectList[NUM_DIRTY_RECT]; - int _numDirtyRects; - - // Keyboard mouse emulation. Disabled by fingolfin 2004-12-18. - // I am keeping the rest of the code in for now, since the joystick - // code (or rather, "hack") uses it, too. - struct KbdMouse { - int16 x, y, x_vel, y_vel, x_max, y_max, x_down_count, y_down_count; - uint32 last_time, delay_time, x_down_time, y_down_time; - }; - - struct MousePos { - // The mouse position, using either virtual (game) or real - // (overlay) coordinates. - int16 x, y; - - // The size and hotspot of the original cursor image. - int16 w, h; - int16 hotX, hotY; - - // The size and hotspot of the pre-scaled cursor image, in real - // coordinates. - int16 rW, rH; - int16 rHotX, rHotY; - - // The size and hotspot of the pre-scaled cursor image, in game - // coordinates. - int16 vW, vH; - int16 vHotX, vHotY; - - 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) - { } - }; - - // mouse - KbdMouse _km; - bool _mouseVisible; - bool _mouseNeedsRedraw; - byte *_mouseData; - SDL_Rect _mouseBackup; - MousePos _mouseCurState; - byte _mouseKeyColor; - int _cursorTargetScale; - bool _cursorPaletteDisabled; - SDL_Surface *_mouseOrigSurface; - SDL_Surface *_mouseSurface; - enum { - kMouseColorKey = 1 - }; - - // joystick - SDL_Joystick *_joystick; - bool _stickBtn[32]; - - // Shake mode - int _currentShakePos; - int _newShakePos; - - // Palette data - SDL_Color *_currentPalette; - uint _paletteDirtyStart, _paletteDirtyEnd; - - // Cursor palette data - SDL_Color *_cursorPalette; - - /** - * Mutex which prevents multiple threads from interfering with each other - * when accessing the screen. - */ - MutexRef _graphicsMutex; - -#ifdef MIXER_DOUBLE_BUFFERING - SDL_mutex *_soundMutex; - SDL_cond *_soundCond; - SDL_Thread *_soundThread; - bool _soundThreadIsRunning; - bool _soundThreadShouldQuit; - - byte _activeSoundBuf; - uint _soundBufSize; - byte *_soundBuffers[2]; - - void mixerProducerThread(); - static int SDLCALL mixerProducerThreadEntry(void *arg); - void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize); - void deinitThreadedMixer(); -#endif - - FilesystemFactory *_fsFactory; - Common::SaveFileManager *_savefile; - Audio::MixerImpl *_mixer; - - SDL_TimerID _timerID; - Common::TimerManager *_timer; - protected: - virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); - - void drawMouse(); - void undrawMouse(); - void blitCursor(); - - /** Set the position of the virtual mouse cursor. */ - void setMousePos(int x, int y); - void fillMouseEvent(Common::Event &event, int x, int y); - void toggleMouseGrab(); - - void internUpdateScreen(); - - bool loadGFXMode(); - void unloadGFXMode(); - bool hotswapGFXMode(); - - void setFullscreenMode(bool enable); - void setAspectRatioCorrection(bool enable); - - void setZoomOnMouse(); // GP2X: On > 240 high games zooms on the mouse + radius. - - bool saveScreenshot(const char *filename); - - int effectiveScreenHeight() const; - - void setupIcon(); - void handleKbdMouse(); - - virtual bool remapKey(SDL_Event &ev, Common::Event &event); - - void handleScalerHotkeys(const SDL_KeyboardEvent &key); - - void moveStick(); - int _gp2xInputType; + virtual void initSDL(); }; -#endif // GP2X_COMMON_H +#endif diff --git a/backends/platform/gp2x/gp2x-main.cpp b/backends/platform/gp2x/gp2x-main.cpp new file mode 100644 index 0000000000..8dc5be764b --- /dev/null +++ b/backends/platform/gp2x/gp2x-main.cpp @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/platform/gp2x/gp2x-sdl.h" +#include "backends/plugins/posix/posix-provider.h" +#include "base/main.h" + +int main(int argc, char *argv[]) { + + // Create our OSystem instance + g_system = new OSystem_GP2X(); + assert(g_system); + + // Pre initialize the backend + ((OSystem_GP2X *)g_system)->init(); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + + // Free OSystem + delete (OSystem_GP2X *)g_system; + + return res; +} diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 88d4f9d632..b4396db0ea 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -23,29 +23,19 @@ * */ -/* - * GP2X: Main backend. - * - */ - #include "backends/platform/gp2x/gp2x-common.h" #include "backends/platform/gp2x/gp2x-hw.h" #include "backends/platform/gp2x/gp2x-mem.h" -#include "common/archive.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/EventRecorder.h" -#include "common/events.h" -#include "common/util.h" - -#include "common/file.h" -#include "base/main.h" +#include "backends/graphics/gp2xsdl/gp2xsdl-graphics.h" +#include "backends/events/gp2xsdl/gp2xsdl-events.h" #include "backends/saves/default/default-saves.h" -#include "backends/timer/default/default-timer.h" -#include "backends/plugins/posix/posix-provider.h" -#include "sound/mixer_intern.h" +#include "common/config-manager.h" +#include "common/debug.h" + +// Disable for normal serial logging. +#define DUMP_STDOUT #include <stdio.h> #include <stdlib.h> @@ -53,66 +43,11 @@ #include <limits.h> #include <errno.h> #include <sys/stat.h> -#include <time.h> // for getTimeAndDate() - -// Disable for normal serial logging. -#define DUMP_STDOUT - -#define SAMPLES_PER_SEC 11025 -//#define SAMPLES_PER_SEC 22050 -//#define SAMPLES_PER_SEC 44100 - -#define DEFAULT_CONFIG_FILE ".scummvmrc" - -#include "backends/fs/posix/posix-fs-factory.h" - -static Uint32 timer_handler(Uint32 interval, void *param) { - ((DefaultTimerManager *)param)->handler(); - return interval; -} - -int main(int argc, char *argv[]) { - g_system = new OSystem_GP2X(); - assert(g_system); - -#ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); -#endif - - // Invoke the actual ScummVM main entry point: - int res = scummvm_main(argc, argv); - g_system->quit(); - return res; -} - -OSystem *OSystem_GP2X_create() { - return new OSystem_GP2X(); -} void OSystem_GP2X::initBackend() { - assert(!_inited); - - ConfMan.setInt("joystick_num", 0); - int joystick_num = ConfMan.getInt("joystick_num"); - uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_EVENTTHREAD; - - if (ConfMan.hasKey("disable_sdl_parachute")) - sdlFlags |= SDL_INIT_NOPARACHUTE; - - if (joystick_num > -1) - sdlFlags |= SDL_INIT_JOYSTICK; - - if (SDL_Init(sdlFlags) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); - } - // Setup default save path to be workingdir/saves - #ifndef PATH_MAX - #define PATH_MAX 255 - #endif - - char savePath[PATH_MAX+1]; - char workDirName[PATH_MAX+1]; + char savePath[PATH_MAX + 1]; + char workDirName[PATH_MAX + 1]; if (getcwd(workDirName, PATH_MAX) == NULL) { error("Could not obtain current working directory."); @@ -134,8 +69,8 @@ void OSystem_GP2X::initBackend() { #ifdef DUMP_STDOUT // The GP2X has a serial console but most users do not use this so we // output all our STDOUT and STDERR to files for debug purposes. - char STDOUT_FILE[PATH_MAX+1]; - char STDERR_FILE[PATH_MAX+1]; + char STDOUT_FILE[PATH_MAX + 1]; + char STDERR_FILE[PATH_MAX + 1]; strcpy(STDOUT_FILE, workDirName); strcpy(STDERR_FILE, workDirName); @@ -175,12 +110,7 @@ void OSystem_GP2X::initBackend() { printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); #endif /* DUMP_STDOUT */ - _graphicsMutex = createMutex(); - - SDL_ShowCursor(SDL_DISABLE); - // Setup other defaults. - ConfMan.registerDefault("aspect_ratio", true); /* Up default volume values as we use a seperate system level volume anyway. */ @@ -189,143 +119,47 @@ void OSystem_GP2X::initBackend() { ConfMan.registerDefault("speech_volume", 192); ConfMan.registerDefault("autosave_period", 3 * 60); // Trigger autosave every 3 minutes - On low batts 4 mins is about your warning time. - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); - memset(&_videoMode, 0, sizeof(_videoMode)); - memset(&_transactionDetails, 0, sizeof(_transactionDetails)); - - _videoMode.mode = GFX_NORMAL; - _videoMode.scaleFactor = 1; - _scalerProc = Normal1x; - _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); - _scalerType = 0; - _adjustZoomOnMouse = false; ConfMan.setBool("FM_low_quality", true); - // enable joystick - if (joystick_num > -1 && SDL_NumJoysticks() > 0) { - _joystick = SDL_JoystickOpen(joystick_num); - } - - _savefile = new DefaultSaveFileManager(); - // Create and hook up the mixer, if none exists yet (we check for this to - // allow subclasses to provide their own). - if (_mixer == 0) { - setupMixer(); - } - - // Create and hook up the timer manager, if none exists yet (we check for - // this to allow subclasses to provide their own). - if (_timer == 0) { - // Note: We could implement a custom SDLTimerManager by using - // SDL_AddTimer. That might yield better timer resolution, but it would - // also change the semantics of a timer: Right now, ScummVM timers - // *never* run in parallel, due to the way they are implemented. If we - // switched to SDL_AddTimer, each timer might run in a separate thread. - // However, not all our code is prepared for that, so we can't just - // switch. Still, it's a potential future change to keep in mind. - _timer = new DefaultTimerManager(); - _timerID = SDL_AddTimer(10, &timer_handler, _timer); - } - /* Initialise any GP2X specific stuff we may want (Batt Status, scaler etc.) */ GP2X_HW::deviceInit(); /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */ GP2X_HW::mixerMoveVolume(0); - OSystem::initBackend(); + // Create the events manager + if (_eventManager == 0) + _eventManager = new GP2XSdlEventManager(this); - _inited = true; -} - -OSystem_GP2X::OSystem_GP2X() - : - _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0), - _hwscreen(0), _screen(0), _tmpscreen(0), - _overlayVisible(false), - _overlayscreen(0), _tmpscreen2(0), - _scalerProc(0), _modeChanged(false), _screenChangeCount(0), - _mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0), - _mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true), - _joystick(0), - _currentShakePos(0), _newShakePos(0), - _paletteDirtyStart(0), _paletteDirtyEnd(0), -#ifdef MIXER_DOUBLE_BUFFERING - _soundMutex(0), _soundCond(0), _soundThread(0), - _soundThreadIsRunning(false), _soundThreadShouldQuit(false), -#endif - _fsFactory(0), - _savefile(0), - _mixer(0), - _timer(0), - _screenIsLocked(false), - _graphicsMutex(0), _transactionMode(kTransactionNone) { - - // allocate palette storage - _currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); - _cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); - - _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; - - // reset mouse state - memset(&_km, 0, sizeof(_km)); - memset(&_mouseCurState, 0, sizeof(_mouseCurState)); - - _inited = false; - _fsFactory = new POSIXFilesystemFactory(); -} - -OSystem_GP2X::~OSystem_GP2X() { - SDL_RemoveTimer(_timerID); - closeMixer(); + // Create the graphics manager + if (_graphicsManager == 0) + _graphicsManager = new GP2XSdlGraphicsManager(); - free(_currentPalette); - free(_cursorPalette); - free(_mouseData); - - delete _savefile; - delete _timer; + // Call parent implementation of this method + OSystem_POSIX::initBackend(); } -uint32 OSystem_GP2X::getMillis() { - uint32 millis = SDL_GetTicks(); - g_eventRec.processMillis(millis); - return millis; -} +void OSystem_GP2X::initSDL() { + // Check if SDL has not been initialized + if (!_initedSDL) { + uint32 sdlFlags = SDL_INIT_EVENTTHREAD; + if (ConfMan.hasKey("disable_sdl_parachute")) + sdlFlags |= SDL_INIT_NOPARACHUTE; -void OSystem_GP2X::delayMillis(uint msecs) { - SDL_Delay(msecs); -} + // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers) + if (SDL_Init(sdlFlags) == -1) + error("Could not initialize SDL: %s", SDL_GetError()); -void OSystem_GP2X::getTimeAndDate(TimeDate &td) const { - time_t curTime = time(0); - struct tm t = *localtime(&curTime); - td.tm_sec = t.tm_sec; - td.tm_min = t.tm_min; - td.tm_hour = t.tm_hour; - td.tm_mday = t.tm_mday; - td.tm_mon = t.tm_mon; - td.tm_year = t.tm_year; -} + // Enable unicode support if possible + SDL_EnableUNICODE(1); -Common::TimerManager *OSystem_GP2X::getTimerManager() { - assert(_timer); - return _timer; -} - -Common::SaveFileManager *OSystem_GP2X::getSavefileManager() { - assert(_savefile); - return _savefile; -} - -FilesystemFactory *OSystem_GP2X::getFilesystemFactory() { - assert(_fsFactory); - return _fsFactory; + _initedSDL = true; + } } void OSystem_GP2X::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { /* Setup default extra data paths for engine data files and plugins */ - char workDirName[PATH_MAX+1]; + char workDirName[PATH_MAX + 1]; if (getcwd(workDirName, PATH_MAX) == NULL) { error("Error: Could not obtain current working directory."); @@ -357,283 +191,14 @@ void OSystem_GP2X::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) } } -static Common::String getDefaultConfigFileName() { - char configFile[MAXPATHLEN]; - strcpy(configFile, DEFAULT_CONFIG_FILE); - return configFile; -} - -Common::SeekableReadStream *OSystem_GP2X::createConfigReadStream() { - Common::FSNode file(getDefaultConfigFileName()); - return file.createReadStream(); -} - -Common::WriteStream *OSystem_GP2X::createConfigWriteStream() { - Common::FSNode file(getDefaultConfigFileName()); - return file.createWriteStream(); -} - -bool OSystem_GP2X::hasFeature(Feature f) { - return - (f == kFeatureFullscreenMode) || - (f == kFeatureAspectRatioCorrection) || - (f == kFeatureCursorHasPalette); -} - -void OSystem_GP2X::setFeatureState(Feature f, bool enable) { - switch (f) { - case kFeatureFullscreenMode: - return; - case kFeatureAspectRatioCorrection: - setAspectRatioCorrection(enable); - break; - case kFeatureDisableKeyFiltering: - // TODO: Extend as more support for this is added to engines. - return; - default: - break; - } -} - -bool OSystem_GP2X::getFeatureState(Feature f) { - assert (_transactionMode == kTransactionNone); - - switch (f) { - case kFeatureFullscreenMode: - return false; - case kFeatureAspectRatioCorrection: - return _videoMode.aspectRatioCorrection; - default: - return false; - } -} - void OSystem_GP2X::quit() { - unloadGFXMode(); - deleteMutex(_graphicsMutex); - - if (_joystick) - SDL_JoystickClose(_joystick); GP2X_HW::deviceDeinit(); - SDL_RemoveTimer(_timerID); - closeMixer(); - - free(_currentPalette); - free(_cursorPalette); - free(_mouseData); - - delete _timer; - SDL_ShowCursor(SDL_ENABLE); - SDL_Quit(); - - delete getEventManager(); - delete _savefile; - #ifdef DUMP_STDOUT printf("%s\n", "Debug: STDOUT and STDERR text files closed."); fclose(stdout); fclose(stderr); #endif /* DUMP_STDOUT */ - exit(0); -} - -OSystem::MutexRef OSystem_GP2X::createMutex(void) { - return (MutexRef) SDL_CreateMutex(); -} - -void OSystem_GP2X::lockMutex(MutexRef mutex) { - SDL_mutexP((SDL_mutex *) mutex); -} - -void OSystem_GP2X::unlockMutex(MutexRef mutex) { - SDL_mutexV((SDL_mutex *) mutex); -} - -void OSystem_GP2X::deleteMutex(MutexRef mutex) { - SDL_DestroyMutex((SDL_mutex *) mutex); -} - -#pragma mark - -#pragma mark --- Audio --- -#pragma mark - - -#ifdef MIXER_DOUBLE_BUFFERING - -void OSystem_GP2X::mixerProducerThread() { - byte nextSoundBuffer; - - SDL_LockMutex(_soundMutex); - while (true) { - // Wait till we are allowed to produce data - SDL_CondWait(_soundCond, _soundMutex); - - if (_soundThreadShouldQuit) - break; - - // Generate samples and put them into the next buffer - nextSoundBuffer = _activeSoundBuf ^ 1; - _mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize); - - // Swap buffers - _activeSoundBuf = nextSoundBuffer; - } - SDL_UnlockMutex(_soundMutex); -} - -int SDLCALL OSystem_GP2X::mixerProducerThreadEntry(void *arg) { - OSystem_GP2X *this_ = (OSystem_GP2X *)arg; - assert(this_); - this_->mixerProducerThread(); - return 0; -} - - -void OSystem_GP2X::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) { - _soundThreadIsRunning = false; - _soundThreadShouldQuit = false; - - // Create mutex and condition variable - _soundMutex = SDL_CreateMutex(); - _soundCond = SDL_CreateCond(); - - // Create two sound buffers - _activeSoundBuf = 0; - _soundBufSize = bufSize; - _soundBuffers[0] = (byte *)calloc(1, bufSize); - _soundBuffers[1] = (byte *)calloc(1, bufSize); - - _soundThreadIsRunning = true; - - // Finally start the thread - _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this); -} - -void OSystem_GP2X::deinitThreadedMixer() { - // Kill thread?? _soundThread - - if (_soundThreadIsRunning) { - // Signal the producer thread to end, and wait for it to actually finish. - _soundThreadShouldQuit = true; - SDL_CondBroadcast(_soundCond); - SDL_WaitThread(_soundThread, NULL); - - // Kill the mutex & cond variables. - // Attention: AT this point, the mixer callback must not be running - // anymore, else we will crash! - SDL_DestroyMutex(_soundMutex); - SDL_DestroyCond(_soundCond); - - _soundThreadIsRunning = false; - - free(_soundBuffers[0]); - free(_soundBuffers[1]); - } -} - - -void OSystem_GP2X::mixCallback(void *arg, byte *samples, int len) { - OSystem_GP2X *this_ = (OSystem_GP2X *)arg; - assert(this_); - assert(this_->_mixer); - - assert((int)this_->_soundBufSize == len); - - // Lock mutex, to ensure our data is not overwritten by the producer thread - SDL_LockMutex(this_->_soundMutex); - - // Copy data from the current sound buffer - memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len); - - // Unlock mutex and wake up the produced thread - SDL_UnlockMutex(this_->_soundMutex); - SDL_CondSignal(this_->_soundCond); -} - -#else - -void OSystem_GP2X::mixCallback(void *sys, byte *samples, int len) { - OSystem_GP2X *this_ = (OSystem_GP2X *)sys; - assert(this_); - assert(this_->_mixer); - - this_->_mixer->mixCallback(samples, len); -} - -#endif - -void OSystem_GP2X::setupMixer() { - SDL_AudioSpec desired; - SDL_AudioSpec obtained; - - // Determine the desired output sampling frequency. - uint32 samplesPerSec = 0; - if (ConfMan.hasKey("output_rate")) - samplesPerSec = ConfMan.getInt("output_rate"); - if (samplesPerSec <= 0) - samplesPerSec = SAMPLES_PER_SEC; - - // Determine the sample buffer size. We want it to store enough data for - // at least 1/16th of a second (though at most 8192 samples). Note - // that it must be a power of two. So e.g. at 22050 Hz, we request a - // sample buffer size of 2048. - uint32 samples = 8192; - while (samples * 16 > samplesPerSec * 2) - samples >>= 1; - - memset(&desired, 0, sizeof(desired)); - desired.freq = samplesPerSec; - desired.format = AUDIO_S16SYS; - desired.channels = 2; - //desired.samples = (uint16)samples; - desired.samples = 128; // Samples hack - desired.callback = mixCallback; - desired.userdata = this; - - assert(!_mixer); - if (SDL_OpenAudio(&desired, &obtained) != 0) { - warning("Could not open audio device: %s", SDL_GetError()); - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(false); - } else { - // Note: This should be the obtained output rate, but it seems that at - // least on some platforms SDL will lie and claim it did get the rate - // even if it didn't. Probably only happens for "weird" rates, though. - samplesPerSec = obtained.freq; - debug(1, "Output sample rate: %d Hz", samplesPerSec); - - // Create the mixer instance and start the sound processing - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(true); - -#ifdef MIXER_DOUBLE_BUFFERING - initThreadedMixer(_mixer, obtained.samples * 4); -#endif - - // start the sound system - SDL_PauseAudio(0); - } -} - -void OSystem_GP2X::closeMixer() { - if (_mixer) - _mixer->setReady(false); - - SDL_CloseAudio(); - - delete _mixer; - _mixer = 0; - -#ifdef MIXER_DOUBLE_BUFFERING - deinitThreadedMixer(); -#endif - -} - -Audio::Mixer *OSystem_GP2X::getMixer() { - assert(_mixer); - return _mixer; + OSystem_POSIX::quit(); } diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp deleted file mode 100644 index 4a3c668c52..0000000000 --- a/backends/platform/gp2x/graphics.cpp +++ /dev/null @@ -1,1679 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * GP2X: Graphics handling. - * - */ - -#include "backends/platform/gp2x/gp2x-common.h" -#include "common/util.h" -#include "common/mutex.h" -#include "common/str-array.h" -#include "graphics/font.h" -#include "graphics/fontman.h" -#include "graphics/scaler.h" -#include "graphics/scaler/aspect.h" -#include "graphics/surface.h" - -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"Fullscreen", "1x", GFX_NORMAL}, - {0, 0, 0} -}; - -// Table of relative scalers magnitudes -// [definedScale - 1][_scaleFactor - 1] -static ScalerProc *scalersMagn[3][3] = { - { Normal1x, Normal1x, Normal1x }, - { Normal1x, Normal1x, Normal1x }, - { Normal1x, Normal1x, Normal1x } -}; - -static const int s_gfxModeSwitchTable[][4] = { - { GFX_NORMAL } - }; - -static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY); - -const OSystem::GraphicsMode *OSystem_GP2X::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; -} - -int OSystem_GP2X::getDefaultGraphicsMode() const { - return GFX_NORMAL; -} - -void OSystem_GP2X::beginGFXTransaction(void) { - assert(_transactionMode == kTransactionNone); - - _transactionMode = kTransactionActive; - - _transactionDetails.sizeChanged = false; - - _transactionDetails.needHotswap = false; - _transactionDetails.needUpdatescreen = false; - - _transactionDetails.normal1xScaler = false; - - _oldVideoMode = _videoMode; -} - -OSystem::TransactionError OSystem_GP2X::endGFXTransaction(void) { - int errors = kTransactionSuccess; - - assert(_transactionMode != kTransactionNone); - - if (_transactionMode == kTransactionRollback) { - if (_videoMode.fullscreen != _oldVideoMode.fullscreen) { - errors |= kTransactionFullscreenFailed; - - _videoMode.fullscreen = _oldVideoMode.fullscreen; - } else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) { - errors |= kTransactionAspectRatioFailed; - - _videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection; - } else if (_videoMode.mode != _oldVideoMode.mode) { - errors |= kTransactionModeSwitchFailed; - - _videoMode.mode = _oldVideoMode.mode; - _videoMode.scaleFactor = _oldVideoMode.scaleFactor; - } else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) { - errors |= kTransactionSizeChangeFailed; - - _videoMode.screenWidth = _oldVideoMode.screenWidth; - _videoMode.screenHeight = _oldVideoMode.screenHeight; - _videoMode.overlayWidth = _oldVideoMode.overlayWidth; - _videoMode.overlayHeight = _oldVideoMode.overlayHeight; - } - - if (_videoMode.fullscreen == _oldVideoMode.fullscreen && - _videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection && - _videoMode.mode == _oldVideoMode.mode && - _videoMode.screenWidth == _oldVideoMode.screenWidth && - _videoMode.screenHeight == _oldVideoMode.screenHeight) { - - // Our new video mode would now be exactly the same as the - // old one. Since we still can not assume SDL_SetVideoMode - // to be working fine, we need to invalidate the old video - // mode, so loadGFXMode would error out properly. - _oldVideoMode.setup = false; - } - } - - if (_transactionDetails.sizeChanged) { - unloadGFXMode(); - if (!loadGFXMode()) { - if (_oldVideoMode.setup) { - _transactionMode = kTransactionRollback; - errors |= endGFXTransaction(); - } - } else { - setGraphicsModeIntern(); - clearOverlay(); - - _videoMode.setup = true; - _modeChanged = true; - // OSystem_SDL::pollEvent used to update the screen change count, - // but actually it gives problems when a video mode was changed - // but OSystem_SDL::pollEvent was not called. This for example - // caused a crash under certain circumstances when doing an RTL. - // To fix this issue we update the screen change count right here. - _screenChangeCount++; - } - } else if (_transactionDetails.needHotswap) { - setGraphicsModeIntern(); - if (!hotswapGFXMode()) { - if (_oldVideoMode.setup) { - _transactionMode = kTransactionRollback; - errors |= endGFXTransaction(); - } - } else { - _videoMode.setup = true; - _modeChanged = true; - // OSystem_SDL::pollEvent used to update the screen change count, - // but actually it gives problems when a video mode was changed - // but OSystem_SDL::pollEvent was not called. This for example - // caused a crash under certain circumstances when doing an RTL. - // To fix this issue we update the screen change count right here. - _screenChangeCount++; - - if (_transactionDetails.needUpdatescreen) - internUpdateScreen(); - } - } else if (_transactionDetails.needUpdatescreen) { - setGraphicsModeIntern(); - internUpdateScreen(); - } - - _transactionMode = kTransactionNone; - return (TransactionError)errors; -} - -bool OSystem_GP2X::setGraphicsMode(int mode) { - Common::StackLock lock(_graphicsMutex); - - assert(_transactionMode == kTransactionActive); - - if (_oldVideoMode.setup && _oldVideoMode.mode == mode) - return true; - - int newScaleFactor = 1; - - switch (mode) { - case GFX_NORMAL: - newScaleFactor = 1; - break; - default: - warning("unknown gfx mode %d", mode); - return false; - } - - _transactionDetails.normal1xScaler = (mode == GFX_NORMAL); - if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) - _transactionDetails.needHotswap = true; - - _transactionDetails.needUpdatescreen = true; - - _videoMode.mode = mode; - _videoMode.scaleFactor = newScaleFactor; - - return true; -} - -void OSystem_GP2X::setGraphicsModeIntern() { - Common::StackLock lock(_graphicsMutex); - ScalerProc *newScalerProc = 0; - - switch (_videoMode.mode) { - case GFX_NORMAL: - newScalerProc = Normal1x; - break; - - default: - error("Unknown gfx mode %d", _videoMode.mode); - } - - _scalerProc = newScalerProc; - - if (_videoMode.mode != GFX_NORMAL) { - for (int i = 0; i < ARRAYSIZE(s_gfxModeSwitchTable); i++) { - if (s_gfxModeSwitchTable[i][1] == _videoMode.mode || s_gfxModeSwitchTable[i][2] == _videoMode.mode) { - _scalerType = i; - break; - } - } - } - - if (!_screen || !_hwscreen) - return; - - // Blit everything to the screen - _forceFull = true; - - // Even if the old and new scale factors are the same, we may have a - // different scaler for the cursor now. - blitCursor(); -} - -int OSystem_GP2X::getGraphicsMode() const { - assert (_transactionMode == kTransactionNone); - return _videoMode.mode; -} - -void OSystem_GP2X::initSize(uint w, uint h, const Graphics::PixelFormat *format) { - assert(_transactionMode == kTransactionActive); - -#ifdef USE_RGB_COLOR - //avoid redundant format changes - Graphics::PixelFormat newFormat; - if (!format) - newFormat = Graphics::PixelFormat::createFormatCLUT8(); - else - newFormat = *format; - - assert(newFormat.bytesPerPixel > 0); - - if (newFormat != _videoMode.format) - { - _videoMode.format = newFormat; - _transactionDetails.formatChanged = true; - _screenFormat = newFormat; - } -#endif - - // Avoid redundant res changes - if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight) - return; - - _videoMode.screenWidth = w; - _videoMode.screenHeight = h; - - _transactionDetails.sizeChanged = true; -} - -int OSystem_GP2X::effectiveScreenHeight() const { - return (_videoMode.aspectRatioCorrection ? real2Aspect(_videoMode.screenHeight) : _videoMode.screenHeight) - * _videoMode.scaleFactor; -} - - -bool OSystem_GP2X::loadGFXMode() { - assert(_inited); - _forceFull = true; - - int hwW, hwH; - - _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; - - if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) - _videoMode.aspectRatioCorrection = false; - - if (_videoMode.aspectRatioCorrection) - _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); - - hwW = _videoMode.screenWidth * _videoMode.scaleFactor; - - if (_videoMode.screenHeight == 200) { - hwH = 240; - } else if (_videoMode.screenHeight == 400) { - hwH = 480; - } else { - hwH = _videoMode.screenHeight; - } - - printf ("Game Screen Height: %d\n", hwH); - - // - // Create the surface that contains the game data - // - - _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, hwH, 8, 0, 0, 0, 0); - if (_screen == NULL) - error("allocating _screen failed"); - - // - // Create the surface that contains the scaled graphics in 16 bit mode - // - - _hwscreen = SDL_SetVideoMode(hwW, hwH, 16, SDL_SWSURFACE | SDL_NOFRAME | SDL_FULLSCREEN); - 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()); - quit(); - } else { - return false; - } - } - - // GP2X Specific, must be called after any SDL_SetVideoMode to ensure the hardware cursor is off. - // Note: On the GP2X SDL_SetVideoMode recalls SDL_Init(). - SDL_ShowCursor(SDL_DISABLE); - - // - // Create the surface used for the graphics in 16 bit before scaling, and also the overlay - // - - // Need some extra bytes around when using 2xSaI - _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); - - if (_tmpscreen == NULL) - error("allocating _tmpscreen failed"); - - _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); - - if (_overlayscreen == NULL) - error("allocating _overlayscreen failed"); - - _overlayFormat.bytesPerPixel = _overlayscreen->format->BytesPerPixel; - - _overlayFormat.rLoss = _overlayscreen->format->Rloss; - _overlayFormat.gLoss = _overlayscreen->format->Gloss; - _overlayFormat.bLoss = _overlayscreen->format->Bloss; - _overlayFormat.aLoss = _overlayscreen->format->Aloss; - - _overlayFormat.rShift = _overlayscreen->format->Rshift; - _overlayFormat.gShift = _overlayscreen->format->Gshift; - _overlayFormat.bShift = _overlayscreen->format->Bshift; - _overlayFormat.aShift = _overlayscreen->format->Ashift; - - _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); - - if (_tmpscreen2 == NULL) - error("allocating _tmpscreen2 failed"); - - _osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, - _hwscreen->w, - _hwscreen->h, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); - if (_osdSurface == NULL) - error("allocating _osdSurface failed"); - SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey); - - // keyboard cursor control, some other better place for it? - _km.x_max = _videoMode.screenWidth * _videoMode.scaleFactor - 1; - _km.y_max = effectiveScreenHeight() - 1; - _km.delay_time = 25; - _km.last_time = 0; - - // Distinguish 555 and 565 mode - if (_hwscreen->format->Rmask == 0x7C00) - InitScalers(555); - else - InitScalers(565); - - return true; -} - -void OSystem_GP2X::unloadGFXMode() { - if (_screen) { - SDL_FreeSurface(_screen); - _screen = NULL; - } - - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; - } - - if (_tmpscreen) { - SDL_FreeSurface(_tmpscreen); - _tmpscreen = NULL; - } - - if (_tmpscreen2) { - SDL_FreeSurface(_tmpscreen2); - _tmpscreen2 = NULL; - } - - if (_overlayscreen) { - SDL_FreeSurface(_overlayscreen); - _overlayscreen = NULL; - } - - if (_osdSurface) { - SDL_FreeSurface(_osdSurface); - _osdSurface = NULL; - } - DestroyScalers(); -} - -bool OSystem_GP2X::hotswapGFXMode() { - if (!_screen) - return false; - - // Keep around the old _screen & _overlayscreen so we can restore the screen data - // after the mode switch. - SDL_Surface *old_screen = _screen; - SDL_Surface *old_overlayscreen = _overlayscreen; - _screen = NULL; - _overlayscreen = NULL; - - // Release the HW screen surface - SDL_FreeSurface(_hwscreen); _hwscreen = NULL; - - SDL_FreeSurface(_tmpscreen); _tmpscreen = NULL; - SDL_FreeSurface(_tmpscreen2); _tmpscreen2 = NULL; - - // Release the OSD surface - SDL_FreeSurface(_osdSurface); _osdSurface = NULL; - - // Setup the new GFX mode - if (!loadGFXMode()) { - unloadGFXMode(); - - _screen = old_screen; - _overlayscreen = old_overlayscreen; - - return false; - } - - // reset palette - SDL_SetColors(_screen, _currentPalette, 0, 256); - - // Restore old screen content - SDL_BlitSurface(old_screen, NULL, _screen, NULL); - SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL); - - // Free the old surfaces - SDL_FreeSurface(old_screen); - SDL_FreeSurface(old_overlayscreen); - - // Update cursor to new scale - blitCursor(); - - // Blit everything to the screen - internUpdateScreen(); - - return true; -} - -void OSystem_GP2X::updateScreen() { - assert (_transactionMode == kTransactionNone); - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - - internUpdateScreen(); -} - -void OSystem_GP2X::internUpdateScreen() { - SDL_Surface *srcSurf, *origSurf; - int height, width; - ScalerProc *scalerProc; - int scale1; - -#if defined (DEBUG) && ! defined(_WIN32_WCE) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) - assert(_hwscreen != NULL); - assert(_hwscreen->map->sw_data != NULL); -#endif - - // If the shake position changed, fill the dirty area with blackness - if (_currentShakePos != _newShakePos) { - SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor}; - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - blackrect.h = real2Aspect(blackrect.h - 1) + 1; - - SDL_FillRect(_hwscreen, &blackrect, 0); - - _currentShakePos = _newShakePos; - - _forceFull = true; - } - - // Check whether the palette was changed in the meantime and update the - // screen surface accordingly. - if (_screen && _paletteDirtyEnd != 0) { - SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, - _paletteDirtyStart, - _paletteDirtyEnd - _paletteDirtyStart); - - _paletteDirtyEnd = 0; - - _forceFull = true; - } - // OSD visible (i.e. non-transparent)? - if (_osdAlpha != SDL_ALPHA_TRANSPARENT) { - // Updated alpha value - const int diff = SDL_GetTicks() - _osdFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdAlpha = SDL_ALPHA_TRANSPARENT; - } else { - // Do a linear fade out... - const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; - } - SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha); - _forceFull = true; - } - } - - if (!_overlayVisible) { - origSurf = _screen; - srcSurf = _tmpscreen; - width = _videoMode.screenWidth; - height = _videoMode.screenHeight; - scalerProc = _scalerProc; - scale1 = _videoMode.scaleFactor; - } else { - origSurf = _overlayscreen; - srcSurf = _tmpscreen2; - width = _videoMode.overlayWidth; - height = _videoMode.overlayHeight; - scalerProc = Normal1x; - - scale1 = 1; - } - - // Add the area covered by the mouse cursor to the list of dirty rects if - // we have to redraw the mouse. - if (_mouseNeedsRedraw) - undrawMouse(); - - // Force a full redraw if requested - if (_forceFull) { - _numDirtyRects = 1; - _dirtyRectList[0].x = 0; - _dirtyRectList[0].y = 0; - _dirtyRectList[0].w = width; - _dirtyRectList[0].h = height; - } - - // Only draw anything if necessary - if (_numDirtyRects > 0 || _mouseNeedsRedraw) { - SDL_Rect *r; - SDL_Rect dst; - uint32 srcPitch, dstPitch; - SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects; - - for (r = _dirtyRectList; r != lastRect; ++r) { - dst = *r; - dst.x++; // Shift rect by one since 2xSai needs to access the data around - dst.y++; // any pixel to scale it, and we want to avoid mem access crashes. - - if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0) - error("SDL_BlitSurface failed: %s", SDL_GetError()); - } - - SDL_LockSurface(srcSurf); - SDL_LockSurface(_hwscreen); - - srcPitch = srcSurf->pitch; - dstPitch = _hwscreen->pitch; - - for (r = _dirtyRectList; r != lastRect; ++r) { - register int dst_y = r->y + _currentShakePos; - register int dst_h = 0; - register int orig_dst_y = 0; - register int rx1 = r->x * scale1; - - if (dst_y < height) { - dst_h = r->h; - if (dst_h > height - dst_y) - dst_h = height - dst_y; - - orig_dst_y = dst_y; - dst_y = dst_y * scale1; - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - dst_y = real2Aspect(dst_y); - - assert(scalerProc != NULL); - scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); - } - - r->x = rx1; - r->y = dst_y; - r->w = r->w * scale1; - r->h = dst_h * scale1; - - if (_videoMode.aspectRatioCorrection && orig_dst_y < height && !_overlayVisible) - r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1); - } - SDL_UnlockSurface(srcSurf); - SDL_UnlockSurface(_hwscreen); - - // Readjust the dirty rect list in case we are doing a full update. - // This is necessary if shaking is active. - if (_forceFull) { - _dirtyRectList[0].y = 0; - _dirtyRectList[0].h = effectiveScreenHeight(); - } - - drawMouse(); - - if (_osdAlpha != SDL_ALPHA_TRANSPARENT) { - SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); - } - - // Finally, blit all our changes to the screen - SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); - } - - _numDirtyRects = 0; - _forceFull = false; - _mouseNeedsRedraw = false; -} - -bool OSystem_GP2X::saveScreenshot(const char *filename) { - assert(_hwscreen != NULL); - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - return SDL_SaveBMP(_hwscreen, filename) == 0; -} - -void OSystem_GP2X::setFullscreenMode(bool enable) { - Common::StackLock lock(_graphicsMutex); - - if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable) - return; - - if (_transactionMode == kTransactionActive) { - _videoMode.fullscreen = enable; - _transactionDetails.needHotswap = true; - } -} - -void OSystem_GP2X::setAspectRatioCorrection(bool enable) { - Common::StackLock lock(_graphicsMutex); - - if (_oldVideoMode.setup && _oldVideoMode.aspectRatioCorrection == enable) - return; - - if (_transactionMode == kTransactionActive) { - _videoMode.aspectRatioCorrection = enable; - _transactionDetails.needHotswap = true; - } -} - -void OSystem_GP2X::setZoomOnMouse() { - if (_adjustZoomOnMouse == true) { - _adjustZoomOnMouse = false; - return; - } else { - _adjustZoomOnMouse = true; - return; - } -} - -void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) { - assert (_transactionMode == kTransactionNone); - assert(src); - - if (_screen == NULL) { - warning("OSystem_GP2X::copyRectToScreen: _screen == NULL"); - return; - } - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - - assert(x >= 0 && x < _videoMode.screenWidth); - assert(y >= 0 && y < _videoMode.screenHeight); - assert(h > 0 && y + h <= _videoMode.screenHeight); - assert(w > 0 && x + w <= _videoMode.screenWidth); - - /* Clip the coordinates */ - if (x < 0) { - w += x; - src -= x; - x = 0; - } - - if (y < 0) { - h += y; - src -= y * pitch; - y = 0; - } - - if (w > _videoMode.screenWidth - x) { - w = _videoMode.screenWidth - x; - } - - if (h > _videoMode.screenHeight - y) { - h = _videoMode.screenHeight - y; - } - - if (w <= 0 || h <= 0) - return; - - addDirtyRect(x, y, w, h); - - // Try to lock the screen surface - if (SDL_LockSurface(_screen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x; - - if (_videoMode.screenWidth == pitch && pitch == w) { - memcpy(dst, src, h*w); - } else { - do { - memcpy(dst, src, w); - src += pitch; - dst += _videoMode.screenWidth; - } while (--h); - } - - // Unlock the screen surface - SDL_UnlockSurface(_screen); -} - -Graphics::Surface *OSystem_GP2X::lockScreen() { - assert (_transactionMode == kTransactionNone); - - // Lock the graphics mutex - lockMutex(_graphicsMutex); - - // paranoia check - assert(!_screenIsLocked); - _screenIsLocked = true; - - // Try to lock the screen surface - 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.bytesPerPixel = 1; - - return &_framebuffer; -} - -void OSystem_GP2X::unlockScreen() { - assert (_transactionMode == kTransactionNone); - - // paranoia check - assert(_screenIsLocked); - _screenIsLocked = false; - - // Unlock the screen surface - SDL_UnlockSurface(_screen); - - // Trigger a full screen update - _forceFull = true; - - // Finally unlock the graphics mutex - unlockMutex(_graphicsMutex); -} - -void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) { - if (_forceFull) - return; - - if (_numDirtyRects == NUM_DIRTY_RECT) { - _forceFull = true; - return; - } - - int height, width; - - if (!_overlayVisible && !realCoordinates) { - width = _videoMode.screenWidth; - height = _videoMode.screenHeight; - } else { - width = _videoMode.overlayWidth; - height = _videoMode.overlayHeight; - } - - // Extend the dirty region by 1 pixel for scalers - // that "smear" the screen, e.g. 2xSAI - if (!realCoordinates) { - x--; - y--; - w+=2; - h+=2; - } - - // clip - if (x < 0) { - w += x; - x = 0; - } - - if (y < 0) { - h += y; - y=0; - } - - if (w > width - x) { - w = width - x; - } - - if (h > height - y) { - h = height - y; - } - - if (_videoMode.aspectRatioCorrection && !_overlayVisible && !realCoordinates) { - makeRectStretchable(x, y, w, h); - } - - if (w == width && h == height) { - _forceFull = true; - return; - } - - if (w > 0 && h > 0) { - SDL_Rect *r = &_dirtyRectList[_numDirtyRects++]; - - r->x = x; - r->y = y; - r->w = w; - r->h = h; - } -} - -int16 OSystem_GP2X::getHeight() { - return _videoMode.screenHeight; -} - -int16 OSystem_GP2X::getWidth() { - return _videoMode.screenWidth; -} - -void OSystem_GP2X::setPalette(const byte *colors, uint start, uint num) { - assert(colors); - - // Setting the palette before _screen is created is allowed - for now - - // since we don't actually set the palette until the screen is updated. - // But it could indicate a programming error, so let's warn about it. - - if (!_screen) - warning("OSystem_SDL::setPalette: _screen == NULL"); - - const byte *b = colors; - uint i; - SDL_Color *base = _currentPalette + start; - for (i = 0; i < num; i++) { - base[i].r = b[0]; - base[i].g = b[1]; - base[i].b = b[2]; - b += 4; - } - - if (start < _paletteDirtyStart) - _paletteDirtyStart = start; - - if (start + num > _paletteDirtyEnd) - _paletteDirtyEnd = start + num; - - // Some games blink cursors with palette - if (_cursorPaletteDisabled) - blitCursor(); -} - -void OSystem_GP2X::grabPalette(byte *colors, uint start, uint num) { - assert(colors); - const SDL_Color *base = _currentPalette + start; - - for (uint i = 0; i < num; ++i) { - colors[i * 4] = base[i].r; - colors[i * 4 + 1] = base[i].g; - colors[i * 4 + 2] = base[i].b; - colors[i * 4 + 3] = 0xFF; - } -} - -void OSystem_GP2X::setCursorPalette(const byte *colors, uint start, uint num) { - assert(colors); - const byte *b = colors; - uint i; - SDL_Color *base = _cursorPalette + start; - for (i = 0; i < num; i++) { - base[i].r = b[0]; - base[i].g = b[1]; - base[i].b = b[2]; - b += 4; - } - - _cursorPaletteDisabled = false; - - blitCursor(); -} - -void OSystem_GP2X::setShakePos(int shake_pos) { - assert (_transactionMode == kTransactionNone); - - _newShakePos = shake_pos; -} - -#pragma mark - -#pragma mark --- Overlays --- -#pragma mark - - -void OSystem_GP2X::showOverlay() { - assert (_transactionMode == kTransactionNone); - - int x, y; - - if (_overlayVisible) - return; - - _overlayVisible = true; - - // Since resolution could change, put mouse to adjusted position - // Fixes bug #1349059 - x = _mouseCurState.x * _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor; - else - y = _mouseCurState.y * _videoMode.scaleFactor; - - warpMouse(x, y); - - clearOverlay(); -} - -void OSystem_GP2X::hideOverlay() { - assert (_transactionMode == kTransactionNone); - - if (!_overlayVisible) - return; - - int x, y; - - _overlayVisible = false; - - // Since resolution could change, put mouse to adjusted position - // Fixes bug #1349059 - x = _mouseCurState.x / _videoMode.scaleFactor; - y = _mouseCurState.y / _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - y = aspect2Real(y); - - warpMouse(x, y); - - clearOverlay(); - - _forceFull = true; -} - -void OSystem_GP2X::clearOverlay() { - //assert (_transactionMode == kTransactionNone); - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - - if (!_overlayVisible) - return; - - // Clear the overlay by making the game screen "look through" everywhere. - SDL_Rect src, dst; - src.x = src.y = 0; - dst.x = dst.y = 1; - src.w = dst.w = _videoMode.screenWidth; - src.h = dst.h = _videoMode.screenHeight; - if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0) - error("SDL_BlitSurface failed: %s", SDL_GetError()); - - SDL_LockSurface(_tmpscreen); - SDL_LockSurface(_overlayscreen); - _scalerProc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, _tmpscreen->pitch, - (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight); - -#ifdef USE_SCALERS - if (_videoMode.aspectRatioCorrection) - stretch200To240((uint8 *)_overlayscreen->pixels, _overlayscreen->pitch, - _videoMode.overlayWidth, _videoMode.screenHeight * _videoMode.scaleFactor, 0, 0, 0); -#endif - SDL_UnlockSurface(_tmpscreen); - SDL_UnlockSurface(_overlayscreen); - - _forceFull = true; -} - -void OSystem_GP2X::grabOverlay(OverlayColor *buf, int pitch) { - assert (_transactionMode == kTransactionNone); - - if (_overlayscreen == NULL) - return; - - if (SDL_LockSurface(_overlayscreen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - byte *src = (byte *)_overlayscreen->pixels; - int h = _videoMode.overlayHeight; - do { - memcpy(buf, src, _videoMode.overlayWidth * 2); - src += _overlayscreen->pitch; - buf += pitch; - } while (--h); - - SDL_UnlockSurface(_overlayscreen); -} - -void OSystem_GP2X::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { - assert (_transactionMode == kTransactionNone); - - if (_overlayscreen == NULL) - return; - - // Clip the coordinates - if (x < 0) { - w += x; - buf -= x; - x = 0; - } - - if (y < 0) { - h += y; buf -= y * pitch; - y = 0; - } - - if (w > _videoMode.overlayWidth - x) { - w = _videoMode.overlayWidth - x; - } - - if (h > _videoMode.overlayHeight - y) { - h = _videoMode.overlayHeight - y; - } - - if (w <= 0 || h <= 0) - return; - - // Mark the modified region as dirty - addDirtyRect(x, y, w, h); - - if (SDL_LockSurface(_overlayscreen) == -1) - error("SDL_LockSurface failed: %s", SDL_GetError()); - - byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2; - do { - memcpy(dst, buf, w * 2); - dst += _overlayscreen->pitch; - buf += pitch; - } while (--h); - - SDL_UnlockSurface(_overlayscreen); -} - - -#pragma mark - -#pragma mark --- Mouse --- -#pragma mark - - -bool OSystem_GP2X::showMouse(bool visible) { - if (_mouseVisible == visible) - return visible; - - bool last = _mouseVisible; - _mouseVisible = visible; - _mouseNeedsRedraw = true; - - return last; -} - -void OSystem_GP2X::setMousePos(int x, int y) { - if (x != _mouseCurState.x || y != _mouseCurState.y) { - _mouseNeedsRedraw = true; - _mouseCurState.x = x; - _mouseCurState.y = y; - } -} - -void OSystem_GP2X::warpMouse(int x, int y) { - int y1 = y; - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - y1 = real2Aspect(y); - - if (_mouseCurState.x != x || _mouseCurState.y != y) { - if (!_overlayVisible) - SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor); - else - SDL_WarpMouse(x, y1); - - // SDL_WarpMouse() generates a mouse movement event, so - // setMousePos() would be called eventually. However, the - // cannon script in CoMI calls this function twice each time - // the cannon is reloaded. Unless we update the mouse position - // immediately the second call is ignored, causing the cannon - // to change its aim. - - setMousePos(x, y); - } -} - -void OSystem_GP2X::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { -#ifdef USE_RGB_COLOR - if (!format) - _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); - else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel) - _cursorFormat = *format; - keycolor &= (1 << (_cursorFormat.bytesPerPixel << 3)) - 1; -#else - keycolor &= 0xFF; -#endif - - if (w == 0 || h == 0) - return; - - _mouseCurState.hotX = hotspot_x; - _mouseCurState.hotY = hotspot_y; - - _mouseKeyColor = keycolor; - - _cursorTargetScale = cursorTargetScale; - - if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) { - _mouseCurState.w = w; - _mouseCurState.h = h; - - if (_mouseOrigSurface) - SDL_FreeSurface(_mouseOrigSurface); - - // Allocate bigger surface because AdvMame2x adds black pixel at [0,0] - _mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, - _mouseCurState.w + 2, - _mouseCurState.h + 2, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); - - if (_mouseOrigSurface == NULL) - error("allocating _mouseOrigSurface failed"); - SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); - } - - free(_mouseData); -#ifdef USE_RGB_COLOR - _mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel); - memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel); -#else - _mouseData = (byte *)malloc(w * h); - memcpy(_mouseData, buf, w * h); -#endif - - blitCursor(); -} - -void OSystem_GP2X::blitCursor() { - byte *dstPtr; - const byte *srcPtr = _mouseData; -#ifdef USE_RGB_COLOR - uint32 color; - uint32 colormask = (1 << (_cursorFormat.bytesPerPixel << 3)) - 1; -#else - byte color; -#endif - int w, h, i, j; - - if (!_mouseOrigSurface || !_mouseData) - return; - - _mouseNeedsRedraw = true; - - w = _mouseCurState.w; - h = _mouseCurState.h; - - SDL_LockSurface(_mouseOrigSurface); - - // Make whole surface transparent - for (i = 0; i < h + 2; i++) { - dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i; - for (j = 0; j < w + 2; j++) { - *(uint16 *)dstPtr = kMouseColorKey; - dstPtr += 2; - } - } - - // Draw from [1,1] since AdvMame2x adds artefact at 0,0 - dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2; - - SDL_Color *palette; - - if (_cursorPaletteDisabled) - palette = _currentPalette; - else - palette = _cursorPalette; - - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { -#ifdef USE_RGB_COLOR - if (_cursorFormat.bytesPerPixel > 1) { - color = (*(uint32 *) srcPtr) & colormask; - if (color != _mouseKeyColor) { // transparent, don't draw - uint8 r,g,b; - _cursorFormat.colorToRGB(color,r,g,b); - *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, - r, g, b); - } - dstPtr += 2; - srcPtr += _cursorFormat.bytesPerPixel; - } else { -#endif - color = *srcPtr; - if (color != _mouseKeyColor) { // transparent, don't draw - *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, - palette[color].r, palette[color].g, palette[color].b); - } - dstPtr += 2; - srcPtr++; -#ifdef USE_RGB_COLOR - } -#endif - } - dstPtr += _mouseOrigSurface->pitch - w * 2; - } - - int rW, rH; - - if (_cursorTargetScale >= _videoMode.scaleFactor) { - // The cursor target scale is greater or equal to the scale at - // which the rest of the screen is drawn. We do not downscale - // the cursor image, we draw it at its original size. It will - // appear too large on screen. - - rW = w; - rH = h; - _mouseCurState.rHotX = _mouseCurState.hotX; - _mouseCurState.rHotY = _mouseCurState.hotY; - - // The virtual dimensions may be larger than the original. - - _mouseCurState.vW = w * _cursorTargetScale / _videoMode.scaleFactor; - _mouseCurState.vH = h * _cursorTargetScale / _videoMode.scaleFactor; - _mouseCurState.vHotX = _mouseCurState.hotX * _cursorTargetScale / - _videoMode.scaleFactor; - _mouseCurState.vHotY = _mouseCurState.hotY * _cursorTargetScale / - _videoMode.scaleFactor; - } else { - // The cursor target scale is smaller than the scale at which - // the rest of the screen is drawn. We scale up the cursor - // image to make it appear correct. - - rW = w * _videoMode.scaleFactor / _cursorTargetScale; - rH = h * _videoMode.scaleFactor / _cursorTargetScale; - _mouseCurState.rHotX = _mouseCurState.hotX * _videoMode.scaleFactor / - _cursorTargetScale; - _mouseCurState.rHotY = _mouseCurState.hotY * _videoMode.scaleFactor / - _cursorTargetScale; - - // The virtual dimensions will be the same as the original. - - _mouseCurState.vW = w; - _mouseCurState.vH = h; - _mouseCurState.vHotX = _mouseCurState.hotX; - _mouseCurState.vHotY = _mouseCurState.hotY; - } - - int rH1 = rH; // store original to pass to aspect-correction function later - - if (_videoMode.aspectRatioCorrection && _cursorTargetScale == 1) { - rH = real2Aspect(rH - 1) + 1; - _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY); - } - - if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) { - _mouseCurState.rW = rW; - _mouseCurState.rH = rH; - - if (_mouseSurface) - SDL_FreeSurface(_mouseSurface); - - _mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, - _mouseCurState.rW, - _mouseCurState.rH, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); - - if (_mouseSurface == NULL) - error("allocating _mouseSurface failed"); - - SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); - } - - SDL_LockSurface(_mouseSurface); - - ScalerProc *scalerProc; - - if (_cursorTargetScale == 1 && _videoMode.screenWidth > 320) { - scalerProc = scalersMagn[_cursorTargetScale + 1][_videoMode.scaleFactor + 1]; - } else { - scalerProc = scalersMagn[_cursorTargetScale - 1][_videoMode.scaleFactor - 1]; - } - - scalerProc((byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2, - _mouseOrigSurface->pitch, (byte *)_mouseSurface->pixels, _mouseSurface->pitch, - _mouseCurState.w, _mouseCurState.h); - - if (_videoMode.aspectRatioCorrection && _cursorTargetScale == 1) - cursorStretch200To240((uint8 *)_mouseSurface->pixels, _mouseSurface->pitch, rW, rH1, 0, 0, 0); - - SDL_UnlockSurface(_mouseSurface); - SDL_UnlockSurface(_mouseOrigSurface); -} - -// Basically it is kVeryFastAndUglyAspectMode of stretch200To240 from -// common/scale/aspect.cpp -static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY) { - int maxDstY = real2Aspect(origSrcY + height - 1); - int y; - const uint8 *startSrcPtr = buf + srcX * 2 + (srcY - origSrcY) * pitch; - uint8 *dstPtr = buf + srcX * 2 + maxDstY * pitch; - - for (y = maxDstY; y >= srcY; y--) { - const uint8 *srcPtr = startSrcPtr + aspect2Real(y) * pitch; - - if (srcPtr == dstPtr) - break; - memcpy(dstPtr, srcPtr, width * 2); - dstPtr -= pitch; - } - - return 1 + maxDstY - srcY; -} - -void OSystem_GP2X::toggleMouseGrab() { - if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) - SDL_WM_GrabInput(SDL_GRAB_ON); - else - SDL_WM_GrabInput(SDL_GRAB_OFF); -} - -void OSystem_GP2X::undrawMouse() { - const int x = _mouseBackup.x; - const int y = _mouseBackup.y; - - // When we switch bigger overlay off mouse jumps. Argh! - // This is intended to prevent undrawing offscreen mouse - if (!_overlayVisible && (x >= _videoMode.screenWidth || y >= _videoMode.screenHeight)) - return; - - if (_mouseBackup.w != 0 && _mouseBackup.h != 0) - addDirtyRect(x, y, _mouseBackup.w, _mouseBackup.h); -} - -void OSystem_GP2X::drawMouse() { - if (!_mouseVisible || !_mouseSurface) { - _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; - return; - } - - SDL_Rect zoomdst; - SDL_Rect dst; - int scale; - int hotX, hotY; - int tmpScreenWidth, tmpScreenHeight; - - // Temp vars to ensure we zoom to the LCD resolution or greater. - tmpScreenWidth = _videoMode.screenWidth; - tmpScreenHeight = _videoMode.screenHeight; - - if (_videoMode.screenHeight <= 240) { - tmpScreenHeight = 240; - } - - if (_videoMode.screenWidth <= 320) { - tmpScreenWidth = 320; - } - - dst.x = _mouseCurState.x; - dst.y = _mouseCurState.y; - - if (!_overlayVisible) { - scale = _videoMode.scaleFactor; - dst.w = _mouseCurState.vW; - dst.h = _mouseCurState.vH; - hotX = _mouseCurState.vHotX; - hotY = _mouseCurState.vHotY; - } else { - scale = 1; - dst.w = _mouseCurState.rW; - dst.h = _mouseCurState.rH; - hotX = _mouseCurState.rHotX; - hotY = _mouseCurState.rHotY; - } - - // The mouse is undrawn using virtual coordinates, i.e. they may be - // scaled and aspect-ratio corrected. - - _mouseBackup.x = dst.x - hotX; - _mouseBackup.y = dst.y - hotY; - _mouseBackup.w = dst.w; - _mouseBackup.h = dst.h; - - // We draw the pre-scaled cursor image, so now we need to adjust for - // scaling, shake position and aspect ratio correction manually. - - if (!_overlayVisible) { - dst.y += _currentShakePos; - } - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - dst.y = real2Aspect(dst.y); - - dst.x = scale * dst.x - _mouseCurState.rHotX; - dst.y = scale * dst.y - _mouseCurState.rHotY; - dst.w = _mouseCurState.rW; - dst.h = _mouseCurState.rH; - - // Hacking about with the zoom around mouse pointer stuff. - if (_adjustZoomOnMouse == true){ - - zoomdst.w = (tmpScreenWidth / 2); - zoomdst.h = (tmpScreenHeight / 2); - - // Create a zoomed rect centered on the mouse pointer. - // Will pan 1/4 of the screen. - - if (dst.x > ((tmpScreenWidth / 4) * 3)) { - zoomdst.x = (tmpScreenWidth / 2); - } else { - zoomdst.x = (dst.x - (tmpScreenWidth / 4)); - if (zoomdst.x < 0) { - zoomdst.x = 0; - } - } - - if (dst.y > ((tmpScreenHeight / 4) * 3)) { - zoomdst.y = (tmpScreenHeight / 2); - } else { - zoomdst.y = (dst.y - (tmpScreenHeight / 4)); - if (zoomdst.y < 0) { - zoomdst.y = 0; - } - } - SDL_GP2X_Display(&zoomdst); - } else { - - // Make sure we are looking at the whole screen otherwise. - - zoomdst.x = 0; - zoomdst.y = 0; - zoomdst.w = (tmpScreenWidth); - zoomdst.h = (tmpScreenHeight); - - SDL_GP2X_Display(&zoomdst); - }; - - // Note that SDL_BlitSurface() and addDirtyRect() will both perform any - // clipping necessary - - if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0) - error("SDL_BlitSurface failed: %s", SDL_GetError()); - - // The screen will be updated using real surface coordinates, i.e. - // they will not be scaled or aspect-ratio corrected. - - addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); -} - -#pragma mark - -#pragma mark --- On Screen Display --- -#pragma mark - - -void OSystem_GP2X::displayMessageOnOSD(const char *msg) { - assert (_transactionMode == kTransactionNone); - assert(msg); - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - - uint i; - - // Lock the OSD surface for drawing - if (SDL_LockSurface(_osdSurface)) - 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.bytesPerPixel = _osdSurface->format->BytesPerPixel; - - // The font we are going to use: - const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont); - - // Clear everything with the "transparent" color, i.e. the colorkey - SDL_FillRect(_osdSurface, 0, kOSDColorKey); - - // Split the message into separate lines. - Common::StringArray lines; - const char *ptr; - for (ptr = msg; *ptr; ++ptr) { - if (*ptr == '\n') { - lines.push_back(Common::String(msg, ptr - msg)); - msg = ptr + 1; - } - } - lines.push_back(Common::String(msg, ptr - msg)); - - // Determine a rect which would contain the message string (clipped to the - // screen dimensions). - const int vOffset = 6; - const int lineSpacing = 1; - const int lineHeight = font->getFontHeight() + 2 * lineSpacing; - int width = 0; - int height = lineHeight * lines.size() + 2 * vOffset; - for (i = 0; i < lines.size(); i++) { - width = MAX(width, font->getStringWidth(lines[i]) + 14); - } - - // Clip the rect - if (width > dst.w) - width = dst.w; - if (height > dst.h) - height = dst.h; - - // Draw a dark gray rect - // TODO: Rounded corners ? Border? - SDL_Rect osdRect; - osdRect.x = (dst.w - width) / 2; - osdRect.y = (dst.h - height) / 2; - osdRect.w = width; - osdRect.h = height; - SDL_FillRect(_osdSurface, &osdRect, SDL_MapRGB(_osdSurface->format, 64, 64, 64)); - - // Render the message, centered, and in white - for (i = 0; i < lines.size(); i++) { - font->drawString(&dst, lines[i], - osdRect.x, osdRect.y + i * lineHeight + vOffset + lineSpacing, osdRect.w, - SDL_MapRGB(_osdSurface->format, 255, 255, 255), - Graphics::kTextAlignCenter); - } - - // Finished drawing, so unlock the OSD surface again - SDL_UnlockSurface(_osdSurface); - - // Init the OSD display parameters, and the fade out - _osdAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay; - SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha); - - // Ensure a full redraw takes place next time the screen is updated - _forceFull = true; -} - -#pragma mark - -#pragma mark --- Misc --- -#pragma mark - - -void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { - // Ctrl-Alt-a toggles aspect ratio correction - if (key.keysym.sym == 'a') { - beginGFXTransaction(); - setFeatureState(kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection); - endGFXTransaction(); - char buffer[128]; - if (_videoMode.aspectRatioCorrection) - sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d", - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h - ); - else - sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d", - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(buffer); - - - return; - } - - int newMode = -1; - int factor = _videoMode.scaleFactor - 1; - - // Increase/decrease the scale factor - if (key.keysym.sym == SDLK_EQUALS || key.keysym.sym == SDLK_PLUS || key.keysym.sym == SDLK_MINUS || - key.keysym.sym == SDLK_KP_PLUS || key.keysym.sym == SDLK_KP_MINUS) { - factor += (key.keysym.sym == SDLK_MINUS || key.keysym.sym == SDLK_KP_MINUS) ? -1 : +1; - if (0 <= factor && factor <= 3) { - newMode = s_gfxModeSwitchTable[_scalerType][factor]; - } - } - - const bool isNormalNumber = (SDLK_1 <= key.keysym.sym && key.keysym.sym <= SDLK_9); - const bool isKeypadNumber = (SDLK_KP1 <= key.keysym.sym && key.keysym.sym <= SDLK_KP9); - if (isNormalNumber || isKeypadNumber) { - _scalerType = key.keysym.sym - (isNormalNumber ? SDLK_1 : SDLK_KP1); - if (_scalerType >= ARRAYSIZE(s_gfxModeSwitchTable)) - return; - - while (s_gfxModeSwitchTable[_scalerType][factor] < 0) { - assert(factor > 0); - factor--; - } - newMode = s_gfxModeSwitchTable[_scalerType][factor]; - } - - if (newMode >= 0) { - beginGFXTransaction(); - setGraphicsMode(newMode); - endGFXTransaction(); - - if (_osdSurface) { - const char *newScalerName = 0; - const GraphicsMode *g = getSupportedGraphicsModes(); - while (g->name) { - if (g->id == _videoMode.mode) { - newScalerName = g->description; - break; - } - g++; - } - if (newScalerName) { - char buffer[128]; - sprintf(buffer, "Active graphics filter: %s\n%d x %d -> %d x %d", - newScalerName, - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(buffer); - } - } - } -} diff --git a/backends/platform/gp2x/module.mk b/backends/platform/gp2x/module.mk index d4f145c64f..837ad99d7b 100644 --- a/backends/platform/gp2x/module.mk +++ b/backends/platform/gp2x/module.mk @@ -2,10 +2,9 @@ MODULE := backends/platform/gp2x MODULE_OBJS := \ gp2x-hw.o \ + gp2x-main.o \ gp2x-mem.o \ - events.o \ - graphics.o \ - gp2x.o \ + gp2x.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/gp2xwiz/gp2xwiz-events.cpp b/backends/platform/gp2xwiz/gp2xwiz-events.cpp deleted file mode 100644 index 19ef24ef58..0000000000 --- a/backends/platform/gp2xwiz/gp2xwiz-events.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* - * GP2X Wiz: Device Specific Event Handling. - * - */ - -#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" -#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" -#include "graphics/scaler/aspect.h" - -#include "common/util.h" -#include "common/events.h" - -// FIXME move joystick defines out and replace with confile file options -// we should really allow users to map any key to a joystick button using the keymapper. -#define JOY_DEADZONE 2200 - -#define JOY_XAXIS 0 -#define JOY_YAXIS 1 - -/* GP2X Wiz: Main Joystick Mappings */ -enum { - GP2X_BUTTON_UP = 0, - GP2X_BUTTON_UPLEFT = 1, - GP2X_BUTTON_LEFT = 2, - GP2X_BUTTON_DOWNLEFT = 3, - GP2X_BUTTON_DOWN = 4, - GP2X_BUTTON_DOWNRIGHT = 5, - GP2X_BUTTON_RIGHT = 6, - GP2X_BUTTON_UPRIGHT = 7, - GP2X_BUTTON_MENU = 8, - GP2X_BUTTON_SELECT = 9, - GP2X_BUTTON_L = 10, - GP2X_BUTTON_R = 11, - GP2X_BUTTON_A = 12, - GP2X_BUTTON_B = 13, - GP2X_BUTTON_X = 14, - GP2X_BUTTON_Y = 15, - GP2X_BUTTON_VOLUP = 16, - GP2X_BUTTON_VOLDOWN = 17 -}; - -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { - if (key >= SDLK_F1 && key <= SDLK_F9) { - return key - SDLK_F1 + Common::ASCII_F1; - } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { - return key - SDLK_KP0 + '0'; - } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { - return key; - } else if (unicode) { - return unicode; - } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { - return key & ~0x20; - } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { - return 0; - } - return key; -} - -void OSystem_GP2XWIZ::fillMouseEvent(Common::Event &event, int x, int y) { - if (_videoMode.mode == GFX_HALF && !_overlayVisible){ - event.mouse.x = x*2; - event.mouse.y = y*2; - } else { - event.mouse.x = x; - event.mouse.y = y; - } - - // Update the "keyboard mouse" coords - _km.x = x; - _km.y = y; - - // Adjust for the screen scaling - if (!_overlayVisible) { - event.mouse.x /= _videoMode.scaleFactor; - event.mouse.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - event.mouse.y = aspect2Real(event.mouse.y); - } -} - -static byte SDLModToOSystemKeyFlags(SDLMod mod) { - byte b = 0; - if (mod & KMOD_SHIFT) - b |= Common::KBD_SHIFT; - if (mod & KMOD_ALT) - b |= Common::KBD_ALT; - if (mod & KMOD_CTRL) - b |= Common::KBD_CTRL; - - return b; -} - -void OSystem_GP2XWIZ::moveStick() { - bool stickBtn[32]; - - memcpy(stickBtn, _stickBtn, sizeof(stickBtn)); - - if ((stickBtn[0])||(stickBtn[2])||(stickBtn[4])||(stickBtn[6])) - stickBtn[1] = stickBtn[3] = stickBtn[5] = stickBtn[7] = 0; - - if ((stickBtn[1])||(stickBtn[2])||(stickBtn[3])) { - if (_km.x_down_count!=2) { - _km.x_vel = -1; - _km.x_down_count = 1; - } else - _km.x_vel = -4; - } else if ((stickBtn[5])||(stickBtn[6])||(stickBtn[7])) { - if (_km.x_down_count!=2) { - _km.x_vel = 1; - _km.x_down_count = 1; - } else - _km.x_vel = 4; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - - if ((stickBtn[0])||(stickBtn[1])||(stickBtn[7])) { - if (_km.y_down_count!=2) { - _km.y_vel = -1; - _km.y_down_count = 1; - } else - _km.y_vel = -4; - } else if ((stickBtn[3])||(stickBtn[4])||(stickBtn[5])) { - if (_km.y_down_count!=2) { - _km.y_vel = 1; - _km.y_down_count = 1; - } else - _km.y_vel = 4; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -} - -/* Quick default button states for modifiers. */ -int GP2X_BUTTON_STATE_L = false; - -/* Override the SDL pollEvent with the Wiz's own event code. */ -bool OSystem_GP2XWIZ::pollEvent(Common::Event &event) { - SDL_Event ev; - ev.type = SDL_NOEVENT; - int axis; - byte b = 0; - - handleKbdMouse(); - - // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED - if (_modeChanged) { - _modeChanged = false; - event.type = Common::EVENT_SCREEN_CHANGED; - return true; - } - - // GP2X Wiz Input mappings. - - /* - Single Button - - Movement: - - GP2X_BUTTON_UP Cursor Up - GP2X_BUTTON_DOWN Cursor Down - GP2X_BUTTON_LEFT Cursor Left - GP2X_BUTTON_RIGHT Cursor Right - - GP2X_BUTTON_UPLEFT Cursor Up Left - GP2X_BUTTON_UPRIGHT Cursor Up Right - GP2X_BUTTON_DOWNLEFT Cursor Down Left - GP2X_BUTTON_DOWNRIGHT Cursor Down Right - - Button Emulation: - - GP2X_BUTTON_A . (Period) - GP2X_BUTTON_B Left Mouse Click - GP2X_BUTTON_Y Space Bar - GP2X_BUTTON_X Right Mouse Click - GP2X_BUTTON_L Combo Modifier (Left Trigger) - GP2X_BUTTON_R Return (Right Trigger) - GP2X_BUTTON_MENU F5 (Game Menu) - GP2X_BUTTON_SELECT Escape - GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up - GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down - - Combos: - - GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) or Virtual Keyboard if enabled - GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) - GP2X_BUTTON_L & GP2X_BUTTON_MENU Common::EVENT_MAINMENU (ScummVM Global Main Menu) - GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) - */ - - while (SDL_PollEvent(&ev)) { - - switch (ev.type) { - case SDL_KEYDOWN:{ - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - - return true; - } - case SDL_KEYUP: - { - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - // Ctrl-Alt-<key> will change the GFX mode - if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { - // Swallow these key up events - break; - } - - return true; - } - case SDL_MOUSEMOTION: - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, ev.motion.x, ev.motion.y); - - setMousePos(event.mouse.x, event.mouse.y); - return true; - - case SDL_MOUSEBUTTONDOWN: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONDOWN; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONDOWN; -#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) - else if (ev.button.button == SDL_BUTTON_WHEELUP) - event.type = Common::EVENT_WHEELUP; - else if (ev.button.button == SDL_BUTTON_WHEELDOWN) - event.type = Common::EVENT_WHEELDOWN; -#endif -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONDOWN; -#endif - else - break; - - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - case SDL_MOUSEBUTTONUP: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONUP; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONUP; -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONUP; -#endif - else - break; - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - case SDL_JOYBUTTONDOWN: - _stickBtn[ev.jbutton.button] = 1; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (_stickBtn[GP2X_BUTTON_L] && (ev.jbutton.button == GP2X_BUTTON_SELECT)) { - event.type = Common::EVENT_QUIT; - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYDOWN; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = true; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_SELECT: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_QUIT; - } else { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_A: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_PREDICTIVE_DIALOG; - } else { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_Y: - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_MENU: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - WIZ_HW::mixerMoveVolume(2); - if (WIZ_HW::volumeLevel == 100) { - displayMessageOnOSD("Maximum Volume"); - } else { - displayMessageOnOSD("Increasing Volume"); - } - break; - - case GP2X_BUTTON_VOLDOWN: - WIZ_HW::mixerMoveVolume(1); - if (WIZ_HW::volumeLevel == 0) { - displayMessageOnOSD("Minimal Volume"); - } else { - displayMessageOnOSD("Decreasing Volume"); - } - break; - } - } - return true; - - case SDL_JOYBUTTONUP: - _stickBtn[ev.jbutton.button] = 0; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYUP; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_SELECT: - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_A: - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_Y: - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_MENU: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = false; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - break; - case GP2X_BUTTON_VOLDOWN: - break; - } - } - return true; - - case SDL_JOYAXISMOTION: - axis = ev.jaxis.value; - if ( axis > JOY_DEADZONE) { - axis -= JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else if ( axis < -JOY_DEADZONE ) { - axis += JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else - axis = 0; - - if ( ev.jaxis.axis == JOY_XAXIS) { - if (axis != 0) { - _km.x_vel = (axis > 0) ? 1:-1; - _km.x_down_count = 1; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - } else if (ev.jaxis.axis == JOY_YAXIS) { -#ifndef JOY_INVERT_Y - axis = -axis; -#endif -#ifdef JOY_ANALOG - _km.y_vel = -axis / 2000; - _km.y_down_count = 0; -#else - if (axis != 0) { - _km.y_vel = (-axis > 0) ? 1: -1; - _km.y_down_count = 1; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -#endif - } - - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case SDL_VIDEOEXPOSE: - _forceFull = true; - break; - - case SDL_QUIT: - event.type = Common::EVENT_QUIT; - return true; - } - } - return false; -} - -bool OSystem_GP2XWIZ::remapKey(SDL_Event &ev,Common::Event &event) { - return false; -} diff --git a/backends/platform/gp2xwiz/gp2xwiz-main.cpp b/backends/platform/gp2xwiz/gp2xwiz-main.cpp index 394c3090c3..d6601f5250 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-main.cpp +++ b/backends/platform/gp2xwiz/gp2xwiz-main.cpp @@ -23,194 +23,28 @@ * */ -#include "common/scummsys.h" -#include <SDL/SDL.h> - #include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" -#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" #include "backends/plugins/posix/posix-provider.h" #include "base/main.h" -#include "base/internal_version.h" - -#include "common/archive.h" -#include "common/config-manager.h" -#include "common/debug.h" -#include "common/events.h" -#include "common/util.h" - -#include "common/file.h" -#include "base/main.h" - -#include "backends/saves/default/default-saves.h" - -#include "backends/timer/default/default-timer.h" -#include "sound/mixer_intern.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include <sys/stat.h> -#include <time.h> // for getTimeAndDate() - -/* Dump console info to files. */ -// #define DUMP_STDOUT int main(int argc, char *argv[]) { + // Create our OSystem instance g_system = new OSystem_GP2XWIZ(); assert(g_system); + // Pre initialize the backend + ((OSystem_GP2XWIZ *)g_system)->init(); + #ifdef DYNAMIC_MODULES PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); #endif // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - g_system->quit(); - - return res; -} - -void OSystem_GP2XWIZ::initBackend() { - - /* Setup default save path to be workingdir/saves */ - - char savePath[PATH_MAX+1]; - char workDirName[PATH_MAX+1]; - - if (getcwd(workDirName, PATH_MAX) == NULL) { - error("Could not obtain current working directory."); - } else { - printf("Current working directory: %s\n", workDirName); - } - - strcpy(savePath, workDirName); - strcat(savePath, "/saves"); - printf("Current save directory: %s\n", savePath); - struct stat sb; - if (stat(savePath, &sb) == -1) - if (errno == ENOENT) // Create the dir if it does not exist - if (mkdir(savePath, 0755) != 0) - warning("mkdir for '%s' failed!", savePath); - - _savefile = new DefaultSaveFileManager(savePath); - - #ifdef DUMP_STDOUT - // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we - // output all our STDOUT and STDERR to files for debug purposes. - char STDOUT_FILE[PATH_MAX+1]; - char STDERR_FILE[PATH_MAX+1]; - - strcpy(STDOUT_FILE, workDirName); - strcpy(STDERR_FILE, workDirName); - strcat(STDOUT_FILE, "/scummvm.stdout.txt"); - strcat(STDERR_FILE, "/scummvm.stderr.txt"); - - // Flush the output in case anything is queued - fclose(stdout); - fclose(stderr); - - // Redirect standard input and standard output - FILE *newfp = freopen(STDOUT_FILE, "w", stdout); - if (newfp == NULL) { - #if !defined(stdout) - stdout = fopen(STDOUT_FILE, "w"); - #else - newfp = fopen(STDOUT_FILE, "w"); - if (newfp) { - *stdout = *newfp; - } - #endif - } - - newfp = freopen(STDERR_FILE, "w", stderr); - if (newfp == NULL) { - #if !defined(stderr) - stderr = fopen(STDERR_FILE, "w"); - #else - newfp = fopen(STDERR_FILE, "w"); - if (newfp) { - *stderr = *newfp; - } - #endif - } - - setbuf(stderr, NULL); - printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); - #endif /* DUMP_STDOUT */ - /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */ - WIZ_HW::deviceInit(); + // Free OSystem + delete (OSystem_GP2XWIZ *)g_system; - /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */ - WIZ_HW::mixerMoveVolume(0); - - /* Up default volume values as we use a seperate system level volume anyway. */ - ConfMan.registerDefault("music_volume", 192); - ConfMan.registerDefault("sfx_volume", 192); - ConfMan.registerDefault("speech_volume", 192); - - /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */ - ConfMan.registerDefault("autosave_period", 4 * 60); - - /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */ - ConfMan.registerDefault("aspect_ratio", true); - - /* Make sure SDL knows that we have a joystick we want to use. */ - ConfMan.setInt("joystick_num", 0); - - printf("%s\n", "Passing to OSystem::SDL initBackend."); - - /* Pass to SDL backend to do the heavy lifting */ - OSystem_SDL::initBackend(); -} - -void OSystem_GP2XWIZ::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { - - /* Setup default extra data paths for engine data files and plugins */ - char workDirName[PATH_MAX+1]; - - if (getcwd(workDirName, PATH_MAX) == NULL) { - error("Error: Could not obtain current working directory."); - } - - Common::FSNode workdirNode(workDirName); - if (workdirNode.exists() && workdirNode.isDirectory()) { - s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority); - } - - char enginedataPath[PATH_MAX+1]; - - strcpy(enginedataPath, workDirName); - strcat(enginedataPath, "/engine-data"); - - Common::FSNode engineNode(enginedataPath); - if (engineNode.exists() && engineNode.isDirectory()) { - s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); - } - - char pluginsPath[PATH_MAX+1]; - - strcpy(pluginsPath, workDirName); - strcat(pluginsPath, "/plugins"); - - Common::FSNode pluginsNode(pluginsPath); - if (pluginsNode.exists() && pluginsNode.isDirectory()) { - s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority); - } -} - -void OSystem_GP2XWIZ::quit() { - - WIZ_HW::deviceDeinit(); - - #ifdef DUMP_STDOUT - printf("%s\n", "Debug: STDOUT and STDERR text files closed."); - fclose(stdout); - fclose(stderr); - #endif /* DUMP_STDOUT */ - - OSystem_SDL::quit(); + return res; } diff --git a/backends/platform/gp2xwiz/gp2xwiz-sdl.cpp b/backends/platform/gp2xwiz/gp2xwiz-sdl.cpp new file mode 100644 index 0000000000..b07eaa0ffa --- /dev/null +++ b/backends/platform/gp2xwiz/gp2xwiz-sdl.cpp @@ -0,0 +1,194 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" +#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" + +#include "backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h" +#include "backends/events/gp2xsdl/gp2xsdl-events.h" +#include "backends/saves/default/default-saves.h" + +#include "common/config-manager.h" +#include "common/debug.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> +#include <sys/stat.h> + +/* Dump console info to files. */ +// #define DUMP_STDOUT + +void OSystem_GP2XWIZ::initBackend() { + + /* Setup default save path to be workingdir/saves */ + + char savePath[PATH_MAX+1]; + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Could not obtain current working directory."); + } else { + printf("Current working directory: %s\n", workDirName); + } + + strcpy(savePath, workDirName); + strcat(savePath, "/saves"); + printf("Current save directory: %s\n", savePath); + struct stat sb; + if (stat(savePath, &sb) == -1) + if (errno == ENOENT) // Create the dir if it does not exist + if (mkdir(savePath, 0755) != 0) + warning("mkdir for '%s' failed!", savePath); + + _savefileManager = new DefaultSaveFileManager(savePath); + + #ifdef DUMP_STDOUT + // The GP2X Wiz has a serial console on the breakout board but most users do not use this so we + // output all our STDOUT and STDERR to files for debug purposes. + char STDOUT_FILE[PATH_MAX+1]; + char STDERR_FILE[PATH_MAX+1]; + + strcpy(STDOUT_FILE, workDirName); + strcpy(STDERR_FILE, workDirName); + strcat(STDOUT_FILE, "/scummvm.stdout.txt"); + strcat(STDERR_FILE, "/scummvm.stderr.txt"); + + // Flush the output in case anything is queued + fclose(stdout); + fclose(stderr); + + // Redirect standard input and standard output + FILE *newfp = freopen(STDOUT_FILE, "w", stdout); + if (newfp == NULL) { + #if !defined(stdout) + stdout = fopen(STDOUT_FILE, "w"); + #else + newfp = fopen(STDOUT_FILE, "w"); + if (newfp) { + *stdout = *newfp; + } + #endif + } + + newfp = freopen(STDERR_FILE, "w", stderr); + if (newfp == NULL) { + #if !defined(stderr) + stderr = fopen(STDERR_FILE, "w"); + #else + newfp = fopen(STDERR_FILE, "w"); + if (newfp) { + *stderr = *newfp; + } + #endif + } + + setbuf(stderr, NULL); + printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); + #endif /* DUMP_STDOUT */ + + /* Initialise any GP2X Wiz specific stuff we may want (Batt Status, scaler etc.) */ + WIZ_HW::deviceInit(); + + /* Set Default hardware mixer volume to a preset level (VOLUME_INITIAL). This is done to 'reset' volume level if set by other apps. */ + WIZ_HW::mixerMoveVolume(0); + + /* Up default volume values as we use a seperate system level volume anyway. */ + ConfMan.registerDefault("music_volume", 192); + ConfMan.registerDefault("sfx_volume", 192); + ConfMan.registerDefault("speech_volume", 192); + + /* Trigger autosave every 4 minutes - On low batts 5 mins is about your warning time. */ + ConfMan.registerDefault("autosave_period", 4 * 60); + + /* Make sure that aspect ratio correction is enabled on the 1st run to stop users asking me what the 'wasted space' is ;-). */ + ConfMan.registerDefault("aspect_ratio", true); + + /* Make sure SDL knows that we have a joystick we want to use. */ + ConfMan.setInt("joystick_num", 0); + + // Create the events manager + if (_eventManager == 0) + _eventManager = new GP2XSdlEventManager(this); + + // Create the graphics manager + if (_graphicsManager == 0) + _graphicsManager = new GP2XWIZSdlGraphicsManager(); + + printf("%s\n", "Passing to OSystem_POSIX initBackend."); + + /* Pass to SDL backend to do the heavy lifting */ + OSystem_POSIX::initBackend(); +} + +void OSystem_GP2XWIZ::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + + /* Setup default extra data paths for engine data files and plugins */ + char workDirName[PATH_MAX + 1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Error: Could not obtain current working directory."); + } + + Common::FSNode workdirNode(workDirName); + if (workdirNode.exists() && workdirNode.isDirectory()) { + s.add("__GP2XWIZ_WORKDIR__", new Common::FSDirectory(workDirName), priority); + } + + char enginedataPath[PATH_MAX + 1]; + + strcpy(enginedataPath, workDirName); + strcat(enginedataPath, "/engine-data"); + + Common::FSNode engineNode(enginedataPath); + if (engineNode.exists() && engineNode.isDirectory()) { + s.add("__GP2XWIZ_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); + } + + char pluginsPath[PATH_MAX + 1]; + + strcpy(pluginsPath, workDirName); + strcat(pluginsPath, "/plugins"); + + Common::FSNode pluginsNode(pluginsPath); + if (pluginsNode.exists() && pluginsNode.isDirectory()) { + s.add("__GP2XWIZ_PLUGINS__", new Common::FSDirectory(pluginsPath), priority); + } +} + +void OSystem_GP2XWIZ::quit() { + + WIZ_HW::deviceDeinit(); + + #ifdef DUMP_STDOUT + printf("%s\n", "Debug: STDOUT and STDERR text files closed."); + fclose(stdout); + fclose(stderr); + #endif /* DUMP_STDOUT */ + + OSystem_POSIX::quit(); +} diff --git a/backends/platform/gp2xwiz/gp2xwiz-sdl.h b/backends/platform/gp2xwiz/gp2xwiz-sdl.h index e312d0f26d..56ca883b02 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-sdl.h +++ b/backends/platform/gp2xwiz/gp2xwiz-sdl.h @@ -23,55 +23,20 @@ * */ -#ifndef GP2XWIZ_SDL_H -#define GP2XWIZ_SDL_H +#ifndef PLATFORM_SDL_GP2XWIZ_H +#define PLATFORM_SDL_GP2XWIZ_H -#include "backends/platform/sdl/sdl.h" - -// FIXME: For now keep hacks in this header to save polluting the SDL backend. -enum { - GFX_HALF = 12 -}; - -#define __GP2XWIZ__ -#define MIXER_DOUBLE_BUFFERING 1 +#include "backends/platform/sdl/posix/posix.h" #ifndef PATH_MAX #define PATH_MAX 255 #endif -class OSystem_GP2XWIZ : public OSystem_SDL { +class OSystem_GP2XWIZ : public OSystem_POSIX { public: - OSystem_GP2XWIZ() {} - - /* Graphics */ - void initSize(uint w, uint h); - void setGraphicsModeIntern(); - bool setGraphicsMode(int mode); - void internUpdateScreen(); - const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(const char *name); - int getDefaultGraphicsMode() const; - bool loadGFXMode(); - void drawMouse(); - void undrawMouse(); - void showOverlay(); - void hideOverlay(); - - /* Event Stuff */ - bool pollEvent(Common::Event &event); - void moveStick(); - void fillMouseEvent(Common::Event&, int, int); - void warpMouse(int, int); - bool remapKey(SDL_Event&, Common::Event&); - - /* Platform Setup Stuff */ - void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); - void initBackend(); - void quit(); - -protected: - bool _stickBtn[32]; + virtual void initBackend(); + virtual void quit(); + virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); }; #endif diff --git a/backends/platform/gp2xwiz/module.mk b/backends/platform/gp2xwiz/module.mk index edf2f2a717..cca77058af 100644 --- a/backends/platform/gp2xwiz/module.mk +++ b/backends/platform/gp2xwiz/module.mk @@ -1,10 +1,9 @@ MODULE := backends/platform/gp2xwiz MODULE_OBJS := \ - gp2xwiz-events.o \ - gp2xwiz-graphics.o \ gp2xwiz-hw.o \ - gp2xwiz-main.o + gp2xwiz-main.o \ + gp2xwiz-sdl.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/linuxmoto/linuxmoto-main.cpp b/backends/platform/linuxmoto/linuxmoto-main.cpp index b971a65f7e..e9f2e661de 100644 --- a/backends/platform/linuxmoto/linuxmoto-main.cpp +++ b/backends/platform/linuxmoto/linuxmoto-main.cpp @@ -23,22 +23,23 @@ * */ -#include "common/scummsys.h" -#include "common/system.h" - -#include <SDL/SDL.h> -#include <SDL/SDL_syswm.h> - #include "backends/platform/linuxmoto/linuxmoto-sdl.h" #include "base/main.h" -#include "base/internal_version.h" int main(int argc, char *argv[]) { + + // Create our OSystem instance g_system = new OSystem_LINUXMOTO(); assert(g_system); + + // Pre initialize the backend + ((OSystem_POSIX *)g_system)->init(); + // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - g_system->quit(); // TODO: Consider removing / replacing this! + + // Free OSystem + delete (OSystem_LINUXMOTO *)g_system; return res; } diff --git a/backends/platform/linuxmoto/linuxmoto-sdl.cpp b/backends/platform/linuxmoto/linuxmoto-sdl.cpp index ad1af455c3..6ef03ed3ac 100644 --- a/backends/platform/linuxmoto/linuxmoto-sdl.cpp +++ b/backends/platform/linuxmoto/linuxmoto-sdl.cpp @@ -25,44 +25,17 @@ #include "backends/platform/linuxmoto/linuxmoto-sdl.h" -void OSystem_LINUXMOTO::preprocessEvents(SDL_Event *event) { - if (event->type == SDL_ACTIVEEVENT) { - if (event->active.state == SDL_APPINPUTFOCUS && !event->active.gain) { - suspendAudio(); - for (;;) { - if (!SDL_WaitEvent(event)) { - SDL_Delay(10); - continue; - } - if (event->type == SDL_QUIT) - return; - if (event->type != SDL_ACTIVEEVENT) - continue; - if (event->active.state == SDL_APPINPUTFOCUS && event->active.gain) { - resumeAudio(); - return; - } - } - } - } -} +#include "backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h" +#include "backends/events/linuxmotosdl/linuxmotosdl-events.h" -void OSystem_LINUXMOTO::suspendAudio() { - SDL_CloseAudio(); - _audioSuspended = true; -} +void OSystem_LINUXMOTO::initBackend() { + // Create the backend custom managers + if (_eventManager == 0) + _eventManager = new LinuxmotoSdlEventManager(this); -int OSystem_LINUXMOTO::resumeAudio() { - if (!_audioSuspended) - return -2; - if (SDL_OpenAudio(&_obtainedRate, NULL) < 0){ - return -1; - } - SDL_PauseAudio(0); - _audioSuspended = false; - return 0; -} + if (_graphicsManager == 0) + _graphicsManager = new LinuxmotoSdlGraphicsManager(); -void OSystem_LINUXMOTO::setupMixer() { - OSystem_SDL::setupMixer(); + // Call parent implementation of this method + OSystem_POSIX::initBackend(); } diff --git a/backends/platform/linuxmoto/linuxmoto-sdl.h b/backends/platform/linuxmoto/linuxmoto-sdl.h index c01d375603..78b9f81fd2 100644 --- a/backends/platform/linuxmoto/linuxmoto-sdl.h +++ b/backends/platform/linuxmoto/linuxmoto-sdl.h @@ -23,43 +23,17 @@ * */ -#ifndef LINUXMOTO_SDL -#define LINUXMOTO_SDL +#ifndef PLATFORM_SDL_LINUXMOTO_H +#define PLATFORM_SDL_LINUXMOTO_H -#include "backends/platform/sdl/sdl.h" +#include "backends/platform/sdl/posix/posix.h" -// FIXME: For now keep hacks in this header to save polluting the SDL backend. -enum { - GFX_HALF = 12 -}; - -class OSystem_LINUXMOTO : public OSystem_SDL { -private: - bool _audioSuspended; +class OSystem_LINUXMOTO : public OSystem_POSIX { public: - /* Graphics */ - void initSize(uint w, uint h); - void setGraphicsModeIntern(); - bool setGraphicsMode(int mode); - void internUpdateScreen(); - const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(const char *name); - int getDefaultGraphicsMode() const; - bool loadGFXMode(); - void drawMouse(); - void undrawMouse(); - void showOverlay(); - void hideOverlay(); + virtual void initBackend(); - /* Event Stuff */ - virtual bool remapKey(SDL_Event &ev, Common::Event &event); - virtual void preprocessEvents(SDL_Event *event); - virtual void setupMixer(); + // FIXME: This just calls parent methods, is it needed? virtual Common::HardwareKeySet *getHardwareKeySet(); - void fillMouseEvent(Common::Event&, int, int); - void suspendAudio(); - int resumeAudio(); - void warpMouse(int, int); }; #endif diff --git a/backends/platform/linuxmoto/module.mk b/backends/platform/linuxmoto/module.mk index 316ecbf78e..c604d69da1 100644 --- a/backends/platform/linuxmoto/module.mk +++ b/backends/platform/linuxmoto/module.mk @@ -1,8 +1,6 @@ MODULE := backends/platform/linuxmoto MODULE_OBJS := \ - linuxmoto-events.o \ - linuxmoto-graphics.o \ linuxmoto-main.o \ linuxmoto-sdl.o \ hardwarekeys.o diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp index 51166baae7..d888e632d6 100644 --- a/backends/platform/null/null.cpp +++ b/backends/platform/null/null.cpp @@ -23,22 +23,14 @@ * */ -#include "backends/base-backend.h" +#include "backends/modular-backend.h" #include "base/main.h" #if defined(USE_NULL_DRIVER) - -#ifdef UNIX -#include <unistd.h> -#include <sys/time.h> -#endif - -#include "common/rect.h" -#include "graphics/colormasks.h" - #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" #include "sound/mixer_intern.h" +#include "common/scummsys.h" /* * Include header files needed for the getFilesystemFactory() method. @@ -51,82 +43,24 @@ #include "backends/fs/windows/windows-fs-factory.h" #endif -class OSystem_NULL : public BaseBackend { -protected: - Common::SaveFileManager *_savefile; - Audio::MixerImpl *_mixer; - Common::TimerManager *_timer; - FilesystemFactory *_fsFactory; - - timeval _startTime; +class OSystem_NULL : public ModularBackend { public: - OSystem_NULL(); virtual ~OSystem_NULL(); virtual void initBackend(); - virtual bool hasFeature(Feature f); - virtual void setFeatureState(Feature f, bool enable); - virtual bool getFeatureState(Feature f); - virtual const GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - bool setGraphicsMode(const char *name); - virtual bool setGraphicsMode(int mode); - virtual int getGraphicsMode() const; - virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); - virtual int16 getHeight(); - virtual int16 getWidth(); - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); - virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h); - virtual void updateScreen(); - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - virtual void setShakePos(int shakeOffset); - - virtual void showOverlay(); - virtual void hideOverlay(); - virtual void clearOverlay(); - virtual void grabOverlay(OverlayColor *buf, int pitch); - virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); - virtual int16 getOverlayHeight(); - virtual int16 getOverlayWidth(); - virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<565>(); } - - virtual bool showMouse(bool visible); - - virtual void warpMouse(int x, int y); - virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); - virtual bool pollEvent(Common::Event &event); - virtual uint32 getMillis(); - virtual void delayMillis(uint msecs); - - virtual MutexRef createMutex(void); - virtual void lockMutex(MutexRef mutex); - virtual void unlockMutex(MutexRef mutex); - virtual void deleteMutex(MutexRef mutex); - - virtual void quit(); - - virtual Common::SaveFileManager *getSavefileManager(); - virtual Audio::Mixer *getMixer(); - virtual void getTimeAndDate(TimeDate &t) const; - virtual Common::TimerManager *getTimerManager(); - FilesystemFactory *getFilesystemFactory(); -}; + virtual uint32 getMillis(); + virtual void delayMillis(uint msecs) {} + virtual void getTimeAndDate(TimeDate &t) const {} -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {0, 0, 0} + virtual Common::SeekableReadStream *createConfigReadStream(); + virtual Common::WriteStream *createConfigWriteStream(); }; OSystem_NULL::OSystem_NULL() { - _savefile = 0; - _mixer = 0; - _timer = 0; - #if defined(__amigaos4__) _fsFactory = new AmigaOSFilesystemFactory(); #elif defined(UNIX) @@ -139,20 +73,18 @@ OSystem_NULL::OSystem_NULL() { } OSystem_NULL::~OSystem_NULL() { - delete _savefile; - delete _mixer; - delete _timer; - delete _fsFactory; } void OSystem_NULL::initBackend() { - _savefile = new DefaultSaveFileManager(); + _mutexManager = (MutexManager *)new NullMutexManager(); + _timerManager = new DefaultTimerManager(); + _eventManager = new DefaultEventManager(this); + _savefileManager = new DefaultSaveFileManager(); + _graphicsManager = (GraphicsManager *)new NullGraphicsManager(); + _audiocdManager = (AudioCDManager *)new DefaultAudioCDManager(); _mixer = new Audio::MixerImpl(this, 22050); - _timer = new DefaultTimerManager(); - - _mixer->setReady(false); - - gettimeofday(&_startTime, NULL); + + ((Audio::MixerImpl *)_mixer)->setReady(false); // Note that both the mixer and the timer manager are useless // this way; they need to be hooked into the system somehow to @@ -161,163 +93,38 @@ void OSystem_NULL::initBackend() { OSystem::initBackend(); } -bool OSystem_NULL::hasFeature(Feature f) { - return false; -} - -void OSystem_NULL::setFeatureState(Feature f, bool enable) { -} - -bool OSystem_NULL::getFeatureState(Feature f) { - return false; -} - -const OSystem::GraphicsMode* OSystem_NULL::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; -} - - -int OSystem_NULL::getDefaultGraphicsMode() const { - return -1; -} - -bool OSystem_NULL::setGraphicsMode(const char *mode) { - return true; -} - -bool OSystem_NULL::setGraphicsMode(int mode) { - return true; -} - -int OSystem_NULL::getGraphicsMode() const { - return -1; -} - -void OSystem_NULL::initSize(uint width, uint height, const Graphics::PixelFormat *format) { -} - -int16 OSystem_NULL::getHeight() { - return 200; -} - -int16 OSystem_NULL::getWidth() { - return 320; -} - -void OSystem_NULL::setPalette(const byte *colors, uint start, uint num) { -} - -void OSystem_NULL::grabPalette(byte *colors, uint start, uint num) { - -} - -void OSystem_NULL::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { -} - -void OSystem_NULL::updateScreen() { -} - -Graphics::Surface *OSystem_NULL::lockScreen() { - return 0; -} - -void OSystem_NULL::unlockScreen() { -} - -void OSystem_NULL::setShakePos(int shakeOffset) { -} - -void OSystem_NULL::showOverlay() { -} - -void OSystem_NULL::hideOverlay() { -} - -void OSystem_NULL::clearOverlay() { -} - -void OSystem_NULL::grabOverlay(OverlayColor *buf, int pitch) { -} - -void OSystem_NULL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { -} - -int16 OSystem_NULL::getOverlayHeight() { - return getHeight(); -} - -int16 OSystem_NULL::getOverlayWidth() { - return getWidth(); -} - - -bool OSystem_NULL::showMouse(bool visible) { - return true; -} - -void OSystem_NULL::warpMouse(int x, int y) { -} - -void OSystem_NULL::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { -} - bool OSystem_NULL::pollEvent(Common::Event &event) { return false; } uint32 OSystem_NULL::getMillis() { -#ifdef UNIX - timeval curTime; - gettimeofday(&curTime, NULL); - return (uint32)(((curTime.tv_sec - _startTime.tv_sec) * 1000) + \ - ((curTime.tv_usec - _startTime.tv_usec) / 1000)); -#else return 0; -#endif } -void OSystem_NULL::delayMillis(uint msecs) { -#ifdef UNIX - usleep(msecs * 1000); +#if defined(UNIX) +#if defined(SAMSUNGTV) +#define DEFAULT_CONFIG_FILE "/dtv/usb/sda1/.scummvmrc" +#else +#define DEFAULT_CONFIG_FILE ".scummvmrc" +#endif #endif -} - -OSystem::MutexRef OSystem_NULL::createMutex(void) { - return NULL; -} - -void OSystem_NULL::lockMutex(MutexRef mutex) { -} - -void OSystem_NULL::unlockMutex(MutexRef mutex) { -} - -void OSystem_NULL::deleteMutex(MutexRef mutex) { -} - -void OSystem_NULL::quit() { -} - -Common::SaveFileManager *OSystem_NULL::getSavefileManager() { - assert(_savefile); - return _savefile; -} - -Audio::Mixer *OSystem_NULL::getMixer() { - assert(_mixer); - return _mixer; -} -Common::TimerManager *OSystem_NULL::getTimerManager() { - assert(_timer); - return _timer; -} +#if !defined(UNIX) +#define DEFAULT_CONFIG_FILE "scummvm.ini" +#endif -void OSystem_NULL::getTimeAndDate(TimeDate &t) const { +Common::SeekableReadStream *OSystem_NULL::createConfigReadStream() { + Common::FSNode file(DEFAULT_CONFIG_FILE); + return file.createReadStream(); } -FilesystemFactory *OSystem_NULL::getFilesystemFactory() { - return _fsFactory; +Common::WriteStream *OSystem_NULL::createConfigWriteStream() { +#ifdef __DC__ + return 0; +#else + Common::FSNode file(DEFAULT_CONFIG_FILE); + return file.createWriteStream(); +#endif } OSystem *OSystem_NULL_create() { @@ -330,7 +137,7 @@ int main(int argc, char *argv[]) { // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - g_system->quit(); // TODO: Consider removing / replacing this! + delete (OSystem_NULL *)g_system; return res; } diff --git a/backends/platform/samsungtv/main.cpp b/backends/platform/samsungtv/main.cpp index 2c025b750c..f3d868641b 100644 --- a/backends/platform/samsungtv/main.cpp +++ b/backends/platform/samsungtv/main.cpp @@ -34,16 +34,23 @@ extern "C" int Game_Main(char *path, char *) { chdir(path); + // Create OSystem instance g_system = new OSystem_SDL_SamsungTV(); assert(g_system); + // Pre initialize the backend + ((OSystem_SDL_SamsungTV *)g_system)->init(); + #ifdef DYNAMIC_MODULES PluginManager::instance().addPluginProvider(new SDLPluginProvider()); #endif // Invoke the actual ScummVM main entry point: int res = scummvm_main(0, 0); - ((OSystem_SDL *)g_system)->deinit(); + + // Free OSystem + delete (OSystem_SDL_SamsungTV *)g_system; + return res; } diff --git a/backends/platform/samsungtv/module.mk b/backends/platform/samsungtv/module.mk index d7ebe75080..36ad75da6d 100644 --- a/backends/platform/samsungtv/module.mk +++ b/backends/platform/samsungtv/module.mk @@ -1,7 +1,6 @@ MODULE := backends/platform/samsungtv MODULE_OBJS := \ - events.o \ main.o \ samsungtv.o diff --git a/backends/platform/samsungtv/samsungtv.cpp b/backends/platform/samsungtv/samsungtv.cpp index aa79b92558..1e316aa840 100644 --- a/backends/platform/samsungtv/samsungtv.cpp +++ b/backends/platform/samsungtv/samsungtv.cpp @@ -24,19 +24,32 @@ */ #include "backends/platform/samsungtv/samsungtv.h" +#include "backends/events/samsungtvsdl/samsungtvsdl-events.h" -#if defined(SAMSUNGTV) +OSystem_SDL_SamsungTV::OSystem_SDL_SamsungTV() + : + OSystem_POSIX("/dtv/usb/sda1/.scummvmrc") { +} bool OSystem_SDL_SamsungTV::hasFeature(Feature f) { return - (f == kFeatureAspectRatioCorrection) || - (f == kFeatureCursorHasPalette); + (f == OSystem::kFeatureAspectRatioCorrection) || + (f == OSystem::kFeatureCursorHasPalette); +} + +void OSystem_SDL_SamsungTV::initBackend() { + // Create the events manager + if (_eventManager == 0) + _eventManager = new SamsungTVSdlEventManager(this); + + // Call parent implementation of this method + OSystem_SDL::initBackend(); } void OSystem_SDL_SamsungTV::setFeatureState(Feature f, bool enable) { switch (f) { - case kFeatureAspectRatioCorrection: - setAspectRatioCorrection(enable); + case OSystem::kFeatureAspectRatioCorrection: + _graphicsManager->setFeatureState(f, enable); break; default: break; @@ -44,14 +57,14 @@ void OSystem_SDL_SamsungTV::setFeatureState(Feature f, bool enable) { } bool OSystem_SDL_SamsungTV::getFeatureState(Feature f) { - assert (_transactionMode == kTransactionNone); - switch (f) { - case kFeatureAspectRatioCorrection: - return _videoMode.aspectRatioCorrection; + case OSystem::kFeatureAspectRatioCorrection: + return _graphicsManager->getFeatureState(f); default: return false; } } -#endif +void OSystem_SDL_SamsungTV::quit() { + deinit(); +} diff --git a/backends/platform/samsungtv/samsungtv.h b/backends/platform/samsungtv/samsungtv.h index b3344385aa..49460a9ddc 100644 --- a/backends/platform/samsungtv/samsungtv.h +++ b/backends/platform/samsungtv/samsungtv.h @@ -23,31 +23,22 @@ * */ -#ifndef SDL_SAMSUNGTV_COMMON_H -#define SDL_SAMSUNGTV_COMMON_H +#ifndef PLATFORM_SDL_SAMSUNGTV_H +#define PLATFORM_SDL_SAMSUNGTV_H -#include <SDL.h> +#include "backends/platform/sdl/posix/posix.h" -#include "backends/base-backend.h" -#include "backends/platform/sdl/sdl.h" - -#if defined(SAMSUNGTV) +class OSystem_SDL_SamsungTV : public OSystem_POSIX { +public: + OSystem_SDL_SamsungTV(); -namespace Audio { - class MixerImpl; -} + virtual void initBackend(); -class OSystem_SDL_SamsungTV : public OSystem_SDL { -public: virtual bool hasFeature(Feature f); virtual void setFeatureState(Feature f, bool enable); virtual bool getFeatureState(Feature f); -protected: - - virtual bool remapKey(SDL_Event &ev, Common::Event &event); + virtual void quit(); }; #endif - -#endif diff --git a/backends/platform/sdl/macosx/macosx-main.cpp b/backends/platform/sdl/macosx/macosx-main.cpp new file mode 100644 index 0000000000..023860b19f --- /dev/null +++ b/backends/platform/sdl/macosx/macosx-main.cpp @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef MACOSX + +#include "backends/platform/sdl/macosx/macosx.h" +#include "backends/plugins/sdl/sdl-provider.h" +#include "base/main.h" + +int main(int argc, char *argv[]) { + + // Create our OSystem instance + g_system = new OSystem_MacOSX(); + assert(g_system); + + // Pre initialize the backend + ((OSystem_MacOSX *)g_system)->init(); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + + // Free OSystem + delete (OSystem_MacOSX *)g_system; + + return res; +} + +#endif diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp new file mode 100644 index 0000000000..a36769b417 --- /dev/null +++ b/backends/platform/sdl/macosx/macosx.cpp @@ -0,0 +1,76 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef MACOSX + +#include "backends/platform/sdl/macosx/macosx.h" +#include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h" + +#include "common/archive.h" +#include "common/fs.h" + +#include "CoreFoundation/CoreFoundation.h" + +OSystem_MacOSX::OSystem_MacOSX() + : + OSystem_POSIX("Library/Preferences/ScummVM Preferences") { +} + +void OSystem_MacOSX::initBackend() { + // Create the mixer manager + if (_mixer == 0) { + _mixerManager = new DoubleBufferSDLMixerManager(); + + // Setup and start mixer + _mixerManager->init(); + } + + // Invoke parent implementation of this method + OSystem_POSIX::initBackend(); +} + +void OSystem_MacOSX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + // Invoke parent implementation of this method + OSystem_POSIX::addSysArchivesToSearchSet(s, priority); + + // Get URL of the Resource directory of the .app bundle + CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); + if (fileUrl) { + // Try to convert the URL to an absolute path + UInt8 buf[MAXPATHLEN]; + if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) { + // Success: Add it to the search path + Common::String bundlePath((const char *)buf); + s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority); + } + CFRelease(fileUrl); + } +} + +void OSystem_MacOSX::setupIcon() { + // Don't set icon on OS X, as we use a nicer external icon there. +} + +#endif diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h new file mode 100644 index 0000000000..3c583a0ac0 --- /dev/null +++ b/backends/platform/sdl/macosx/macosx.h @@ -0,0 +1,41 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef PLATFORM_SDL_MACOSX_H +#define PLATFORM_SDL_MACOSX_H + +#include "backends/platform/sdl/posix/posix.h" + +class OSystem_MacOSX : public OSystem_POSIX { +public: + OSystem_MacOSX(); + virtual ~OSystem_MacOSX() {} + + virtual void initBackend(); + virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); + virtual void setupIcon(); +}; + +#endif diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp index 52bbb59165..38d0259121 100644 --- a/backends/platform/sdl/main.cpp +++ b/backends/platform/sdl/main.cpp @@ -23,48 +23,33 @@ * */ -// Fix for bug #2895217 "MSVC compilation broken with r47595": -// We need to keep this on top of the "common/scummsys.h" include, -// otherwise we will get errors about the windows headers redefining -// "ARRAYSIZE" for example. -#if defined(WIN32) && !defined(__SYMBIAN32__) -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -// winnt.h defines ARRAYSIZE, but we want our own one... -#undef ARRAYSIZE -#endif - -#include "common/scummsys.h" - // Several SDL based ports use a custom main, and hence do not want to compile // of this file. The following "#if" ensures that. -#if !defined(__MAEMO__) && !defined(_WIN32_WCE) && !defined(GP2XWIZ)&& !defined(LINUXMOTO) && !defined(__SYMBIAN32__) - +#if !defined(UNIX) && !defined(WIN32) && !defined(__MAEMO__) && !defined(__SYMBIAN32__) #include "backends/platform/sdl/sdl.h" #include "backends/plugins/sdl/sdl-provider.h" #include "base/main.h" -#ifdef WIN32 -int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpCmdLine*/, int /*iShowCmd*/) { - SDL_SetModuleHandle(GetModuleHandle(NULL)); - return main(__argc, __argv); -} -#endif - int main(int argc, char *argv[]) { // Create our OSystem instance g_system = new OSystem_SDL(); assert(g_system); + // Pre initialize the backend + ((OSystem_SDL *)g_system)->init(); + #ifdef DYNAMIC_MODULES PluginManager::instance().addPluginProvider(new SDLPluginProvider()); #endif // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - ((OSystem_SDL *)g_system)->deinit(); + + // Free OSystem + delete (OSystem_SDL *)g_system; + return res; } diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk index 43751a57b2..a26c57f46c 100644 --- a/backends/platform/sdl/module.mk +++ b/backends/platform/sdl/module.mk @@ -1,13 +1,25 @@ MODULE := backends/platform/sdl MODULE_OBJS := \ - events.o \ - graphics.o \ + posix/posix-main.o \ + posix/posix.o \ hardwarekeys.o \ main.o \ sdl.o -# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. +ifdef MACOSX +MODULE_OBJS += \ + macosx/macosx-main.o \ + macosx/macosx.o +endif + +ifdef WIN32 +MODULE_OBJS += \ + win32/win32-main.o \ + win32/win32.o +endif + +# We don't use the rules.mk here on purpose MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) OBJS := $(MODULE_OBJS) $(OBJS) -MODULE_DIRS += $(sort $(dir $(MODULE_OBJS))) +MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
\ No newline at end of file diff --git a/backends/platform/sdl/posix/posix-main.cpp b/backends/platform/sdl/posix/posix-main.cpp new file mode 100644 index 0000000000..ad11fc230e --- /dev/null +++ b/backends/platform/sdl/posix/posix-main.cpp @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(UNIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(LINUXMOTO) && !defined(GP2XWIZ) && !defined(GP2X) + +#include "backends/platform/sdl/posix/posix.h" +#include "backends/plugins/sdl/sdl-provider.h" +#include "base/main.h" + +int main(int argc, char *argv[]) { + + // Create our OSystem instance + g_system = new OSystem_POSIX(); + assert(g_system); + + // Pre initialize the backend + ((OSystem_POSIX *)g_system)->init(); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + + // Free OSystem + delete (OSystem_POSIX *)g_system; + + return res; +} + +#endif diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp new file mode 100644 index 0000000000..c9c7304c0f --- /dev/null +++ b/backends/platform/sdl/posix/posix.cpp @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef UNIX + +#include "backends/platform/sdl/posix/posix.h" +#include "backends/saves/posix/posix-saves.h" +#include "backends/fs/posix/posix-fs-factory.h" + +OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName) + : + _baseConfigName(baseConfigName) { +} + +void OSystem_POSIX::init() { + // Initialze File System Factory + _fsFactory = new POSIXFilesystemFactory(); + + // Invoke parent implementation of this method + OSystem_SDL::init(); +} + +void OSystem_POSIX::initBackend() { + // Create the savefile manager + if (_savefileManager == 0) + _savefileManager = new POSIXSaveFileManager(); + + // Invoke parent implementation of this method + OSystem_SDL::initBackend(); +} + +Common::String OSystem_POSIX::getDefaultConfigFileName() { + char configFile[MAXPATHLEN]; + + // On UNIX 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()); + + return configFile; +} + +#endif diff --git a/backends/platform/sdl/posix/posix.h b/backends/platform/sdl/posix/posix.h new file mode 100644 index 0000000000..13f9304f1e --- /dev/null +++ b/backends/platform/sdl/posix/posix.h @@ -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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef PLATFORM_SDL_POSIX_H +#define PLATFORM_SDL_POSIX_H + +#include "backends/platform/sdl/sdl.h" + +class OSystem_POSIX : public OSystem_SDL { +public: + // Let the subclasses be able to change _baseConfigName in the constructor + OSystem_POSIX(Common::String baseConfigName = ".scummvmrc"); + virtual ~OSystem_POSIX() {} + + virtual void init(); + virtual void initBackend(); + +protected: + // Base string for creating the default path and filename + // for the configuration file + Common::String _baseConfigName; + + virtual Common::String getDefaultConfigFileName(); +}; + +#endif diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 6686249416..cf6d44ebb7 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -23,303 +23,124 @@ * */ -#if defined(WIN32) -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -// winnt.h defines ARRAYSIZE, but we want our own one... - this is needed before including util.h -#undef ARRAYSIZE -#endif - #include "backends/platform/sdl/sdl.h" -#include "common/archive.h" #include "common/config-manager.h" -#include "common/debug.h" #include "common/EventRecorder.h" -#include "common/util.h" -#ifdef UNIX - #include "backends/saves/posix/posix-saves.h" -#else - #include "backends/saves/default/default-saves.h" +#include "backends/saves/default/default-saves.h" +#include "backends/audiocd/sdl/sdl-audiocd.h" +#include "backends/events/sdl/sdl-events.h" +#include "backends/mutex/sdl/sdl-mutex.h" +#include "backends/timer/sdl/sdl-timer.h" +#include "backends/graphics/sdl/sdl-graphics.h" +#ifdef USE_OPENGL +#include "backends/graphics/openglsdl/openglsdl-graphics.h" #endif -#include "backends/timer/default/default-timer.h" -#include "sound/mixer_intern.h" #include "icons/scummvm.xpm" -#include <time.h> // for getTimeAndDate() - -//#define SAMPLES_PER_SEC 11025 -#define SAMPLES_PER_SEC 22050 -//#define SAMPLES_PER_SEC 44100 - - -/* - * Include header files needed for the getFilesystemFactory() method. - */ -#if defined(__amigaos4__) - #include "backends/fs/amigaos4/amigaos4-fs-factory.h" -#elif defined(UNIX) - #include "backends/fs/posix/posix-fs-factory.h" -#elif defined(WIN32) - #include "backends/fs/windows/windows-fs-factory.h" -#endif +#include <time.h> - -#if defined(UNIX) -#ifdef MACOSX -#define DEFAULT_CONFIG_FILE "Library/Preferences/ScummVM Preferences" -#elif defined(SAMSUNGTV) -#define DEFAULT_CONFIG_FILE "/dtv/usb/sda1/.scummvmrc" -#else -#define DEFAULT_CONFIG_FILE ".scummvmrc" -#endif -#else -#define DEFAULT_CONFIG_FILE "scummvm.ini" -#endif - -#if defined(MACOSX) || defined(IPHONE) -#include "CoreFoundation/CoreFoundation.h" +OSystem_SDL::OSystem_SDL() + : +#ifdef USE_OPENGL + _graphicsModes(0), + _graphicsMode(0), + _sdlModesCount(0), + _glModesCount(0), #endif + _inited(false), + _initedSDL(false), + _mixerManager(0) { - -static Uint32 timer_handler(Uint32 interval, void *param) { - ((DefaultTimerManager *)param)->handler(); - return interval; } -AspectRatio::AspectRatio(int w, int h) { - // TODO : Validation and so on... - // Currently, we just ensure the program don't instantiate non-supported aspect ratios - _kw = w; - _kh = h; +OSystem_SDL::~OSystem_SDL() { + deinit(); } -#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS) -static AspectRatio getDesiredAspectRatio() { - const size_t AR_COUNT = 4; - const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" }; - const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) }; +void OSystem_SDL::init() { + // Initialize SDL + initSDL(); - //TODO : We could parse an arbitrary string, if we code enough proper validation - Common::String desiredAspectRatio = ConfMan.get("desired_screen_aspect_ratio"); + // Creates the early needed managers, if they don't exist yet + // (we check for this to allow subclasses to provide their own). + if (_mutexManager == 0) + _mutexManager = new SdlMutexManager(); - for (size_t i = 0; i < AR_COUNT; i++) { - assert(desiredAspectRatioAsStrings[i] != NULL); - - if (!scumm_stricmp(desiredAspectRatio.c_str(), desiredAspectRatioAsStrings[i])) { - return desiredAspectRatios[i]; - } - } - // TODO : Report a warning - return AspectRatio(0, 0); + if (_timerManager == 0) + _timerManager = new SdlTimerManager(); } -#endif void OSystem_SDL::initBackend() { + // Check if backend has not been initialized assert(!_inited); - int joystick_num = ConfMan.getInt("joystick_num"); - uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; - - if (ConfMan.hasKey("disable_sdl_parachute")) - sdlFlags |= SDL_INIT_NOPARACHUTE; + // Creates the backend managers, if they don't exist yet (we check + // for this to allow subclasses to provide their own). + if (_eventManager == 0) + _eventManager = new SdlEventManager(this); -#ifdef _WIN32_WCE - if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) { - SDL_VideoInit("windib", 0); - sdlFlags ^= SDL_INIT_VIDEO; - } -#endif + if (_savefileManager == 0) + _savefileManager = new DefaultSaveFileManager(); - if (joystick_num > -1) - sdlFlags |= SDL_INIT_JOYSTICK; + if (_mixerManager == 0) { + _mixerManager = new SdlMixerManager(); - if (SDL_Init(sdlFlags) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); + // Setup and start mixer + _mixerManager->init(); } - _graphicsMutex = createMutex(); - - SDL_ShowCursor(SDL_DISABLE); + if (_graphicsManager == 0) { +#ifdef USE_OPENGL + // Setup a list with both SDL and OpenGL graphics modes + setupGraphicsModes(); - // Enable unicode support if possible - SDL_EnableUNICODE(1); + if (ConfMan.hasKey("gfx_mode")) { + Common::String gfxMode(ConfMan.get("gfx_mode")); + bool use_opengl = false; + const OSystem::GraphicsMode *mode = OpenGLSdlGraphicsManager::supportedGraphicsModes(); + while (mode->name) { + if (scumm_stricmp(mode->name, gfxMode.c_str()) == 0) + use_opengl = true; - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); - memset(&_videoMode, 0, sizeof(_videoMode)); - memset(&_transactionDetails, 0, sizeof(_transactionDetails)); + mode++; + } -#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS) - _videoMode.mode = GFX_DOUBLESIZE; - _videoMode.scaleFactor = 2; - _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); - _videoMode.desiredAspectRatio = getDesiredAspectRatio(); - _scalerProc = Normal2x; -#else // for small screen platforms - _videoMode.mode = GFX_NORMAL; - _videoMode.scaleFactor = 1; - _videoMode.aspectRatioCorrection = false; - _scalerProc = Normal1x; + // If the gfx_mode is from OpenGL, create the OpenGL graphics manager + if (use_opengl) + _graphicsManager = new OpenGLSdlGraphicsManager(); + } #endif - _scalerType = 0; + if (_graphicsManager == 0) + _graphicsManager = new SdlGraphicsManager(); + } -#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) - _videoMode.fullscreen = ConfMan.getBool("fullscreen"); -#else - _videoMode.fullscreen = true; -#endif + if (_audiocdManager == 0) + _audiocdManager = new SdlAudioCDManager(); -#if !defined(MACOSX) && !defined(__SYMBIAN32__) // Setup a custom program icon. - // Don't set icon on OS X, as we use a nicer external icon there. - // Don't for Symbian: it uses the EScummVM.aif file for the icon. setupIcon(); -#endif - - // enable joystick - if (joystick_num > -1 && SDL_NumJoysticks() > 0) { - printf("Using joystick: %s\n", SDL_JoystickName(0)); - _joystick = SDL_JoystickOpen(joystick_num); - } - - - // Create the savefile manager, if none exists yet (we check for this to - // allow subclasses to provide their own). - if (_savefile == 0) { -#ifdef UNIX - _savefile = new POSIXSaveFileManager(); -#else - _savefile = new DefaultSaveFileManager(); -#endif - } - - // Create and hook up the mixer, if none exists yet (we check for this to - // allow subclasses to provide their own). - if (_mixer == 0) { - setupMixer(); - } - - // Create and hook up the timer manager, if none exists yet (we check for - // this to allow subclasses to provide their own). - if (_timer == 0) { - // Note: We could implement a custom SDLTimerManager by using - // SDL_AddTimer. That might yield better timer resolution, but it would - // also change the semantics of a timer: Right now, ScummVM timers - // *never* run in parallel, due to the way they are implemented. If we - // switched to SDL_AddTimer, each timer might run in a separate thread. - // However, not all our code is prepared for that, so we can't just - // switch. Still, it's a potential future change to keep in mind. - _timer = new DefaultTimerManager(); - _timerID = SDL_AddTimer(10, &timer_handler, _timer); - } - - // Invoke parent implementation of this method - OSystem::initBackend(); _inited = true; } -OSystem_SDL::OSystem_SDL() - : -#ifdef USE_OSD - _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0), -#endif - _hwscreen(0), _screen(0), _tmpscreen(0), -#ifdef USE_RGB_COLOR - _screenFormat(Graphics::PixelFormat::createFormatCLUT8()), - _cursorFormat(Graphics::PixelFormat::createFormatCLUT8()), -#endif - _overlayVisible(false), - _overlayscreen(0), _tmpscreen2(0), - _cdrom(0), _scalerProc(0), _modeChanged(false), _screenChangeCount(0), - _scrollLock(false), - _mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0), - _mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true), - _joystick(0), - _currentShakePos(0), _newShakePos(0), - _paletteDirtyStart(0), _paletteDirtyEnd(0), -#if MIXER_DOUBLE_BUFFERING - _soundMutex(0), _soundCond(0), _soundThread(0), - _soundThreadIsRunning(false), _soundThreadShouldQuit(false), -#endif - _fsFactory(0), - _savefile(0), - _mixer(0), - _timer(0), - _screenIsLocked(false), - _graphicsMutex(0), _transactionMode(kTransactionNone) { - - // clear palette storage - memset(_currentPalette, 0, sizeof(_currentPalette)); - memset(_cursorPalette, 0, sizeof(_cursorPalette)); - - _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; - - // reset mouse state - memset(&_km, 0, sizeof(_km)); - memset(&_mouseCurState, 0, sizeof(_mouseCurState)); - - _inited = false; - - - #if defined(__amigaos4__) - _fsFactory = new AmigaOSFilesystemFactory(); - #elif defined(UNIX) - _fsFactory = new POSIXFilesystemFactory(); - #elif defined(WIN32) - _fsFactory = new WindowsFilesystemFactory(); - #elif defined(__SYMBIAN32__) - // Do nothing since its handled by the Symbian SDL inheritance - #else - #error Unknown and unsupported FS backend - #endif -} - -OSystem_SDL::~OSystem_SDL() { - SDL_RemoveTimer(_timerID); - closeMixer(); +void OSystem_SDL::initSDL() { + // Check if SDL has not been initialized + if (!_initedSDL) { + uint32 sdlFlags = 0; + if (ConfMan.hasKey("disable_sdl_parachute")) + sdlFlags |= SDL_INIT_NOPARACHUTE; - free(_mouseData); + // Initialize SDL (SDL Subsystems are initiliazed in the corresponding sdl managers) + if (SDL_Init(sdlFlags) == -1) + error("Could not initialize SDL: %s", SDL_GetError()); - delete _savefile; - delete _timer; -} + // Enable unicode support if possible + SDL_EnableUNICODE(1); -uint32 OSystem_SDL::getMillis() { - uint32 millis = SDL_GetTicks(); - g_eventRec.processMillis(millis); - return millis; -} - -void OSystem_SDL::delayMillis(uint msecs) { - SDL_Delay(msecs); -} - -void OSystem_SDL::getTimeAndDate(TimeDate &td) const { - time_t curTime = time(0); - struct tm t = *localtime(&curTime); - td.tm_sec = t.tm_sec; - td.tm_min = t.tm_min; - td.tm_hour = t.tm_hour; - td.tm_mday = t.tm_mday; - td.tm_mon = t.tm_mon; - td.tm_year = t.tm_year; -} - -Common::TimerManager *OSystem_SDL::getTimerManager() { - assert(_timer); - return _timer; -} - -Common::SaveFileManager *OSystem_SDL::getSavefileManager() { - assert(_savefile); - return _savefile; -} - -FilesystemFactory *OSystem_SDL::getFilesystemFactory() { - assert(_fsFactory); - return _fsFactory; + _initedSDL = true; + } } void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { @@ -333,88 +154,10 @@ void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) } #endif -#ifdef MACOSX - // Get URL of the Resource directory of the .app bundle - CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); - if (fileUrl) { - // Try to convert the URL to an absolute path - UInt8 buf[MAXPATHLEN]; - if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) { - // Success: Add it to the search path - Common::String bundlePath((const char *)buf); - s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority); - } - CFRelease(fileUrl); - } - -#endif - } - -static Common::String getDefaultConfigFileName() { - char configFile[MAXPATHLEN]; -#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) - OSVERSIONINFO win32OsVersion; - ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); - win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&win32OsVersion); - // Check for non-9X version of Windows. - if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { - // Use the Application Data directory of the user profile. - if (win32OsVersion.dwMajorVersion >= 5) { - if (!GetEnvironmentVariable("APPDATA", configFile, sizeof(configFile))) - error("Unable to access application data directory"); - } else { - if (!GetEnvironmentVariable("USERPROFILE", configFile, sizeof(configFile))) - error("Unable to access user profile directory"); - - strcat(configFile, "\\Application Data"); - CreateDirectory(configFile, NULL); - } - - strcat(configFile, "\\ScummVM"); - CreateDirectory(configFile, NULL); - strcat(configFile, "\\" DEFAULT_CONFIG_FILE); - - FILE *tmp = NULL; - if ((tmp = fopen(configFile, "r")) == NULL) { - // Check windows directory - char oldConfigFile[MAXPATHLEN]; - GetWindowsDirectory(oldConfigFile, MAXPATHLEN); - strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE); - if ((tmp = fopen(oldConfigFile, "r"))) { - strcpy(configFile, oldConfigFile); - - fclose(tmp); - } - } else { - fclose(tmp); - } - } else { - // Check windows directory - GetWindowsDirectory(configFile, MAXPATHLEN); - strcat(configFile, "\\" DEFAULT_CONFIG_FILE); - } -#elif defined(UNIX) - // On UNIX type systems, by default we store the config file inside - // to the HOME directory of the user. - // - // GP2X is Linux based but Home dir can be read only so do not use - // it and put the config in the executable dir. - // - // On the iPhone, the home dir of the user when you launch the app - // from the Springboard, is /. Which we don't want. - const char *home = getenv("HOME"); - if (home != NULL && strlen(home) < MAXPATHLEN) - snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE); - else - strcpy(configFile, DEFAULT_CONFIG_FILE); -#else - strcpy(configFile, DEFAULT_CONFIG_FILE); -#endif - - return configFile; +Common::String OSystem_SDL::getDefaultConfigFileName() { + return "scummvm.ini"; } Common::SeekableReadStream *OSystem_SDL::createConfigReadStream() { @@ -445,78 +188,34 @@ void OSystem_SDL::setWindowCaption(const char *caption) { SDL_WM_SetCaption(cap.c_str(), cap.c_str()); } -bool OSystem_SDL::hasFeature(Feature f) { - return - (f == kFeatureFullscreenMode) || - (f == kFeatureAspectRatioCorrection) || - (f == kFeatureCursorHasPalette) || - (f == kFeatureIconifyWindow); -} - -void OSystem_SDL::setFeatureState(Feature f, bool enable) { - switch (f) { - case kFeatureFullscreenMode: - setFullscreenMode(enable); - break; - case kFeatureAspectRatioCorrection: - setAspectRatioCorrection(enable); - break; - case kFeatureIconifyWindow: - if (enable) - SDL_WM_IconifyWindow(); - break; - default: - break; - } -} - -bool OSystem_SDL::getFeatureState(Feature f) { - assert (_transactionMode == kTransactionNone); - - switch (f) { - case kFeatureFullscreenMode: - return _videoMode.fullscreen; - case kFeatureAspectRatioCorrection: - return _videoMode.aspectRatioCorrection; - default: - return false; - } -} - void OSystem_SDL::deinit() { - if (_cdrom) { - SDL_CDStop(_cdrom); - SDL_CDClose(_cdrom); - } - unloadGFXMode(); - deleteMutex(_graphicsMutex); - - if (_joystick) - SDL_JoystickClose(_joystick); - SDL_ShowCursor(SDL_ENABLE); - SDL_RemoveTimer(_timerID); - closeMixer(); - - free(_mouseData); - - delete _timer; + delete _savefileManager; + _savefileManager = 0; + delete _graphicsManager; + _graphicsManager = 0; + delete _eventManager; + _eventManager = 0; + delete _audiocdManager; + _audiocdManager = 0; + delete _mixerManager; + _mixerManager = 0; + delete _timerManager; + _timerManager = 0; + delete _mutexManager; + _mutexManager = 0; + +#ifdef USE_OPENGL + free((void *)_graphicsModes), +#endif SDL_Quit(); - - // Event Manager requires save manager for storing - // recorded events - delete getEventManager(); - delete _savefile; } void OSystem_SDL::quit() { deinit(); - -#if !defined(SAMSUNGTV) exit(0); -#endif } void OSystem_SDL::setupIcon() { @@ -571,289 +270,126 @@ void OSystem_SDL::setupIcon() { free(icon); } -OSystem::MutexRef OSystem_SDL::createMutex() { - return (MutexRef) SDL_CreateMutex(); -} - -void OSystem_SDL::lockMutex(MutexRef mutex) { - SDL_mutexP((SDL_mutex *) mutex); +bool OSystem_SDL::pollEvent(Common::Event &event) { + assert(_eventManager); + return ((SdlEventManager *)_eventManager)->pollSdlEvent(event); } -void OSystem_SDL::unlockMutex(MutexRef mutex) { - SDL_mutexV((SDL_mutex *) mutex); -} - -void OSystem_SDL::deleteMutex(MutexRef mutex) { - SDL_DestroyMutex((SDL_mutex *) mutex); +uint32 OSystem_SDL::getMillis() { + uint32 millis = SDL_GetTicks(); + g_eventRec.processMillis(millis); + return millis; } -#pragma mark - -#pragma mark --- Audio --- -#pragma mark - - -#if MIXER_DOUBLE_BUFFERING - -void OSystem_SDL::mixerProducerThread() { - byte nextSoundBuffer; - - SDL_LockMutex(_soundMutex); - while (true) { - // Wait till we are allowed to produce data - SDL_CondWait(_soundCond, _soundMutex); - - if (_soundThreadShouldQuit) - break; - - // Generate samples and put them into the next buffer - nextSoundBuffer = _activeSoundBuf ^ 1; - _mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize); - - // Swap buffers - _activeSoundBuf = nextSoundBuffer; - } - SDL_UnlockMutex(_soundMutex); +void OSystem_SDL::delayMillis(uint msecs) { + SDL_Delay(msecs); } -int SDLCALL OSystem_SDL::mixerProducerThreadEntry(void *arg) { - OSystem_SDL *this_ = (OSystem_SDL *)arg; - assert(this_); - this_->mixerProducerThread(); - return 0; +void OSystem_SDL::getTimeAndDate(TimeDate &td) const { + time_t curTime = time(0); + struct tm t = *localtime(&curTime); + td.tm_sec = t.tm_sec; + td.tm_min = t.tm_min; + td.tm_hour = t.tm_hour; + td.tm_mday = t.tm_mday; + td.tm_mon = t.tm_mon; + td.tm_year = t.tm_year; } - -void OSystem_SDL::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) { - _soundThreadIsRunning = false; - _soundThreadShouldQuit = false; - - // Create mutex and condition variable - _soundMutex = SDL_CreateMutex(); - _soundCond = SDL_CreateCond(); - - // Create two sound buffers - _activeSoundBuf = 0; - _soundBufSize = bufSize; - _soundBuffers[0] = (byte *)calloc(1, bufSize); - _soundBuffers[1] = (byte *)calloc(1, bufSize); - - _soundThreadIsRunning = true; - - // Finally start the thread - _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this); +Audio::Mixer *OSystem_SDL::getMixer() { + assert(_mixerManager); + return _mixerManager->getMixer(); } -void OSystem_SDL::deinitThreadedMixer() { - // Kill thread?? _soundThread - - if (_soundThreadIsRunning) { - // Signal the producer thread to end, and wait for it to actually finish. - _soundThreadShouldQuit = true; - SDL_CondBroadcast(_soundCond); - SDL_WaitThread(_soundThread, NULL); - - // Kill the mutex & cond variables. - // Attention: AT this point, the mixer callback must not be running - // anymore, else we will crash! - SDL_DestroyMutex(_soundMutex); - SDL_DestroyCond(_soundCond); - - _soundThreadIsRunning = false; - - free(_soundBuffers[0]); - free(_soundBuffers[1]); - } +SdlMixerManager *OSystem_SDL::getMixerManager() { + assert(_mixerManager); + return _mixerManager; } +#ifdef USE_OPENGL -void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) { - OSystem_SDL *this_ = (OSystem_SDL *)arg; - assert(this_); - assert(this_->_mixer); - - assert((int)this_->_soundBufSize == len); - - // Lock mutex, to ensure our data is not overwritten by the producer thread - SDL_LockMutex(this_->_soundMutex); - - // Copy data from the current sound buffer - memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len); - - // Unlock mutex and wake up the produced thread - SDL_UnlockMutex(this_->_soundMutex); - SDL_CondSignal(this_->_soundCond); +const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const { + return _graphicsModes; } -#else - -void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) { - OSystem_SDL *this_ = (OSystem_SDL *)sys; - assert(this_); - assert(this_->_mixer); - - this_->_mixer->mixCallback(samples, len); +int OSystem_SDL::getDefaultGraphicsMode() const { + if (_graphicsMode < _sdlModesCount) + return _graphicsManager->getDefaultGraphicsMode(); + else + return _graphicsManager->getDefaultGraphicsMode() + _sdlModesCount; } -#endif - -void OSystem_SDL::setupMixer() { - SDL_AudioSpec desired; - - // Determine the desired output sampling frequency. - uint32 samplesPerSec = 0; - if (ConfMan.hasKey("output_rate")) - samplesPerSec = ConfMan.getInt("output_rate"); - if (samplesPerSec <= 0) - samplesPerSec = SAMPLES_PER_SEC; - - // Determine the sample buffer size. We want it to store enough data for - // at least 1/16th of a second (though at most 8192 samples). Note - // that it must be a power of two. So e.g. at 22050 Hz, we request a - // sample buffer size of 2048. - uint32 samples = 8192; - while (samples * 16 > samplesPerSec * 2) - samples >>= 1; - - memset(&desired, 0, sizeof(desired)); - desired.freq = samplesPerSec; - desired.format = AUDIO_S16SYS; - desired.channels = 2; - desired.samples = (uint16)samples; - desired.callback = mixCallback; - desired.userdata = this; - - assert(!_mixer); - if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) { - warning("Could not open audio device: %s", SDL_GetError()); - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(false); +bool OSystem_SDL::setGraphicsMode(int mode) { + const OSystem::GraphicsMode *srcMode; + int i; + if (mode < _sdlModesCount) { + srcMode = SdlGraphicsManager::supportedGraphicsModes(); + i = 0; } else { - // Note: This should be the obtained output rate, but it seems that at - // least on some platforms SDL will lie and claim it did get the rate - // even if it didn't. Probably only happens for "weird" rates, though. - samplesPerSec = _obtainedRate.freq; - debug(1, "Output sample rate: %d Hz", samplesPerSec); - - // Create the mixer instance and start the sound processing - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(true); - -#if MIXER_DOUBLE_BUFFERING - initThreadedMixer(_mixer, _obtainedRate.samples * 4); -#endif - - // start the sound system - SDL_PauseAudio(0); + srcMode = OpenGLSdlGraphicsManager::supportedGraphicsModes(); + i = _sdlModesCount; } -} - -void OSystem_SDL::closeMixer() { - if (_mixer) - _mixer->setReady(false); - - SDL_CloseAudio(); - - delete _mixer; - _mixer = 0; - -#if MIXER_DOUBLE_BUFFERING - deinitThreadedMixer(); -#endif - -} - -Audio::Mixer *OSystem_SDL::getMixer() { - assert(_mixer); - return _mixer; -} - -#pragma mark - -#pragma mark --- CD Audio --- -#pragma mark - - -bool OSystem_SDL::openCD(int drive) { - if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1) - _cdrom = NULL; - else { - _cdrom = SDL_CDOpen(drive); - // Did it open? Check if _cdrom is NULL - if (!_cdrom) { - warning("Couldn't open drive: %s", SDL_GetError()); - } else { - _cdNumLoops = 0; - _cdStopTime = 0; - _cdEndTime = 0; + while (srcMode->name) { + if (i == mode) { + if (_graphicsMode >= _sdlModesCount && mode < _sdlModesCount) { + delete _graphicsManager; + _graphicsManager = new SdlGraphicsManager(); + _graphicsManager->beginGFXTransaction(); + } else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) { + delete _graphicsManager; + _graphicsManager = new OpenGLSdlGraphicsManager(); + _graphicsManager->beginGFXTransaction(); + } + _graphicsMode = mode; + return _graphicsManager->setGraphicsMode(srcMode->id); } + i++; + srcMode++; } - - return (_cdrom != NULL); -} - -void OSystem_SDL::stopCD() { /* Stop CD Audio in 1/10th of a second */ - _cdStopTime = SDL_GetTicks() + 100; - _cdNumLoops = 0; -} - -void OSystem_SDL::playCD(int track, int num_loops, int start_frame, int duration) { - if (!num_loops && !start_frame) - return; - - if (!_cdrom) - return; - - if (duration > 0) - duration += 5; - - _cdTrack = track; - _cdNumLoops = num_loops; - _cdStartFrame = start_frame; - - SDL_CDStatus(_cdrom); - if (start_frame == 0 && duration == 0) - SDL_CDPlayTracks(_cdrom, track, 0, 1, 0); - else - SDL_CDPlayTracks(_cdrom, track, start_frame, 0, duration); - _cdDuration = duration; - _cdStopTime = 0; - _cdEndTime = SDL_GetTicks() + _cdrom->track[track].length * 1000 / CD_FPS; + return false; } -bool OSystem_SDL::pollCD() { - if (!_cdrom) - return false; - - return (_cdNumLoops != 0 && (SDL_GetTicks() < _cdEndTime || SDL_CDStatus(_cdrom) == CD_PLAYING)); +int OSystem_SDL::getGraphicsMode() const { + return _graphicsMode; } -void OSystem_SDL::updateCD() { - if (!_cdrom) - return; +void OSystem_SDL::setupGraphicsModes() { + const OSystem::GraphicsMode *sdlGraphicsModes = SdlGraphicsManager::supportedGraphicsModes(); + const OSystem::GraphicsMode *openglGraphicsModes = OpenGLSdlGraphicsManager::supportedGraphicsModes(); + _sdlModesCount = 0; + _glModesCount = 0; - if (_cdStopTime != 0 && SDL_GetTicks() >= _cdStopTime) { - SDL_CDStop(_cdrom); - _cdNumLoops = 0; - _cdStopTime = 0; - return; + // Count the number of graphics modes + const OSystem::GraphicsMode *srcMode = sdlGraphicsModes; + while (srcMode->name) { + _sdlModesCount++; + srcMode++; + } + srcMode = openglGraphicsModes; + while (srcMode->name) { + _glModesCount ++; + srcMode++; } - if (_cdNumLoops == 0 || SDL_GetTicks() < _cdEndTime) - return; + // Allocate enough space for merged array of modes + _graphicsModes = (OSystem::GraphicsMode *)malloc(sizeof(OSystem::GraphicsMode) * (_glModesCount + _sdlModesCount + 1)); - if (_cdNumLoops != 1 && SDL_CDStatus(_cdrom) != CD_STOPPED) { - // Wait another second for it to be done - _cdEndTime += 1000; - return; - } + // Copy SDL graphics modes + memcpy((void *)_graphicsModes, sdlGraphicsModes, _sdlModesCount * sizeof(OSystem::GraphicsMode)); - if (_cdNumLoops > 0) - _cdNumLoops--; + // Copy OpenGL graphics modes + memcpy((void *)(_graphicsModes + _sdlModesCount), openglGraphicsModes, _glModesCount * sizeof(OSystem::GraphicsMode)); - if (_cdNumLoops != 0) { - if (_cdStartFrame == 0 && _cdDuration == 0) - SDL_CDPlayTracks(_cdrom, _cdTrack, 0, 1, 0); - else - SDL_CDPlayTracks(_cdrom, _cdTrack, _cdStartFrame, 0, _cdDuration); - _cdEndTime = SDL_GetTicks() + _cdrom->track[_cdTrack].length * 1000 / CD_FPS; + // Set a null mode at the end + memset((void *)(_graphicsModes + _sdlModesCount + _glModesCount), 0, sizeof(OSystem::GraphicsMode)); + + // Set new internal ids for all modes + int i = 0; + OSystem::GraphicsMode * mode = _graphicsModes; + while (mode->name) { + mode->id = i++; + mode++; } } + +#endif diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 5c901ba711..17d4dc4ed9 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -23,8 +23,8 @@ * */ -#ifndef SDL_COMMON_H -#define SDL_COMMON_H +#ifndef PLATFORM_SDL_H +#define PLATFORM_SDL_H #if defined(__SYMBIAN32__) #include <esdl\SDL.h> @@ -32,463 +32,94 @@ #include <SDL.h> #endif -#include "backends/base-backend.h" -#include "graphics/scaler.h" +#include "backends/modular-backend.h" +#include "backends/mixer/sdl/sdl-mixer.h" - -namespace Audio { - class MixerImpl; -} - -#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) -// Uncomment this to enable the 'on screen display' code. -#define USE_OSD 1 -#endif - -#if defined(MACOSX) -// On Mac OS X, we need to double buffer the audio buffer, else anything -// which produces sampled data with high latency (like the MT-32 emulator) -// will sound terribly. -// This could be enabled for more / most ports in the future, but needs some -// testing. -#define MIXER_DOUBLE_BUFFERING 1 -#endif - - -enum { - GFX_NORMAL = 0, - GFX_DOUBLESIZE = 1, - GFX_TRIPLESIZE = 2, - GFX_2XSAI = 3, - GFX_SUPER2XSAI = 4, - GFX_SUPEREAGLE = 5, - GFX_ADVMAME2X = 6, - GFX_ADVMAME3X = 7, - GFX_HQ2X = 8, - GFX_HQ3X = 9, - GFX_TV2X = 10, - GFX_DOTMATRIX = 11 -}; - -class AspectRatio { - int _kw, _kh; -public: - AspectRatio() { _kw = _kh = 0; } - AspectRatio(int w, int h); - - bool isAuto() const { return (_kw | _kh) == 0; } - - int kw() const { return _kw; } - int kh() const { return _kh; } -}; - - -class OSystem_SDL : public BaseBackend { +/** + * Base OSystem class for all SDL ports. + */ +class OSystem_SDL : public ModularBackend { public: OSystem_SDL(); virtual ~OSystem_SDL(); - virtual void initBackend(); - - void beginGFXTransaction(); - TransactionError endGFXTransaction(); - -#ifdef USE_RGB_COLOR - // Game screen - virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; } - - // Highest supported - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; -#endif - - // Set the size and format of the video bitmap. - // Typically, 320x200 CLUT8 - virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format); // overloaded by CE backend - - virtual int getScreenChangeID() const { return _screenChangeCount; } - - // Set colors of the palette - void setPalette(const byte *colors, uint start, uint num); - - // Get colors of the palette - void grabPalette(byte *colors, uint start, uint num); - - // Draw a bitmap to screen. - // The screen will not be updated to reflect the new bitmap - virtual void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME) - - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - - // Update the dirty areas of the screen - void updateScreen(); - - // Either show or hide the mouse cursor - bool showMouse(bool visible); - - // Warp the mouse cursor. Where set_mouse_pos() only informs the - // backend of the mouse cursor's current position, this function - // actually moves the cursor to the specified position. - virtual void warpMouse(int x, int y); // overloaded by CE backend (FIXME) - - // Set the bitmap that's used when drawing the cursor. - virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend (FIXME) - - // Set colors of cursor palette - void setCursorPalette(const byte *colors, uint start, uint num); - - // Disables or enables cursor palette - void disableCursorPalette(bool disable) { - _cursorPaletteDisabled = disable; - blitCursor(); - } - - // Shaking is used in SCUMM. Set current shake position. - void setShakePos(int shake_pos); - - // Get the number of milliseconds since the program was started. - uint32 getMillis(); - - // Delay for a specified amount of milliseconds - void delayMillis(uint msecs); - - // Get the next event. - // Returns true if an event was retrieved. - virtual bool pollEvent(Common::Event &event); // overloaded by CE backend - -protected: - virtual bool dispatchSDLEvent(SDL_Event &ev, Common::Event &event); - - // Handlers for specific SDL events, called by pollEvent. - // This way, if a backend inherits fromt the SDL backend, it can - // change the behavior of only a single event, without having to override all - // of pollEvent. - virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event); - virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event); - virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event); - virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); - virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); - virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); - virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); - virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event); - -public: + /** + * Pre-initialize backend. It should be called after + * instantiating the backend. Early needed managers are + * created here. + */ + virtual void init(); + /** + * Get the Mixer Manager instance. Not to confuse with getMixer(), + * that returns Audio::Mixer. The Mixer Manager is a SDL wrapper class + * for the Audio::Mixer. Used by other managers. + */ + virtual SdlMixerManager *getMixerManager(); - // Define all hardware keys for keymapper + // Override functions from ModularBackend and OSystem + virtual void initBackend(); virtual Common::HardwareKeySet *getHardwareKeySet(); - - // Set function that generates samples - virtual void setupMixer(); - static void mixCallback(void *s, byte *samples, int len); - - virtual void closeMixer(); - - virtual Audio::Mixer *getMixer(); - - // Poll CD status - // Returns true if cd audio is playing - bool pollCD(); - - // Play CD audio track - void playCD(int track, int num_loops, int start_frame, int duration); - - // Stop CD audio track - void stopCD(); - - // Update CD audio status - void updateCD(); - - // Quit - virtual void quit(); // overloaded by CE backend - - void deinit(); - - virtual void getTimeAndDate(TimeDate &t) const; - virtual Common::TimerManager *getTimerManager(); - - // Mutex handling - MutexRef createMutex(); - void lockMutex(MutexRef mutex); - void unlockMutex(MutexRef mutex); - void deleteMutex(MutexRef mutex); - - // Overlay - virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; } - - virtual void showOverlay(); - virtual void hideOverlay(); - virtual void clearOverlay(); - virtual void grabOverlay(OverlayColor *buf, int pitch); - virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); - virtual int16 getHeight(); - virtual int16 getWidth(); - virtual int16 getOverlayHeight() { return _videoMode.overlayHeight; } - virtual int16 getOverlayWidth() { return _videoMode.overlayWidth; } - - virtual const GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool setGraphicsMode(int mode); - virtual int getGraphicsMode() const; - + virtual void quit(); + virtual void deinit(); virtual void setWindowCaption(const char *caption); - virtual bool openCD(int drive); - - virtual bool hasFeature(Feature f); - virtual void setFeatureState(Feature f, bool enable); - virtual bool getFeatureState(Feature f); - virtual void preprocessEvents(SDL_Event *event) {} - -#ifdef USE_OSD - void displayMessageOnOSD(const char *msg); -#endif - - virtual Common::SaveFileManager *getSavefileManager(); - virtual FilesystemFactory *getFilesystemFactory(); virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); - virtual Common::SeekableReadStream *createConfigReadStream(); virtual Common::WriteStream *createConfigWriteStream(); + virtual bool pollEvent(Common::Event &event); + virtual uint32 getMillis(); + virtual void delayMillis(uint msecs); + virtual void getTimeAndDate(TimeDate &td) const; + virtual Audio::Mixer *getMixer(); -protected: - bool _inited; - SDL_AudioSpec _obtainedRate; - -#ifdef USE_OSD - SDL_Surface *_osdSurface; - Uint8 _osdAlpha; // Transparency level of the OSD - uint32 _osdFadeStartTime; // When to start the fade out - enum { - kOSDFadeOutDelay = 2 * 1000, // Delay before the OSD is faded out (in milliseconds) - kOSDFadeOutDuration = 500, // Duration of the OSD fade out (in milliseconds) - kOSDColorKey = 1, - kOSDInitialAlpha = 80 // Initial alpha level, in percent + // HACK: Special SDL events types + enum SdlEvent { + kSdlEventExpose = 100, + kSdlEventResize = 101 }; -#endif - - // hardware screen - SDL_Surface *_hwscreen; - // unseen game screen - SDL_Surface *_screen; -#ifdef USE_RGB_COLOR - Graphics::PixelFormat _screenFormat; - Graphics::PixelFormat _cursorFormat; - Common::List<Graphics::PixelFormat> _supportedFormats; +protected: + bool _inited; + bool _initedSDL; /** - * Update the list of supported pixel formats. - * This method is invoked by loadGFXMode(). + * Mixer manager that configures and setups SDL for + * the wrapped Audio::Mixer, the true mixer. */ - void detectSupportedFormats(); -#endif - - // temporary screen (for scalers) - SDL_Surface *_tmpscreen; - SDL_Surface *_tmpscreen2; - - // overlay - SDL_Surface *_overlayscreen; - bool _overlayVisible; - Graphics::PixelFormat _overlayFormat; - - // CD Audio - SDL_CD *_cdrom; - int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration; - uint32 _cdEndTime, _cdStopTime; - - enum { - kTransactionNone = 0, - kTransactionActive = 1, - kTransactionRollback = 2 - }; - - struct TransactionDetails { - bool sizeChanged; - bool needHotswap; - bool needUpdatescreen; - bool normal1xScaler; -#ifdef USE_RGB_COLOR - bool formatChanged; -#endif - }; - TransactionDetails _transactionDetails; - - struct VideoState { - bool setup; - - bool fullscreen; - bool aspectRatioCorrection; - AspectRatio desiredAspectRatio; - - int mode; - int scaleFactor; - - int screenWidth, screenHeight; - int overlayWidth, overlayHeight; - int hardwareWidth, hardwareHeight; -#ifdef USE_RGB_COLOR - Graphics::PixelFormat format; -#endif - }; - VideoState _videoMode, _oldVideoMode; - - virtual void setGraphicsModeIntern(); // overloaded by CE backend - - /** Force full redraw on next updateScreen */ - bool _forceFull; - ScalerProc *_scalerProc; - int _scalerType; - int _transactionMode; - - bool _screenIsLocked; - Graphics::Surface _framebuffer; - - /** Current video mode flags (see DF_* constants) */ - bool _modeChanged; - int _screenChangeCount; - - enum { - NUM_DIRTY_RECT = 100, - MAX_SCALING = 3 - }; - - // Dirty rect management - SDL_Rect _dirtyRectList[NUM_DIRTY_RECT]; - int _numDirtyRects; - - // Keyboard mouse emulation. Disabled by fingolfin 2004-12-18. - // I am keeping the rest of the code in for now, since the joystick - // code (or rather, "hack") uses it, too. - struct KbdMouse { - int16 x, y, x_vel, y_vel, x_max, y_max, x_down_count, y_down_count; - uint32 last_time, delay_time, x_down_time, y_down_time; - }; - - struct MousePos { - // The mouse position, using either virtual (game) or real - // (overlay) coordinates. - int16 x, y; + SdlMixerManager *_mixerManager; - // The size and hotspot of the original cursor image. - int16 w, h; - int16 hotX, hotY; - - // The size and hotspot of the pre-scaled cursor image, in real - // coordinates. - int16 rW, rH; - int16 rHotX, rHotY; - - // The size and hotspot of the pre-scaled cursor image, in game - // coordinates. - int16 vW, vH; - int16 vHotX, vHotY; - - 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) - { } - }; - - // mouse - KbdMouse _km; - bool _mouseVisible; - bool _mouseNeedsRedraw; - byte *_mouseData; - SDL_Rect _mouseBackup; - MousePos _mouseCurState; -#ifdef USE_RGB_COLOR - uint32 _mouseKeyColor; -#else - byte _mouseKeyColor; -#endif - int _cursorTargetScale; - bool _cursorPaletteDisabled; - SDL_Surface *_mouseOrigSurface; - SDL_Surface *_mouseSurface; - enum { - kMouseColorKey = 1 - }; - - // Scroll lock state - since SDL doesn't track it - bool _scrollLock; - - // joystick - SDL_Joystick *_joystick; - - // Shake mode - int _currentShakePos; - int _newShakePos; - - // Palette data - SDL_Color _currentPalette[256]; - uint _paletteDirtyStart, _paletteDirtyEnd; + /** + * Initialze the SDL library. + */ + virtual void initSDL(); - // Cursor palette data - SDL_Color _cursorPalette[256]; + /** + * Setup the window icon. + */ + virtual void setupIcon(); /** - * Mutex which prevents multiple threads from interfering with each other - * when accessing the screen. + * Get the file path where the user configuration + * of ScummVM will be saved. */ - MutexRef _graphicsMutex; + virtual Common::String getDefaultConfigFileName(); -#ifdef MIXER_DOUBLE_BUFFERING - SDL_mutex *_soundMutex; - SDL_cond *_soundCond; - SDL_Thread *_soundThread; - bool _soundThreadIsRunning; - bool _soundThreadShouldQuit; +#ifdef USE_OPENGL + OSystem::GraphicsMode *_graphicsModes; + int _graphicsMode; + int _sdlModesCount; + int _glModesCount; - byte _activeSoundBuf; - uint _soundBufSize; - byte *_soundBuffers[2]; + /** + * Creates the merged graphics modes list + */ + virtual void setupGraphicsModes(); - void mixerProducerThread(); - static int SDLCALL mixerProducerThreadEntry(void *arg); - void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize); - void deinitThreadedMixer(); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual bool setGraphicsMode(int mode); + virtual int getGraphicsMode() const; #endif - - FilesystemFactory *_fsFactory; - Common::SaveFileManager *_savefile; - Audio::MixerImpl *_mixer; - - SDL_TimerID _timerID; - Common::TimerManager *_timer; - -protected: - virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); // overloaded by CE backend - - virtual void drawMouse(); // overloaded by CE backend - virtual void undrawMouse(); // overloaded by CE backend (FIXME) - virtual void blitCursor(); // overloaded by CE backend (FIXME) - - /** Set the position of the virtual mouse cursor. */ - void setMousePos(int x, int y); - virtual void fillMouseEvent(Common::Event &event, int x, int y); // overloaded by CE backend - void toggleMouseGrab(); - - virtual void internUpdateScreen(); // overloaded by CE backend - - virtual bool loadGFXMode(); // overloaded by CE backend - virtual void unloadGFXMode(); // overloaded by CE backend - virtual bool hotswapGFXMode(); // overloaded by CE backend - - void setFullscreenMode(bool enable); - void setAspectRatioCorrection(bool enable); - - virtual bool saveScreenshot(const char *filename); // overloaded by CE backend - - int effectiveScreenHeight() const; - - void setupIcon(); - void handleKbdMouse(); - - virtual bool remapKey(SDL_Event &ev, Common::Event &event); - - bool handleScalerHotkeys(const SDL_KeyboardEvent &key); - bool isScalerHotkey(const Common::Event &event); }; #endif diff --git a/backends/platform/sdl/win32/win32-main.cpp b/backends/platform/sdl/win32/win32-main.cpp new file mode 100644 index 0000000000..25f208ddac --- /dev/null +++ b/backends/platform/sdl/win32/win32-main.cpp @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef WIN32 + +// Fix for bug #2895217 "MSVC compilation broken with r47595": +// We need to keep this on top of the "common/scummsys.h"(base/main.h) include, +// otherwise we will get errors about the windows headers redefining +// "ARRAYSIZE" for example. +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef ARRAYSIZE // winnt.h defines ARRAYSIZE, but we want our own one... + +#include "backends/platform/sdl/win32/win32.h" +#include "backends/plugins/sdl/sdl-provider.h" +#include "base/main.h" + +int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpCmdLine*/, int /*iShowCmd*/) { + SDL_SetModuleHandle(GetModuleHandle(NULL)); + return main(__argc, __argv); +} + +int main(int argc, char *argv[]) { + // Create our OSystem instance + g_system = new OSystem_Win32(); + assert(g_system); + + // Pre initialize the backend + ((OSystem_Win32 *)g_system)->init(); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + + // Free OSystem + delete (OSystem_Win32 *)g_system; + + return res; +} + +#endif diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp new file mode 100644 index 0000000000..05005dee6f --- /dev/null +++ b/backends/platform/sdl/win32/win32.cpp @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifdef WIN32 + +#include <windows.h> +#define WIN32_LEAN_AND_MEAN +#undef ARRAYSIZE // winnt.h defines ARRAYSIZE, but we want our own one... + +#include "backends/platform/sdl/win32/win32.h" +#include "backends/fs/windows/windows-fs-factory.h" + +#define DEFAULT_CONFIG_FILE "scummvm.ini" + +void OSystem_Win32::init() { + // Initialze File System Factory + _fsFactory = new WindowsFilesystemFactory(); + + // Invoke parent implementation of this method + OSystem_SDL::init(); +} + +Common::String OSystem_Win32::getDefaultConfigFileName() { + char configFile[MAXPATHLEN]; + + OSVERSIONINFO win32OsVersion; + ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); + win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&win32OsVersion); + // Check for non-9X version of Windows. + if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { + // Use the Application Data directory of the user profile. + if (win32OsVersion.dwMajorVersion >= 5) { + if (!GetEnvironmentVariable("APPDATA", configFile, sizeof(configFile))) + error("Unable to access application data directory"); + } else { + if (!GetEnvironmentVariable("USERPROFILE", configFile, sizeof(configFile))) + error("Unable to access user profile directory"); + + strcat(configFile, "\\Application Data"); + CreateDirectory(configFile, NULL); + } + + strcat(configFile, "\\ScummVM"); + CreateDirectory(configFile, NULL); + strcat(configFile, "\\" DEFAULT_CONFIG_FILE); + + FILE *tmp = NULL; + if ((tmp = fopen(configFile, "r")) == NULL) { + // Check windows directory + char oldConfigFile[MAXPATHLEN]; + GetWindowsDirectory(oldConfigFile, MAXPATHLEN); + strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE); + if ((tmp = fopen(oldConfigFile, "r"))) { + strcpy(configFile, oldConfigFile); + + fclose(tmp); + } + } else { + fclose(tmp); + } + } else { + // Check windows directory + GetWindowsDirectory(configFile, MAXPATHLEN); + strcat(configFile, "\\" DEFAULT_CONFIG_FILE); + } + + return configFile; +} + +#endif diff --git a/backends/platform/sdl/win32/win32.h b/backends/platform/sdl/win32/win32.h new file mode 100644 index 0000000000..f18ee6ead1 --- /dev/null +++ b/backends/platform/sdl/win32/win32.h @@ -0,0 +1,39 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef PLATFORM_SDL_WIN32_H +#define PLATFORM_SDL_WIN32_H + +#include "backends/platform/sdl/sdl.h" + +class OSystem_Win32 : public OSystem_SDL { +public: + virtual void init(); + +protected: + virtual Common::String getDefaultConfigFileName(); +}; + +#endif diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index d63c9fe044..3a0dc318b3 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -26,26 +26,17 @@ #include <sdlapp.h> // for CSDLApp::GetExecutablePathCStr() @ Symbian::GetExecutablePath() #include <bautils.h> -#include "backends/fs/symbian/symbian-fs-factory.h" #include "backends/platform/symbian/src/SymbianOS.h" #include "backends/platform/symbian/src/SymbianActions.h" -#include "backends/saves/default/default-saves.h" - -#include "base/main.h" - #include "common/config-manager.h" #include "common/scummsys.h" -#include "common/translation.h" - #include "gui/message.h" -#include "sound/mixer_intern.h" - -#ifdef SAMPLES_PER_SEC_8000 // the GreanSymbianMMP format cannot handle values for defines :( - #define SAMPLES_PER_SEC 8000 -#else - #define SAMPLES_PER_SEC 16000 -#endif +#include "backends/fs/symbian/symbian-fs-factory.h" +#include "backends/saves/default/default-saves.h" +#include "backends/events/symbiansdl/symbiansdl-events.h" +#include "backends/graphics/symbiansdl/symbiansdl-graphics.h" +#include "backends/mixer/symbiansdl/symbiansdl-mixer.h" #define DEFAULT_CONFIG_FILE "scummvm.ini" #define DEFAULT_SAVE_PATH "Savegames" @@ -58,8 +49,7 @@ void FatalError(const char *msg) { TPtrC8 msgPtr((const TUint8 *)msg); TBuf<512> msg16Bit; msg16Bit.Copy(msgPtr); -#ifdef S60 -#else +#ifndef S60 CEikonEnv::Static()->InfoWinL(_L("ScummVM Fatal Error"), msg16Bit); #endif if (g_system) @@ -67,7 +57,7 @@ void FatalError(const char *msg) { } // make this easily available everywhere -char* GetExecutablePath() { +char *GetExecutablePath() { return CSDLApp::GetExecutablePathCStr(); } @@ -75,66 +65,13 @@ char* GetExecutablePath() { ////////// OSystem_SDL_Symbian ////////////////////////////////////////// -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"1x", "Fullscreen", GFX_NORMAL}, - {0, 0, 0} -}; - -bool OSystem_SDL_Symbian::hasFeature(Feature f) { - switch (f) { - case kFeatureFullscreenMode: - case kFeatureAspectRatioCorrection: - case kFeatureCursorHasPalette: -#ifdef USE_VIBRA_SE_PXXX - case kFeatureVibration: -#endif - return true; - - default: - return false; - } -} - -void OSystem_SDL_Symbian::setFeatureState(Feature f, bool enable) { - switch (f) { - case kFeatureVirtualKeyboard: - if (enable) { - } - else { - - } - break; - case kFeatureDisableKeyFiltering: - GUI::Actions::Instance()->beginMapping(enable); - break; - default: - OSystem_SDL::setFeatureState(f, enable); - } +OSystem_SDL_Symbian::OSystem_SDL_Symbian() + : + _RFs(0) { + } -static Common::String getDefaultConfigFileName() { - char configFile[MAXPATHLEN]; - strcpy(configFile, Symbian::GetExecutablePath()); - strcat(configFile, DEFAULT_CONFIG_FILE); - return configFile; -} - -Common::SeekableReadStream *OSystem_SDL_Symbian::createConfigReadStream() { - Common::FSNode file(getDefaultConfigFileName()); - return file.createReadStream(); -} - -Common::WriteStream *OSystem_SDL_Symbian::createConfigWriteStream() { - Common::FSNode file(getDefaultConfigFileName()); - return file.createWriteStream(); -} - -OSystem_SDL_Symbian::zoneDesc OSystem_SDL_Symbian::_zones[TOTAL_ZONES] = { - { 0, 0, 320, 145 }, - { 0, 145, 150, 55 }, - { 150, 145, 170, 55 } -}; -OSystem_SDL_Symbian::OSystem_SDL_Symbian() :_channels(0),_stereo_mix_buffer(0) { +void OSystem_SDL_Symbian::init() { _RFs = &CEikonEnv::Static()->FsSession(); _fsFactory = new SymbianFilesystemFactory(); } @@ -147,20 +84,19 @@ void OSystem_SDL_Symbian::initBackend() { Common::String savePath; savePath = Symbian::GetExecutablePath(); savePath += DEFAULT_SAVE_PATH "\\"; - _savefile = new DefaultSaveFileManager(savePath); + _savefileManager = new DefaultSaveFileManager(savePath); // If savepath has not already been set then set it if (!ConfMan.hasKey("savepath")) { ConfMan.set("savepath", savePath); - } // Ensure that the current set path (might have been altered by the user) exists Common::String currentPath = ConfMan.get("savepath"); TFileName fname; - TPtrC8 ptr((const unsigned char*)currentPath.c_str(),currentPath.size()); + TPtrC8 ptr((const unsigned char*)currentPath.c_str(), currentPath.size()); fname.Copy(ptr); - BaflUtils::EnsurePathExistsL(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), fname); + BaflUtils::EnsurePathExistsL(static_cast<OSystem_SDL_Symbian *>(g_system)->FsSession(), fname); ConfMan.setBool("FM_high_quality", false); #if !defined(S60) || defined(S60V3) // S60 has low quality as default @@ -168,11 +104,26 @@ void OSystem_SDL_Symbian::initBackend() { #else ConfMan.setBool("FM_medium_quality", false); #endif - ConfMan.setInt("joystick_num", 0); // Symbian OS should have joystick_num set to 0 in the ini file , but uiq devices might refuse opening the joystick + // Symbian OS should have joystick_num set to 0 in the ini file, + // but uiq devices might refuse opening the joystick + ConfMan.setInt("joystick_num", 0); ConfMan.flushToDisk(); GUI::Actions::init(); + // Creates the backend managers + if (_eventManager == 0) + _eventManager = new SymbianSdlEventManager(this); + if (_mixerManager == 0) { + _mixerManager = new SymbianSdlMixerManager(); + + // Setup and start mixer + _mixerManager->init(); + } + if (_graphicsManager == 0) + _graphicsManager = new SymbianSdlGraphicsManager(); + + // Call parent implementation of this method OSystem_SDL::initBackend(); // Initialize global key mapping for Smartphones @@ -180,289 +131,25 @@ void OSystem_SDL_Symbian::initBackend() { actions->initInstanceMain(this); actions->loadMapping(); - initZones(); -} - -OSystem_SDL_Symbian::~OSystem_SDL_Symbian() { - delete[] _stereo_mix_buffer; -} - -int OSystem_SDL_Symbian::getDefaultGraphicsMode() const { - return GFX_NORMAL; -} - -const OSystem::GraphicsMode *OSystem_SDL_Symbian::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; -} - -// make sure we always go to normal, even if the string might be set wrong! -bool OSystem_SDL_Symbian::setGraphicsMode(const char * /*name*/) { - // let parent OSystem_SDL handle it - return OSystem_SDL::setGraphicsMode(getDefaultGraphicsMode()); } void OSystem_SDL_Symbian::quitWithErrorMsg(const char * /*aMsg*/) { - CEikonEnv::Static()->AlertWin(_L("quitWithErrorMsg()")) ; if (g_system) g_system->quit(); } -// Overloaded from SDL_Commmon void OSystem_SDL_Symbian::quit() { delete GUI_Actions::Instance(); - OSystem_SDL::quit(); -} -void OSystem_SDL_Symbian::setupMixer() { - - SDL_AudioSpec desired; - SDL_AudioSpec obtained; - - // Determine the desired output sampling frequency. - uint32 samplesPerSec = 0; - if (ConfMan.hasKey("output_rate")) - samplesPerSec = ConfMan.getInt("output_rate"); - if (samplesPerSec <= 0) - samplesPerSec = SAMPLES_PER_SEC; - - // Determine the sample buffer size. We want it to store enough data for - // at least 1/16th of a second (though at most 8192 samples). Note - // that it must be a power of two. So e.g. at 22050 Hz, we request a - // sample buffer size of 2048. - uint32 samples = 8192; - while (samples * 16 > samplesPerSec * 2) - samples >>= 1; - - memset(&desired, 0, sizeof(desired)); - desired.freq = samplesPerSec; - desired.format = AUDIO_S16SYS; - desired.channels = 2; - desired.samples = (uint16)samples; - desired.callback = symbianMixCallback; - desired.userdata = this; - - assert(!_mixer); - if (SDL_OpenAudio(&desired, &obtained) != 0) { - warning("Could not open audio device: %s", SDL_GetError()); - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(false); - } else { - // Note: This should be the obtained output rate, but it seems that at - // least on some platforms SDL will lie and claim it did get the rate - // even if it didn't. Probably only happens for "weird" rates, though. - samplesPerSec = obtained.freq; - _channels = obtained.channels; - - // Need to create mixbuffer for stereo mix to downmix - if (_channels != 2) { - _stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values - } - - // Create the mixer instance and start the sound processing - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(true); - SDL_PauseAudio(0); - } -} - -/** - * The mixer callback function. - */ -void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len) { - OSystem_SDL_Symbian *this_ = (OSystem_SDL_Symbian *)sys; - assert(this_); - - if (!this_->_mixer) - return; - -#if defined (S60) && !defined(S60V3) - // If not stereo then we need to downmix - if (this_->_mixer->_channels != 2) { - this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2); - - int16 *bitmixDst = (int16 *)samples; - int16 *bitmixSrc = (int16 *)_stereo_mix_buffer; - - for (int loop = len / 2; loop >= 0; loop --) { - *bitmixDst = (*bitmixSrc + *(bitmixSrc + 1)) >> 1; - bitmixDst++; - bitmixSrc += 2; - } - } else -#else - this_->_mixer->mixCallback(samples, len); -#endif -} - - -/** - * This is an implementation by the remapKey function - * @param SDL_Event to remap - * @param ScumVM event to modify if special result is requested - * @return true if Common::Event has a valid return status - */ -bool OSystem_SDL_Symbian::remapKey(SDL_Event &ev, Common::Event &event) { - if (GUI::Actions::Instance()->mappingActive() || ev.key.keysym.sym <= SDLK_UNKNOWN) - return false; - - for (TInt loop = 0; loop < GUI::ACTION_LAST; loop++) { - if (GUI::Actions::Instance()->getMapping(loop) == ev.key.keysym.sym && - GUI::Actions::Instance()->isEnabled(loop)) { - // Create proper event instead - switch (loop) { - case GUI::ACTION_UP: - if (ev.type == SDL_KEYDOWN) { - _km.y_vel = -1; - _km.y_down_count = 1; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case GUI::ACTION_DOWN: - if (ev.type == SDL_KEYDOWN) { - _km.y_vel = 1; - _km.y_down_count = 1; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case GUI::ACTION_LEFT: - if (ev.type == SDL_KEYDOWN) { - _km.x_vel = -1; - _km.x_down_count = 1; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case GUI::ACTION_RIGHT: - if (ev.type == SDL_KEYDOWN) { - _km.x_vel = 1; - _km.x_down_count = 1; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case GUI::ACTION_LEFTCLICK: - event.type = (ev.type == SDL_KEYDOWN ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP); - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case GUI::ACTION_RIGHTCLICK: - event.type = (ev.type == SDL_KEYDOWN ? Common::EVENT_RBUTTONDOWN : Common::EVENT_RBUTTONUP); - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case GUI::ACTION_ZONE: - if (ev.type == SDL_KEYDOWN) { - int i; - - for (i=0; i < TOTAL_ZONES; i++) - if (_km.x >= _zones[i].x && _km.y >= _zones[i].y && - _km.x <= _zones[i].x + _zones[i].width && _km.y <= _zones[i].y + _zones[i].height - ) { - _mouseXZone[i] = _km.x; - _mouseYZone[i] = _km.y; - break; - } - _currentZone++; - if (_currentZone >= TOTAL_ZONES) - _currentZone = 0; - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _mouseXZone[_currentZone], _mouseYZone[_currentZone]); - SDL_WarpMouse(event.mouse.x, event.mouse.y); - } - - return true; - case GUI::ACTION_MULTI: { - GUI::Key &key = GUI::Actions::Instance()->getKeyAction(loop); - // if key code is pause, then change event to interactive or just fall through - if (key.keycode() == SDLK_PAUSE) { - event.type = Common::EVENT_PREDICTIVE_DIALOG; - return true; - } - } - case GUI::ACTION_SAVE: - case GUI::ACTION_SKIP: - case GUI::ACTION_SKIP_TEXT: - case GUI::ACTION_PAUSE: - case GUI::ACTION_SWAPCHAR: - case GUI::ACTION_FASTMODE: - case GUI::ACTION_DEBUGGER: - case GUI::ACTION_MAINMENU: - case GUI::ACTION_VKB: - case GUI::ACTION_KEYMAPPER:{ - GUI::Key &key = GUI::Actions::Instance()->getKeyAction(loop); - ev.key.keysym.sym = (SDLKey) key.keycode(); - ev.key.keysym.scancode = 0; - ev.key.keysym.mod = (SDLMod) key.flags(); - - // Translate from SDL keymod event to Scummvm Key Mod Common::Event. - // This codes is also present in GP32 backend and in SDL backend as a static function - // Perhaps it should be shared. - if (key.flags() != 0) { - event.kbd.flags = 0; - - if (ev.key.keysym.mod & KMOD_SHIFT) - event.kbd.flags |= Common::KBD_SHIFT; - - if (ev.key.keysym.mod & KMOD_ALT) - event.kbd.flags |= Common::KBD_ALT; - - if (ev.key.keysym.mod & KMOD_CTRL) - event.kbd.flags |= Common::KBD_CTRL; - } - - return false; - } - - case GUI::ACTION_QUIT: - { - GUI::MessageDialog alert(_("Do you want to quit ?"), _("Yes"), _("No")); - if (alert.runModal() == GUI::kMessageOK) - quit(); - - return true; - } - } - } - } - - return false; -} - -void OSystem_SDL_Symbian::setWindowCaption(const char *caption) { - OSystem_SDL::setWindowCaption(caption); + // Call parent implementation of this method + OSystem_SDL::quit(); } void OSystem_SDL_Symbian::engineInit() { // Check mappings for the engine just started - check_mappings(); + checkMappings(); } void OSystem_SDL_Symbian::engineDone() { @@ -470,22 +157,26 @@ void OSystem_SDL_Symbian::engineDone() { GUI::Actions::Instance()->initInstanceMain(this); } -void OSystem_SDL_Symbian::check_mappings() { +void OSystem_SDL_Symbian::checkMappings() { if (ConfMan.get("gameid").empty() || GUI::Actions::Instance()->initialized()) return; GUI::Actions::Instance()->initInstanceGame(); } -void OSystem_SDL_Symbian::initZones() { - int i; +bool OSystem_SDL_Symbian::setGraphicsMode(const char * /*name*/) { + return _graphicsManager->setGraphicsMode(0); +} - _currentZone = 0; +Common::String OSystem_SDL_Symbian::getDefaultConfigFileName() { + char configFile[MAXPATHLEN]; + strcpy(configFile, Symbian::GetExecutablePath()); + strcat(configFile, DEFAULT_CONFIG_FILE); + return configFile; +} - for (i = 0; i < TOTAL_ZONES; i++) { - _mouseXZone[i] = (_zones[i].x + (_zones[i].width / 2)); - _mouseYZone[i] = (_zones[i].y + (_zones[i].height / 2)); - } +void OSystem_SDL_Symbian::setupIcon() { + // Don't for Symbian: it uses the EScummVM.aif file for the icon. } RFs& OSystem_SDL_Symbian::FsSession() { @@ -511,67 +202,3 @@ void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size return NULL; } - -extern "C" -{ -// Include the snprintf and vsnprintf implementations as 'C' code -#include "vsnprintf.h" -} - -// Symbian SDL_Main implementation -// Redirects standard io, creates Symbian specific SDL backend (inherited from main SDL) -int main(int argc, char *argv[]) { - // - // Set up redirects for stdout/stderr under Symbian. - // Code copied from SDL_main. - // - - // Symbian does not like any output to the console through any *print* function - char STDOUT_FILE[256], STDERR_FILE[256]; // shhh, don't tell anybody :) - strcpy(STDOUT_FILE, Symbian::GetExecutablePath()); - strcpy(STDERR_FILE, Symbian::GetExecutablePath()); - strcat(STDOUT_FILE, "scummvm.stdout.txt"); - strcat(STDERR_FILE, "scummvm.stderr.txt"); - - /* Flush the output in case anything is queued */ - fclose(stdout); - fclose(stderr); - - /* Redirect standard input and standard output */ - FILE *newfp = freopen(STDOUT_FILE, "w", stdout); - if (newfp == NULL) { /* This happens on NT */ -#if !defined(stdout) - stdout = fopen(STDOUT_FILE, "w"); -#else - newfp = fopen(STDOUT_FILE, "w"); - if (newfp) { - *stdout = *newfp; - } -#endif - } - newfp = freopen(STDERR_FILE, "w", stderr); - if (newfp == NULL) { /* This happens on NT */ -#if !defined(stderr) - stderr = fopen(STDERR_FILE, "w"); -#else - newfp = fopen(STDERR_FILE, "w"); - if (newfp) { - *stderr = *newfp; - } -#endif - } - setbuf(stderr, NULL); /* No buffering */ - - // Create our OSystem instance - g_system = new OSystem_SDL_Symbian(); - assert(g_system); - -#ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new SDLPluginProvider()); -#endif - - // Invoke the actual ScummVM main entry point: - int res = scummvm_main(argc, argv); - g_system->quit(); // TODO: Consider removing / replacing this! - return res; -} diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h index 42929f8029..e5f4ea44d0 100644 --- a/backends/platform/symbian/src/SymbianOS.h +++ b/backends/platform/symbian/src/SymbianOS.h @@ -22,71 +22,50 @@ * $Id$ */ -#ifndef SDLSYMBIANH -#define SDLSYMBIANH +#ifndef PLATFORM_SDL_SYMBIAN_H +#define PLATFORM_SDL_SYMBIAN_H #include "backends/platform/sdl/sdl.h" -#define TOTAL_ZONES 3 class RFs; class OSystem_SDL_Symbian : public OSystem_SDL { public: OSystem_SDL_Symbian(); - virtual ~OSystem_SDL_Symbian(); -public: - /** - * The following method is called once, from main.cpp, after all - * config data (including command line params etc.) are fully loaded. - */ + // Override from OSystem_SDL + virtual void init(); virtual void initBackend(); + virtual void quit(); + virtual void engineInit(); + virtual void engineDone(); + virtual bool setGraphicsMode(const char *name); + virtual Common::String getDefaultConfigFileName(); + virtual void setupIcon(); - int getDefaultGraphicsMode() const; - const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(const char *name); - void quitWithErrorMsg(const char *msg); - virtual bool hasFeature(Feature f); - void setFeatureState(Feature f, bool enable); - - // Set function that generates samples - // - // This function is overridden by the symbian port in order to provide MONO audio - // downmix is done by supplying our own audiocallback - // - virtual void setupMixer(); // overloaded by CE backend - - // Overloaded from SDL_Commmon - void quit(); - - // Returns reference to File session + /** + * Returns reference to File session + */ RFs& FsSession(); -protected: - // - // The mixer callback function. - // - static void symbianMixCallback(void *s, byte *samples, int len); + void quitWithErrorMsg(const char *msg); - virtual Common::SeekableReadStream *createConfigReadStream(); - virtual Common::WriteStream *createConfigWriteStream(); -public: - // vibration support + // Vibration support #ifdef USE_VIBRA_SE_PXXX - // - // Intialize the vibration api used if present and supported - // + /** + * Intialize the vibration api used if present and supported + */ void initializeVibration(); - // - // Turn vibration on, repeat no time - // @param vibraLength number of repetitions - // + /** + * Turn vibration on, repeat no time + * @param vibraLength number of repetitions + */ void vibrationOn(int vibraLength); - // - // Turns the vibration off - // + /** + * Turns the vibration off + */ void vibrationOff(); protected: @@ -94,54 +73,11 @@ protected: #endif // USE_VIBRA_SE_PXXX protected: - - // - // This is an implementation by the remapKey function - // @param SDL_Event to remap - // @param ScumVM event to modify if special result is requested - // @return true if Common::Event has a valid return status - // - bool remapKey(SDL_Event &ev, Common::Event &event); - - void setWindowCaption(const char *caption); - /** - * Allows the backend to perform engine specific init. - * Called just before the engine is run. + * Used to intialized special game mappings */ - virtual void engineInit(); - - /** - * Allows the backend to perform engine specific de-init. - * Called after the engine finishes. - */ - virtual void engineDone(); - - // - // Used to intialized special game mappings - // - void check_mappings(); - - void initZones(); - - // Audio - int _channels; - - byte *_stereo_mix_buffer; - - // Used to handle joystick navi zones - int _mouseXZone[TOTAL_ZONES]; - int _mouseYZone[TOTAL_ZONES]; - int _currentZone; - - struct zoneDesc { - int x; - int y; - int width; - int height; - }; + void checkMappings(); - static zoneDesc _zones[TOTAL_ZONES]; RFs* _RFs; }; diff --git a/backends/platform/symbian/src/main.cpp b/backends/platform/symbian/src/main.cpp new file mode 100644 index 0000000000..4aaa05926f --- /dev/null +++ b/backends/platform/symbian/src/main.cpp @@ -0,0 +1,99 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "base/main.h" +#include "backends/platform/symbian/src/SymbianOS.h" +#include "backends/platform/symbian/src/portdefs.h" + +extern "C" +{ +// Include the snprintf and vsnprintf implementations as 'C' code +#include "vsnprintf.h" +} + +// Symbian SDL_Main implementation +// Redirects standard io, creates Symbian specific SDL backend (inherited from main SDL) +int main(int argc, char *argv[]) { + // + // Set up redirects for stdout/stderr under Symbian. + // Code copied from SDL_main. + // + + // Symbian does not like any output to the console through any *print* function + char STDOUT_FILE[256], STDERR_FILE[256]; // shhh, don't tell anybody :) + strcpy(STDOUT_FILE, Symbian::GetExecutablePath()); + strcpy(STDERR_FILE, Symbian::GetExecutablePath()); + strcat(STDOUT_FILE, "scummvm.stdout.txt"); + strcat(STDERR_FILE, "scummvm.stderr.txt"); + + /* Flush the output in case anything is queued */ + fclose(stdout); + fclose(stderr); + + /* Redirect standard input and standard output */ + FILE *newfp = freopen(STDOUT_FILE, "w", stdout); + if (newfp == NULL) { /* This happens on NT */ +#if !defined(stdout) + stdout = fopen(STDOUT_FILE, "w"); +#else + newfp = fopen(STDOUT_FILE, "w"); + if (newfp) { + *stdout = *newfp; + } +#endif + } + newfp = freopen(STDERR_FILE, "w", stderr); + if (newfp == NULL) { /* This happens on NT */ +#if !defined(stderr) + stderr = fopen(STDERR_FILE, "w"); +#else + newfp = fopen(STDERR_FILE, "w"); + if (newfp) { + *stderr = *newfp; + } +#endif + } + setbuf(stderr, NULL); /* No buffering */ + + // Create our OSystem instance + g_system = new OSystem_SDL_Symbian(); + assert(g_system); + + // Pre initialize the backend + ((OSystem_SDL_Symbian *)g_system)->init(); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + + // Free OSystem + delete (OSystem_SDL_Symbian *)g_system; + + return res; +} + diff --git a/backends/timer/default/default-timer.h b/backends/timer/default/default-timer.h index e7ac3d122f..778c69b32d 100644 --- a/backends/timer/default/default-timer.h +++ b/backends/timer/default/default-timer.h @@ -40,7 +40,8 @@ private: public: DefaultTimerManager(); - ~DefaultTimerManager(); + virtual ~DefaultTimerManager(); + bool installTimerProc(TimerProc proc, int32 interval, void *refCon); void removeTimerProc(TimerProc proc); diff --git a/backends/timer/sdl/sdl-timer.cpp b/backends/timer/sdl/sdl-timer.cpp new file mode 100644 index 0000000000..94932d61ba --- /dev/null +++ b/backends/timer/sdl/sdl-timer.cpp @@ -0,0 +1,51 @@ + +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(WIN32) || defined(UNIX) || defined(MACOSX) + +#include "backends/timer/sdl/sdl-timer.h" + +static Uint32 timer_handler(Uint32 interval, void *param) { + ((DefaultTimerManager *)param)->handler(); + return interval; +} + +SdlTimerManager::SdlTimerManager() { + // Initializes the SDL timer subsystem + if (SDL_InitSubSystem(SDL_INIT_TIMER) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + // Creates the timer callback + _timerID = SDL_AddTimer(10, &timer_handler, this); +} + +SdlTimerManager::~SdlTimerManager() { + // Removes the timer callback + SDL_RemoveTimer(_timerID); +} + +#endif diff --git a/backends/timer/sdl/sdl-timer.h b/backends/timer/sdl/sdl-timer.h new file mode 100644 index 0000000000..5995aed4b0 --- /dev/null +++ b/backends/timer/sdl/sdl-timer.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_TIMER_SDL_H +#define BACKENDS_TIMER_SDL_H + +#include "backends/timer/default/default-timer.h" + +#if defined(__SYMBIAN32__) +#include <esdl\SDL.h> +#else +#include <SDL.h> +#endif + +/** + * SDL timer manager. Setups the timer callback for + * DefaultTimerManager. + */ +class SdlTimerManager : public DefaultTimerManager { +public: + SdlTimerManager(); + virtual ~SdlTimerManager(); + +protected: + SDL_TimerID _timerID; +}; + + +#endif |