scummvm/backends/platform/sdl/sdl.cpp
Travis Howell 1b47344cc1 Merged revisions 43066,43068,43088,43093,43095,43097,43101-43102,43107,43112,43114,43117,43119-43120,43122-43123,43126,43131,43139,43143,43145,43147,43150,43152,43155-43156,43163,43165,43167,43171-43172,43178-43179,43183,43186-43200,43202,43205-43223,43227-43235,43237-43241 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk

........
  r43066 | dreammaster | 2009-08-05 20:44:37 +1000 (Wed, 05 Aug 2009) | 1 line
  
  Bugfix for music not being stopped when music volume is set to zero
........
  r43068 | scott_t | 2009-08-05 23:57:40 +1000 (Wed, 05 Aug 2009) | 1 line
  
  T7G: Fix bug #2831041 by implementing opcode responsible for starting music partway through a video
........
  r43088 | knakos | 2009-08-07 04:05:50 +1000 (Fri, 07 Aug 2009) | 1 line
  
  overload showMouse to kill mouse shadows in kyra
........
  r43093 | dreammaster | 2009-08-07 19:25:06 +1000 (Fri, 07 Aug 2009) | 1 line
  
  Bugfix for #2831159 - Palace guards saying !!HIGH STRING!!
........
  r43095 | knakos | 2009-08-07 20:44:34 +1000 (Fri, 07 Aug 2009) | 1 line
  
  hint backend about virtual keyboard on save, in LoK
........
  r43097 | knakos | 2009-08-07 21:05:58 +1000 (Fri, 07 Aug 2009) | 1 line
  
  show VK in gui_v2 games of kyra
........
  r43101 | dhewg | 2009-08-08 04:16:58 +1000 (Sat, 08 Aug 2009) | 3 lines
  
  Merge creation of Info.plist into update-version.pl.
  This fixes the static version info after branching (#2820503).
........
  r43102 | knakos | 2009-08-08 05:33:39 +1000 (Sat, 08 Aug 2009) | 1 line
  
  mouse up events need the same lovin' as mouse down events do. don't underestimate 'em. fixes bug #2833549
........
  r43107 | drmccoy | 2009-08-08 12:23:04 +1000 (Sat, 08 Aug 2009) | 1 line
  
  When opening a data stream, don't read the whole file into memory if not necessary. This vastly improves the loading times of Gob3 on small devices
........
  r43112 | dreammaster | 2009-08-08 19:34:23 +1000 (Sat, 08 Aug 2009) | 1 line
  
  Commit of dhewg's patch to fix screen refreshes on the Wii
........
  r43114 | knakos | 2009-08-08 19:38:12 +1000 (Sat, 08 Aug 2009) | 1 line
  
  forward port of wince 3.0 fix for paths from branch 0.13.0, r39978
........
  r43117 | dhewg | 2009-08-08 21:30:56 +1000 (Sat, 08 Aug 2009) | 1 line
  
  tweaked the mapped keys to reintroduce SHIFT for mass adding games
........
  r43119 | lordhoto | 2009-08-08 21:42:29 +1000 (Sat, 08 Aug 2009) | 1 line
  
  Add workaround for bug #2820054 "DW1: No intro music at first start on Wii", which actually happened on all systems, when using the multilanguage version.
........
  r43120 | lordhoto | 2009-08-08 21:51:15 +1000 (Sat, 08 Aug 2009) | 1 line
  
  Fix for bug #2412336 "DW2: Voices cut off" (commit on behalf of dreammaster)
........
  r43122 | lordhoto | 2009-08-08 22:00:34 +1000 (Sat, 08 Aug 2009) | 1 line
  
  Formatting fix.
........
  r43123 | lordhoto | 2009-08-08 22:22:34 +1000 (Sat, 08 Aug 2009) | 1 line
  
  Change workaround for bug #2820054 to apply for all GRA versions.
........
  r43126 | lordhoto | 2009-08-08 23:57:21 +1000 (Sat, 08 Aug 2009) | 1 line
  
  Fix XMIDI looping implementation. Now for example the music in the ferret village of ITE plays fine.
........
  r43131 | sev | 2009-08-09 04:01:44 +1000 (Sun, 09 Aug 2009) | 2 lines
  
  Implement FR#2821534: "GUI: Mute All disable volume sliders"
........
  r43139 | sev | 2009-08-09 06:08:22 +1000 (Sun, 09 Aug 2009) | 2 lines
  
  Add DS version of Atari MM from Bug #2834054
........
  r43143 | sev | 2009-08-09 06:16:58 +1000 (Sun, 09 Aug 2009) | 2 lines
  
  Patch #2832247: "GMM: Enable loading & deleting of unnamed savegames"
........
  r43145 | sev | 2009-08-09 06:49:13 +1000 (Sun, 09 Aug 2009) | 2 lines
  
  Fix bug #2825565: "Unable to select subtitles in Atlantis and Simon 1"
........
  r43147 | drmccoy | 2009-08-09 07:43:07 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Changed the scroll-handling to be more like the original. This fixes bug #2832362 ("GOB3: Scrolling locked after cutscene")
........
  r43150 | dreammaster | 2009-08-09 11:05:47 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Changed subtitles display speed to also include the time taken to say voice samples (if voices are turned on). This means subtitles will display for the same time irrespective of whether voices are on or not
........
  r43152 | Kirben | 2009-08-09 11:20:08 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Fix bug #2834254 - ELVIRA: Buggy scroll arrows when mixing spells.
........
  r43155 | dreammaster | 2009-08-09 11:45:39 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Slight adjustment to Spanish font lookup table, based on mac_es's description of character lookup problems
........
  r43156 | Kirben | 2009-08-09 11:55:34 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Fix bug #2834252 - ELVIRA1 Problem with 8-character-long save names.
........
  r43163 | Kirben | 2009-08-09 17:16:08 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Fix bug #2834260 - ELVIRA1: Graphic glitch when bird takes off.
........
  r43165 | Kirben | 2009-08-09 20:28:11 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Fix glitch when removing arrows from spell book in Elvira 1.
........
  r43167 | djwillis | 2009-08-09 22:12:24 +1000 (Sun, 09 Aug 2009) | 1 line
  
  GP2X: Commit local version of backend, contains a 'fix' to work around a GP2X SDL 'feature' that was removing the ability to disable aspect ratio correction. Also misc cleanup and changes to default volume levels to cut down on sample clipping.
........
  r43171 | dreammaster | 2009-08-09 22:23:01 +1000 (Sun, 09 Aug 2009) | 1 line
  
  Removed redundant code related to Midi handling
........
  r43172 | lordhoto | 2009-08-10 01:37:00 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Fix for bug #2834250 "GUI: Incorrect behavior of sliders".
........
  r43178 | knakos | 2009-08-10 04:34:08 +1000 (Mon, 10 Aug 2009) | 1 line
  
  removing support for flac (good riddance) and mpeg2
........
  r43179 | knakos | 2009-08-10 04:37:29 +1000 (Mon, 10 Aug 2009) | 1 line
  
  update news files for 1.0.0rc1 release
........
  r43183 | lordhoto | 2009-08-10 05:11:10 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Cleanup AMIGA graphics conversion.
........
  r43186 | lordhoto | 2009-08-10 08:46:25 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Create a "Font" interface and create a "DOSFont" implementation for handling DOS version fonts.
........
  r43187 | lordhoto | 2009-08-10 08:46:43 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Add support for the font format used in Kyrandia 1 Amiga. (font colors are wrong though)
........
  r43188 | lordhoto | 2009-08-10 09:23:48 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Unbreak basic Kyra1 amiga in game support, by disabling some palette code for the amiga version.
........
  r43189 | lordhoto | 2009-08-10 09:32:52 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Clear the destination page for bitmap loading, this fixes graphics artifacts in Kyra1 amiga.
........
  r43190 | waltervn | 2009-08-10 11:08:20 +1000 (Mon, 10 Aug 2009) | 3 lines
  
  SCI: Added detection entries for French versions of Eco Quest 1/2 (reported
  by Strangerke).
........
  r43191 | lordhoto | 2009-08-10 11:32:22 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Disable menu text fading in kyra1 amiga for now.
........
  r43192 | lordhoto | 2009-08-10 11:32:39 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Initial support for correct colors in the interface of Kyra1 AMIGA.
........
  r43193 | lordhoto | 2009-08-10 11:32:59 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Fix inventory background color.
........
  r43194 | lordhoto | 2009-08-10 11:33:18 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Fix text color in character speeches in Kyra1 amiga.
........
  r43195 | lordhoto | 2009-08-10 11:33:36 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Fix interface text color.
........
  r43196 | lordhoto | 2009-08-10 11:33:56 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Enable interface text fading in Kyra1 amiga again.
........
  r43197 | lordhoto | 2009-08-10 11:34:14 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Use interface palette for mouse cursor in Kyra1 amiga, when it's enabled.
........
  r43198 | lordhoto | 2009-08-10 11:34:29 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Cleanup.
........
  r43199 | lordhoto | 2009-08-10 11:34:46 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Remove dead code.
........
  r43200 | lordhoto | 2009-08-10 12:32:19 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Fix bug when setting up mouse cursor with inventory palette.
........
  r43202 | athrxx | 2009-08-10 20:25:53 +1000 (Mon, 10 Aug 2009) | 1 line
  
  LOL: fix main menu in floppy version
........
  r43205 | lordhoto | 2009-08-10 23:46:17 +1000 (Mon, 10 Aug 2009) | 1 line
  
  Made font color configuration independend from font style configuration.
........
  r43206 | lordhoto | 2009-08-11 00:05:14 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Rename 'font_color' attribute for 'text' draw step to 'text_color'.
........
  r43207 | lordhoto | 2009-08-11 00:35:28 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix copyright string displaying in Kyra1 amiga. Unlike the DOS version it does not use a second print for creating a shadow look.
........
  r43208 | lordhoto | 2009-08-11 02:42:39 +1000 (Tue, 11 Aug 2009) | 4 lines
  
  - Fix extraction of Kyra 1 amiga string tables in kyra.dat
  - Fix "taken" string offsets in kyra.dat
  - Add temporary workaround for only one "taken" string being present in Kyra 1 amiga.
  - Update kyra.dat
........
  r43209 | lordhoto | 2009-08-11 03:14:03 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix GUI strings in Kyrandia 1 Amiga.
........
  r43210 | lordhoto | 2009-08-11 03:14:22 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Implement item to item name list index mapping for Kyrandia 1 Amiga.
........
  r43211 | lordhoto | 2009-08-11 03:17:19 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Typo.
........
  r43212 | lordhoto | 2009-08-11 04:01:28 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix GUI font colors and text drawing in Kyrandia 1 Amiga.
........
  r43213 | lordhoto | 2009-08-11 04:03:37 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix GUI button outline colors in Kyra1 Amiga.
........
  r43214 | tramboi | 2009-08-11 04:03:54 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  Option "desired_screen_aspect_ratio" for fullscreen mode in the SDL backend
  Shortcoming: the picture is not centered
........
  r43215 | lordhoto | 2009-08-11 04:04:53 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix GUI menu colors for Kyrandia 1 Amiga.
........
  r43216 | lordhoto | 2009-08-11 04:13:01 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Remove unused variables.
........
  r43217 | waltervn | 2009-08-11 04:37:47 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  SCI: Improved multilanguage support for SCI1 and SCI1.1.
........
  r43218 | waltervn | 2009-08-11 04:43:15 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  SCI: Fix warnings.
........
  r43219 | waltervn | 2009-08-11 04:59:59 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  SCI: Fix vmvars debug command.
........
  r43220 | lordhoto | 2009-08-11 05:08:00 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  - Fix AMIGA to DOS palette conversion
  - Amiga version uses 13 instead of 12 palette buffers
........
  r43221 | lordhoto | 2009-08-11 05:09:13 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix incorrect converted colors in Kyra1 Amiga speech text color setup.
........
  r43222 | lordhoto | 2009-08-11 05:10:11 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Implement differences for Kyrandia 1 Amiga in o1_setCustomPaletteRange.
........
  r43223 | sev | 2009-08-11 05:31:08 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  Add support for Italian MM NES
........
  r43227 | strangerke | 2009-08-11 06:57:26 +1000 (Tue, 11 Aug 2009) | 1 line
  
  gob - Add a workaround for files (at least in Playtoons) that are tested on CD only, with the '@' symbol
........
  r43228 | strangerke | 2009-08-11 06:58:13 +1000 (Tue, 11 Aug 2009) | 1 line
  
  gob - Add 2 files tested and used by Playtoons and Playtoons CK
........
  r43229 | waltervn | 2009-08-11 07:30:16 +1000 (Tue, 11 Aug 2009) | 2 lines
  
  SCI: Added several debug command aliases.
........
  r43230 | lordhoto | 2009-08-11 08:18:18 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Cleanup.
........
  r43231 | lordhoto | 2009-08-11 08:18:33 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix o1_makeAmuletAppear for Kyrandia 1 Amiga.
........
  r43232 | lordhoto | 2009-08-11 08:18:47 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix WSA movies for final sequence of Kyrandia 1 Amiga. (this is just a theoretical fix, the game isn't yet playable till then)
........
  r43233 | lordhoto | 2009-08-11 08:54:25 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Proper implementation of o1_fadeSpecialPalette for Kyrandia 1 Amiga.
........
  r43234 | lordhoto | 2009-08-11 08:54:45 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix cauldron water color in Zanthia's home in Kyrandia 1 Amiga.
........
  r43235 | mthreepwood | 2009-08-11 09:01:11 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Provide a better detection method for Indy3 Mac sound effects. This fixes sounds such as the music that plays when Indy uses the whip on the hook in the giant cork. This also is a proper fix for bug #1852635 -- Sound 54 is actually not a sound effect.
........
  r43237 | lordhoto | 2009-08-11 09:34:35 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Implement different in Kyrandia 1 Amiga in o1_setFireberryGlowPalette.
........
  r43238 | lordhoto | 2009-08-11 09:35:16 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix yet another inventory background color glitch in Kyrandia 1 Amiga.
........
  r43239 | lordhoto | 2009-08-11 10:14:24 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix a little graphics bug in Kyrandia 1 Amiga, when jewels are enabled.
........
  r43240 | lordhoto | 2009-08-11 10:14:40 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Disable Kyragem fading for Kyrandia 1 Amiga.
........
  r43241 | lordhoto | 2009-08-11 10:14:54 +1000 (Tue, 11 Aug 2009) | 1 line
  
  Fix regression introduced with r41081.
........

svn-id: r43250
2009-08-11 02:04:17 +00:00

860 lines
22 KiB
C++

/* 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)
#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"
#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
#if defined(UNIX)
#ifdef MACOSX
#define DEFAULT_CONFIG_FILE "Library/Preferences/ScummVM Preferences"
#else
#define DEFAULT_CONFIG_FILE ".scummvmrc"
#endif
#else
#define DEFAULT_CONFIG_FILE "scummvm.ini"
#endif
#if defined(MACOSX) || defined(IPHONE)
#include "CoreFoundation/CoreFoundation.h"
#endif
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;
}
static const size_t AR_COUNT = 4;
static const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" };
static const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) };
static AspectRatio getDesiredAspectRatio() {
//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);
}
void OSystem_SDL::initBackend() {
assert(!_inited);
int joystick_num = ConfMan.getInt("joystick_num");
uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
if (ConfMan.hasKey("disable_sdl_parachute"))
sdlFlags |= SDL_INIT_NOPARACHUTE;
#ifdef _WIN32_WCE
if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) {
SDL_VideoInit("windib", 0);
sdlFlags ^= SDL_INIT_VIDEO;
}
#endif
if (joystick_num > -1)
sdlFlags |= SDL_INIT_JOYSTICK;
if (SDL_Init(sdlFlags) == -1) {
error("Could not initialize SDL: %s", SDL_GetError());
}
_graphicsMutex = createMutex();
SDL_ShowCursor(SDL_DISABLE);
// Enable unicode support if possible
SDL_EnableUNICODE(1);
memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
memset(&_videoMode, 0, sizeof(_videoMode));
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
_cksumValid = false;
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && !defined(DISABLE_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;
_modeFlags = 0;
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
_videoMode.fullscreen = ConfMan.getBool("fullscreen");
#else
_videoMode.fullscreen = true;
#endif
#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 ENABLE_RGB_COLOR
_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
#endif
_overlayVisible(false),
_overlayscreen(0), _tmpscreen2(0),
_samplesPerSec(0),
_cdrom(0), _scalerProc(0), _modeChanged(false), _screenChangeCount(0), _dirtyChecksums(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;
#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();
free(_dirtyChecksums);
free(_currentPalette);
free(_cursorPalette);
free(_mouseData);
delete _savefile;
delete _timer;
}
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(struct tm &t) const {
time_t curTime = time(0);
t = *localtime(&curTime);
}
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;
}
void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
#ifdef DATA_PATH
// Add the global DATA_PATH to the directory search list
// FIXME: We use depth = 4 for now, to match the old code. May want to change that
Common::FSNode dataNode(DATA_PATH);
if (dataNode.exists() && dataNode.isDirectory()) {
s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), 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::SeekableReadStream *OSystem_SDL::createConfigReadStream() {
Common::FSNode file(getDefaultConfigFileName());
return file.createReadStream();
}
Common::WriteStream *OSystem_SDL::createConfigWriteStream() {
Common::FSNode file(getDefaultConfigFileName());
return file.createWriteStream();
}
void OSystem_SDL::setWindowCaption(const char *caption) {
Common::String cap;
byte c;
// The string caption is supposed to be in LATIN-1 encoding.
// SDL expects UTF-8. So we perform the conversion here.
while ((c = *(const byte *)caption++)) {
if (c < 0x80)
cap += c;
else {
cap += 0xC0 | (c >> 6);
cap += 0x80 | (c & 0x3F);
}
}
SDL_WM_SetCaption(cap.c_str(), cap.c_str());
}
bool OSystem_SDL::hasFeature(Feature f) {
return
(f == kFeatureFullscreenMode) ||
(f == kFeatureAspectRatioCorrection) ||
(f == kFeatureAutoComputeDirtyRects) ||
(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 kFeatureAutoComputeDirtyRects:
if (enable)
_modeFlags |= DF_WANT_RECT_OPTIM;
else
_modeFlags &= ~DF_WANT_RECT_OPTIM;
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;
case kFeatureAutoComputeDirtyRects:
return _modeFlags & DF_WANT_RECT_OPTIM;
default:
return false;
}
}
void OSystem_SDL::quit() {
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(_dirtyChecksums);
free(_currentPalette);
free(_cursorPalette);
free(_mouseData);
delete _timer;
SDL_Quit();
// Even Manager requires save manager for storing
// recorded events
delete getEventManager();
delete _savefile;
exit(0);
}
void OSystem_SDL::setupIcon() {
int x, y, w, h, ncols, nbytes, i;
unsigned int rgba[256];
unsigned int *icon;
sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes);
if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) {
warning("Could not load the built-in icon (%d %d %d %d)", w, h, ncols, nbytes);
return;
}
icon = (unsigned int*)malloc(w*h*sizeof(unsigned int));
if (!icon) {
warning("Could not allocate temp storage for the built-in icon");
return;
}
for (i = 0; i < ncols; i++) {
unsigned char code;
char color[32];
unsigned int col;
sscanf(scummvm_icon[1 + i], "%c c %s", &code, color);
if (!strcmp(color, "None"))
col = 0x00000000;
else if (!strcmp(color, "black"))
col = 0xFF000000;
else if (color[0] == '#') {
sscanf(color + 1, "%06x", &col);
col |= 0xFF000000;
} else {
warning("Could not load the built-in icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
free(icon);
return;
}
rgba[code] = col;
}
for (y = 0; y < h; y++) {
const char *line = scummvm_icon[1 + ncols + y];
for (x = 0; x < w; x++) {
icon[x + w * y] = rgba[(int)line[x]];
}
}
SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, w, h, 32, w * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
if (!sdl_surf) {
warning("SDL_CreateRGBSurfaceFrom(icon) failed");
}
SDL_WM_SetIcon(sdl_surf, NULL);
SDL_FreeSurface(sdl_surf);
free(icon);
}
OSystem::MutexRef OSystem_SDL::createMutex(void) {
return (MutexRef) SDL_CreateMutex();
}
void OSystem_SDL::lockMutex(MutexRef mutex) {
SDL_mutexP((SDL_mutex *) mutex);
}
void OSystem_SDL::unlockMutex(MutexRef mutex) {
SDL_mutexV((SDL_mutex *) mutex);
}
void OSystem_SDL::deleteMutex(MutexRef mutex) {
SDL_DestroyMutex((SDL_mutex *) mutex);
}
#pragma mark -
#pragma mark --- Audio ---
#pragma mark -
#ifdef 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);
}
int SDLCALL OSystem_SDL::mixerProducerThreadEntry(void *arg) {
OSystem_SDL *this_ = (OSystem_SDL *)arg;
assert(this_);
this_->mixerProducerThread();
return 0;
}
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);
}
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]);
}
}
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);
}
#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);
}
#endif
void OSystem_SDL::setupMixer() {
SDL_AudioSpec desired;
SDL_AudioSpec obtained;
// Determine the desired output sampling frequency.
_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
// about 1/16th of a second. Note that it must be a power of two.
// So e.g. at 22050 Hz, we request a sample buffer size of 2048.
int samples = 8192;
while (16 * samples >= _samplesPerSec) {
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;
// Create the mixer instance
assert(!_mixer);
_mixer = new Audio::MixerImpl(this);
assert(_mixer);
if (SDL_OpenAudio(&desired, &obtained) != 0) {
warning("Could not open audio device: %s", SDL_GetError());
_samplesPerSec = 0;
_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);
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
_mixer->setReady(true);
#ifdef MIXER_DOUBLE_BUFFERING
initThreadedMixer(_mixer, obtained.samples * 4);
#endif
// start the sound system
SDL_PauseAudio(0);
}
}
void OSystem_SDL::closeMixer() {
if (_mixer)
_mixer->setReady(false);
SDL_CloseAudio();
delete _mixer;
_mixer = 0;
#ifdef 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;
}
}
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;
}
bool OSystem_SDL::pollCD() {
if (!_cdrom)
return false;
return (_cdNumLoops != 0 && (SDL_GetTicks() < _cdEndTime || SDL_CDStatus(_cdrom) == CD_PLAYING));
}
void OSystem_SDL::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;
}
}