diff options
Diffstat (limited to 'backends')
22 files changed, 344 insertions, 128 deletions
diff --git a/backends/events/dinguxsdl/dinguxsdl-events.cpp b/backends/events/dinguxsdl/dinguxsdl-events.cpp index cc15f2666c..0492c569e1 100644 --- a/backends/events/dinguxsdl/dinguxsdl-events.cpp +++ b/backends/events/dinguxsdl/dinguxsdl-events.cpp @@ -175,7 +175,10 @@ bool DINGUXSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {  		return true;  	} else if (ev.key.keysym.sym == BUT_SELECT) { // virtual keyboard  #ifdef ENABLE_VKEYBD -		event.type = Common::EVENT_VIRTUAL_KEYBOARD; +		if (ev.type == SDL_KEYDOWN) +			event.type = Common::EVENT_VIRTUAL_KEYBOARD; + +		return true;  #endif  	} else if (ev.key.keysym.sym == BUT_START) { // F5, menu in some games  		ev.key.keysym.sym = SDLK_F5; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 2b9d3aa100..21345515bc 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -127,7 +127,8 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou  #if SDL_VERSION_ATLEAST(2, 0, 0)  	_renderer(nullptr), _screenTexture(nullptr),  	_viewport(), _windowWidth(1), _windowHeight(1), -#else +#endif +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)  	_originalBitsPerPixel(0),  #endif  	_screen(0), _tmpscreen(0), @@ -801,8 +802,9 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {  	} else  #endif  	{ -		// Save the original bpp to be able to restore the video mode on unload -#if !SDL_VERSION_ATLEAST(2, 0, 0) +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) +		// Save the original bpp to be able to restore the video mode on +		// unload. See _originalBitsPerPixel documentation.  		if (_originalBitsPerPixel == 0) {  			const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();  			_originalBitsPerPixel = videoInfo->vfmt->BitsPerPixel; @@ -947,9 +949,10 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {  #endif  	DestroyScalers(); -#if !SDL_VERSION_ATLEAST(2, 0, 0) -	// Reset video mode to original -	// This will ensure that any new graphic manager will use the initial BPP when listing available modes +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) +	// Reset video mode to original. +	// This will ensure that any new graphic manager will use the initial BPP +	// when listing available modes. See _originalBitsPerPixel documentation.  	if (_originalBitsPerPixel != 0)  		SDL_SetVideoMode(_videoMode.screenWidth, _videoMode.screenHeight, _originalBitsPerPixel, _videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_SWSURFACE) : SDL_SWSURFACE);  #endif diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index c4f7346525..25d6ff041c 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -251,8 +251,22 @@ protected:  	};  	VideoState _videoMode, _oldVideoMode; -	// Original BPP to restore the video mode on unload +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) +	/** +	 * Original BPP to restore the video mode on unload. +	 * +	 * This is required to make listing video modes for the OpenGL output work +	 * on Windows 8+. On these systems OpenGL modes are only available for +	 * 32bit formats. However, we setup a 16bit format and thus mode listings +	 * for OpenGL will return an empty list afterwards. +	 * +	 * In theory we might require this behavior on non-Win32 platforms too. +	 * However, SDL sometimes gives us invalid pixel formats for X11 outputs +	 * causing crashes when trying to setup the original pixel format. +	 * See bug #7038 "IRIX: X BadMatch when trying to start any 640x480 game". +	 */  	uint8 _originalBitsPerPixel; +#endif  	/** Force full redraw on next updateScreen */  	bool _forceFull; diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index e2b327ffa7..52a46200cb 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -185,6 +185,9 @@ MusicDevices WindowsMusicPlugin::getDevices() const {  		deviceNames.push_back(tmp.szPname);  	} +	// Limit us to the number of actually retrieved devices. +	numDevs = deviceNames.size(); +  	// Check for non-unique device names. This may happen if someone has devices with identical  	// names (e. g. more than one USB device of the exact same hardware type). It seems that this  	// does happen in reality sometimes. We generate index numbers for these devices. diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index d7713f99d8..f847296892 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -469,7 +469,7 @@ void OSystem_Android::updateScreen() {  		GLCALL(glTranslatex(0, -_shake_offset << 16, 0));  	} -// TODO this doesnt work on those sucky drivers, do it differently +// TODO this doesn't work on those sucky drivers, do it differently  //	if (_show_overlay)  //		GLCALL(glColor4ub(0x9f, 0x9f, 0x9f, 0x9f)); diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp index 5f5cdff24f..75fc1ed0df 100644 --- a/backends/platform/dc/vmsave.cpp +++ b/backends/platform/dc/vmsave.cpp @@ -165,30 +165,7 @@ static bool tryDelete(const char *filename, int vm)    return true;  } -static bool matches(const char *glob, const char *name) -{ -  while(*glob) -    if(*glob == '*') { -      while(*glob == '*') -	glob++; -      do { -	if((*name == *glob || *glob == '?') && -	   matches(glob, name)) -	  return true; -      } while(*name++); -      return false; -    } else if(!*name) -      return false; -    else if(*glob == '?' || *glob == *name) { -      glob++; -      name++; -    } -    else -      return false; -  return !*name; -} - -static void tryList(const char *glob, int vm, Common::StringArray &list) +static void tryList(const Common::String &glob, int vm, Common::StringArray &list)  {    struct vmsinfo info;    struct superblock super; @@ -205,7 +182,7 @@ static void tryList(const char *glob, int vm, Common::StringArray &list)        char buf[16];        strncpy(buf, (char *)de.entry+4, 12);        buf[12] = 0; -      if (matches(glob, buf)) +      if (Common::matchString(buf, glob.c_str()))  	list.push_back(buf);      }  } @@ -425,7 +402,7 @@ Common::StringArray VMSaveManager::listSavefiles(const Common::String &pattern)    Common::StringArray list;    for (int i=0; i<24; i++) -    tryList(pattern.c_str(), i, list); +    tryList(pattern, i, list);    return list;  } diff --git a/backends/platform/dingux/README.GCW0 b/backends/platform/dingux/README.GCW0 new file mode 100644 index 0000000000..1875e5323a --- /dev/null +++ b/backends/platform/dingux/README.GCW0 @@ -0,0 +1,26 @@ +[ScummVM-GCW0 README] + +Controls +======== +- Dpad/analog joy: move mouse cursor +- A: left mouse button click +- B: right mouse button click +- X: '0' key +- Y: '.' key (skips dialogue line in some engines) +- Left Trigger: open global menu +- Right Trigger: opens virtual keyboard +- Select: ESC button, scene skip in some engines +- Start: F5 key, game menu in some engines + +Installation from binaries +========================== +Copy over scummvm.opk file + +Building from binaries +====================== +It's pretty simple if you are running Linux on an x86/amd64 machine: +1. Download and install the GCW0 toolchain (http://www.gcw-zero.com/develop) +2. Download ScummVM sources and uncompress them +3. Run backends/platform/dingux/build.gcw0.sh script +4. Copy the resulting file scummvm.opk to your device +5. Enjoy diff --git a/backends/platform/dingux/build.gcw0.sh b/backends/platform/dingux/build.gcw0.sh new file mode 100755 index 0000000000..c1a4fa29c2 --- /dev/null +++ b/backends/platform/dingux/build.gcw0.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +export PATH=/opt/gcw0-toolchain/usr/bin:$PATH + +# Disable high resolution engines since we have 320x240 hardware +./configure --host=gcw0 --enable-plugins --default-dynamic --enable-release  --disable-mt32emu --disable-hq-scalers && make -j6 gcw-opk && ls -l scummvm.opk diff --git a/backends/platform/dingux/dingux.mk b/backends/platform/dingux/dingux.mk index 1333e89ff8..56c26c3be1 100644 --- a/backends/platform/dingux/dingux.mk +++ b/backends/platform/dingux/dingux.mk @@ -55,6 +55,13 @@ endif  	$(CP) $(srcdir)/dists/gcw0/default.gcw0.desktop $(gcw0_bundle)/  	$(CP) $(srcdir)/dists/gcw0/scummvmrc $(gcw0_bundle)/  	$(CP) $(srcdir)/dists/gcw0/scummvm.sh $(gcw0_bundle)/ +	$(CP) $(srcdir)/backends/platform/dingux/README.GCW0 $(gcw0_bundle)/README.man.txt +	echo >> $(gcw0_bundle)/README.man.txt +	echo '[General README]' >> $(gcw0_bundle)/README.man.txt +	echo >> $(gcw0_bundle)/README.man.txt +	cat README >> $(gcw0_bundle)/README.man.txt + +#	$(CP) GeneralUser\ GS\ FluidSynth\ v1.44.sf2 $(gcw0_bundle)/  gcw0-opk-unstripped: $(gcw0_bundle)  	$(CP) $(PLUGINS) $(gcw0_bundle)/plugins/ @@ -65,3 +72,12 @@ gcw-opk: $(gcw0_bundle)  	$(STRIP) $(gcw0_bundle)/plugins/*  	$(STRIP) $(gcw0_bundle)/scummvm  	./dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm + +GeneralUser_GS_1.44-FluidSynth.zip: +	curl -s http://www.scummvm.org/frs/extras/SoundFont/GeneralUser_GS_1.44-FluidSynth.zip -o GeneralUser_GS_1.44-FluidSynth.zip + +GeneralUser\ GS\ FluidSynth\ v1.44.sf2: GeneralUser_GS_1.44-FluidSynth.zip +	unzip -n GeneralUser_GS_1.44-FluidSynth.zip +	mv "GeneralUser GS 1.44 FluidSynth/GeneralUser GS FluidSynth v1.44.sf2" . +	mv "GeneralUser GS 1.44 FluidSynth/README.txt" README.soundfont +	mv "GeneralUser GS 1.44 FluidSynth/LICENSE.txt" LICENSE.soundfont diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp index c1280a2969..25d9cbed15 100644 --- a/backends/platform/ios7/ios7_osys_main.cpp +++ b/backends/platform/ios7/ios7_osys_main.cpp @@ -79,6 +79,33 @@ AQCallbackStruct OSystem_iOS7::s_AudioQueue;  SoundProc OSystem_iOS7::s_soundCallback = NULL;  void *OSystem_iOS7::s_soundParam = NULL; +#ifdef IPHONE_SANDBOXED +class SandboxedSaveFileManager : public DefaultSaveFileManager { +	Common::String _sandboxRootPath; +public: + +	SandboxedSaveFileManager(Common::String sandboxRootPath, Common::String defaultSavepath) +			: DefaultSaveFileManager(defaultSavepath), _sandboxRootPath(sandboxRootPath) { +	} + +	virtual bool removeSavefile(const Common::String &filename) override { +		Common::String chrootedFile = getSavePath() + "/" + filename; +		Common::String realFilePath = _sandboxRootPath + chrootedFile; + +		if (remove(realFilePath.c_str()) != 0) { +			if (errno == EACCES) +				setError(Common::kWritePermissionDenied, "Search or write permission denied: "+chrootedFile); + +			if (errno == ENOENT) +				setError(Common::kPathDoesNotExist, "removeSavefile: '"+chrootedFile+"' does not exist or path is invalid"); +			return false; +		} else { +			return true; +		} +	} +}; +#endif +  OSystem_iOS7::OSystem_iOS7() :  	_mixer(NULL), _lastMouseTap(0), _queuedEventTime(0),  	_mouseNeedTextureUpdate(false), _secondaryTapped(false), _lastSecondaryTap(0), @@ -89,7 +116,8 @@ OSystem_iOS7::OSystem_iOS7() :  	_queuedInputEvent.type = Common::EVENT_INVALID;  	_touchpadModeEnabled = !iOS7_isBigDevice();  #ifdef IPHONE_SANDBOXED -	_fsFactory = new ChRootFilesystemFactory(iOS7_getDocumentsDir()); +	_chrootBasePath = iOS7_getDocumentsDir(); +	_fsFactory = new ChRootFilesystemFactory(_chrootBasePath);  #else  	_fsFactory = new POSIXFilesystemFactory();  #endif @@ -124,7 +152,7 @@ int OSystem_iOS7::timerHandler(int t) {  void OSystem_iOS7::initBackend() {  #ifdef IPHONE_SANDBOXED -	_savefileManager = new DefaultSaveFileManager("/Savegames"); +	_savefileManager = new SandboxedSaveFileManager(_chrootBasePath, "/Savegames");  #else  	_savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);  #endif diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h index cc2f1ccc06..174c160bd6 100644 --- a/backends/platform/ios7/ios7_osys_main.h +++ b/backends/platform/ios7/ios7_osys_main.h @@ -111,6 +111,10 @@ protected:  	char *_lastErrorMessage; +#ifdef IPHONE_SANDBOXED +	Common::String _chrootBasePath; +#endif +  public:  	OSystem_iOS7(); diff --git a/backends/platform/maemo/debian/changelog b/backends/platform/maemo/debian/changelog index 8975871203..6b6d1aebd8 100644 --- a/backends/platform/maemo/debian/changelog +++ b/backends/platform/maemo/debian/changelog @@ -1,8 +1,14 @@ -scummvm (1.8.0~git) unstable; urgency=low +scummvm (1.9.0~git) unstable; urgency=low    * Development snapshot - -- Tarek Soliman <tsoliman@scummvm.org>  Mon, 01 Feb 2016 22:37:44 -0600 + -- Tarek Soliman <tsoliman@scummvm.org>  Fri, 26 Feb 2016 21:11:20 -0600 + +scummvm (1.8.0) unstable; urgency=low + +  * 1.8.0 release + + -- Tarek Soliman <tsoliman@scummvm.org>  Fri, 26 Feb 2016 21:11:20 -0600  scummvm (1.7.0) unstable; urgency=low diff --git a/backends/platform/maemo/debian/rules b/backends/platform/maemo/debian/rules index 70f52aac8f..0e72c8aa9a 100755 --- a/backends/platform/maemo/debian/rules +++ b/backends/platform/maemo/debian/rules @@ -6,8 +6,8 @@ build: scummvm  scummvm:  	dh_testdir -	./configure --host=maemo -	$(MAKE) +	./configure --host=maemo $(CONFIGURE_EXTRA_ARGS) +	$(MAKE) $(MAKE_EXTRA_ARGS)  clean:  	dh_testdir diff --git a/backends/platform/sdl/amigaos/amigaos.mk b/backends/platform/sdl/amigaos/amigaos.mk index 0c3c467965..15a2e9f93f 100644 --- a/backends/platform/sdl/amigaos/amigaos.mk +++ b/backends/platform/sdl/amigaos/amigaos.mk @@ -11,8 +11,14 @@ ifdef DIST_FILES_ENGINEDATA  	cp $(DIST_FILES_ENGINEDATA) $(AMIGAOSPATH)/extras/  endif  	cat ${srcdir}/README | sed -f ${srcdir}/dists/amiga/convertRM.sed > README.conv -	rx dists/amiga/RM2AG.rx README.conv -	cp ${srcdir}/README.guide $(AMIGAOSPATH) -	rm ${srcdir}/README.conv -	rm ${srcdir}/README.guide +# AmigaOS's shell is not happy with indented comments, thus don't do it. +# AREXX seems to have problems when ${srcdir} is '.'. It will break with a +# "Program not found" error. Therefore we copy the script to the cwd and +# remove it again, once it has finished. +	cp ${srcdir}/dists/amiga/RM2AG.rx . +	rx RM2AG.rx README.conv +	cp README.guide $(AMIGAOSPATH) +	rm RM2AG.rx +	rm README.conv +	rm README.guide  	cp $(DIST_FILES_DOCS) $(AMIGAOSPATH) diff --git a/backends/platform/sdl/sdl-sys.h b/backends/platform/sdl/sdl-sys.h index 67ad84efd3..551605a4b4 100644 --- a/backends/platform/sdl/sdl-sys.h +++ b/backends/platform/sdl/sdl-sys.h @@ -52,6 +52,21 @@ typedef struct { int FAKE; } FAKE_FILE;  #define strncasecmp FAKE_strncasecmp  #endif +#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit) +#undef exit +#define exit FAKE_exit +#endif + +#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort) +#undef abort +#define abort FAKE_abort +#endif + +#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system) +#undef system +#define system FAKE_system +#endif +  // HACK: SDL might include windows.h which defines its own ARRAYSIZE.  // However, we want to use the version from common/util.h. Thus, we make sure  // that we actually have this definition after including the SDL headers. @@ -112,7 +127,7 @@ typedef struct { int FAKE; } FAKE_FILE;  #endif  // In a moment of brilliance Xlib.h included by SDL_syswm.h #defines the -// following names. In a moment of mental breakdown, which occured upon +// following names. In a moment of mental breakdown, which occurred upon  // gazing at Xlib.h, LordHoto decided to undefine them to prevent havoc.  #ifdef Status  #undef Status @@ -146,6 +161,21 @@ typedef struct { int FAKE; } FAKE_FILE;  #define strncasecmp    FORBIDDEN_SYMBOL_REPLACEMENT  #endif +#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit) +#undef exit +#define exit(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort) +#undef abort +#define abort() FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system) +#undef system +#define system(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif +  // SDL 2 has major API changes. We redefine constants which got renamed to  // ease the transition. This is sometimes dangerous because the values changed  // too! diff --git a/backends/platform/sdl/win32/win32-main.cpp b/backends/platform/sdl/win32/win32-main.cpp index c6339f0c8c..4864347d81 100644 --- a/backends/platform/sdl/win32/win32-main.cpp +++ b/backends/platform/sdl/win32/win32-main.cpp @@ -44,7 +44,12 @@ int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/,  LPSTR /*lpC  	SDL_SetModuleHandle(GetModuleHandle(NULL));  #endif  // HACK: __argc, __argv are broken and return zero when using mingwrt 4.0+ on MinGW -#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__) +// HACK: MinGW-w64 based toolchains neither feature _argc nor _argv. The 32 bit +// incarnation only defines __MINGW32__. This leads to build breakage due to +// missing declarations. Luckily MinGW-w64 based toolchains define +// __MINGW64_VERSION_foo macros inside _mingw.h, which is included from all +// system headers. Thus we abuse that to detect them. +#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)  	return main(_argc, _argv);  #else  	return main(__argc, __argv); diff --git a/backends/platform/tizen/system.cpp b/backends/platform/tizen/system.cpp index a235456670..1820a28791 100644 --- a/backends/platform/tizen/system.cpp +++ b/backends/platform/tizen/system.cpp @@ -81,36 +81,41 @@ struct TizenSaveFileManager : public DefaultSaveFileManager {  };  bool TizenSaveFileManager::removeSavefile(const Common::String &filename) { -	Common::String savePathName = getSavePath(); +	// Assure the savefile name cache is up-to-date. +	assureCached(getSavePath()); +	if (getError().getCode() != Common::kNoError) +		return false; -	checkPath(Common::FSNode(savePathName)); -	if (getError().getCode() != Common::kNoError) { +	// Obtain node if exists. +	SaveFileCache::const_iterator file = _saveFileCache.find(filename); +	if (file == _saveFileCache.end()) {  		return false; -	} +	} else { +		const Common::FSNode fileNode = file->_value; +		// Remove from cache, this invalidates the 'file' iterator. +		_saveFileCache.erase(file); +		file = _saveFileCache.end(); -	// recreate FSNode since checkPath may have changed/created the directory -	Common::FSNode savePath(savePathName); -	Common::FSNode file = savePath.getChild(filename); +		String unicodeFileName; +		StringUtil::Utf8ToString(fileNode.getPath().c_str(), unicodeFileName); -	String unicodeFileName; -	StringUtil::Utf8ToString(file.getPath().c_str(), unicodeFileName); +		switch (Tizen::Io::File::Remove(unicodeFileName)) { +		case E_SUCCESS: +			return true; -	switch (Tizen::Io::File::Remove(unicodeFileName)) { -	case E_SUCCESS: -		return true; +		case E_ILLEGAL_ACCESS: +			setError(Common::kWritePermissionDenied, "Search or write permission denied: " + +						file.getName()); +			break; -	case E_ILLEGAL_ACCESS: -		setError(Common::kWritePermissionDenied, "Search or write permission denied: " + -					file.getName()); -		break; +		default: +			setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() + +						"' does not exist or path is invalid"); +			break; +		} -	default: -		setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() + -					"' does not exist or path is invalid"); -		break; +		return false;  	} - -	return false;  }  // diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index c1b0c7f692..02853b548e 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -645,7 +645,7 @@ Common::String OSystem_WINCE3::getSystemLanguage() const {  	const char *posixMappingTable[][3] = {  		{"CAT", "ESP", "ca_ES"},  		{"CSY", "CZE", "cs_CZ"}, -		{"DAN", "DNK", "da_DA"}, +		{"DAN", "DNK", "da_DK"},  		{"DEU", "DEU", "de_DE"},  		{"ESN", "ESP", "es_ES"},  		{"ESP", "ESP", "es_ES"}, @@ -657,7 +657,7 @@ Common::String OSystem_WINCE3::getSystemLanguage() const {  		{"PLK", "POL", "pl_PL"},  		{"PTB", "BRA", "pt_BR"},  		{"RUS", "RUS", "ru_RU"}, -		{"SVE", "SWE", "se_SE"}, +		{"SVE", "SWE", "sv_SE"},  		{"UKR", "UKR", "uk_UA"},  		{NULL, NULL, NULL}  	}; diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp index 5f4d405da4..ae8a5f0472 100644 --- a/backends/plugins/win32/win32-provider.cpp +++ b/backends/plugins/win32/win32-provider.cpp @@ -77,7 +77,7 @@ public:  			debug("Failed loading plugin '%s' (error code %d)", _filename.c_str(), (int32) GetLastError());  			return false;  		} else { -			debug(1, "Success loading plugin '%s', handle %08X", _filename.c_str(), (uint32) _dlHandle); +			debug(1, "Success loading plugin '%s', handle %p", _filename.c_str(), _dlHandle);  		}  		return DynamicPlugin::loadPlugin(); diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp index 4f7013724a..daec36ae72 100644 --- a/backends/saves/default/default-saves.cpp +++ b/backends/saves/default/default-saves.cpp @@ -60,22 +60,15 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {  }  Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) { -	Common::String savePathName = getSavePath(); -	checkPath(Common::FSNode(savePathName)); +	// Assure the savefile name cache is up-to-date. +	assureCached(getSavePath());  	if (getError().getCode() != Common::kNoError)  		return Common::StringArray(); -	// recreate FSNode since checkPath may have changed/created the directory -	Common::FSNode savePath(savePathName); - -	Common::FSDirectory dir(savePath); -	Common::ArchiveMemberList savefiles;  	Common::StringArray results; -	Common::String search(pattern); - -	if (dir.listMatchingMembers(savefiles, search) > 0) { -		for (Common::ArchiveMemberList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) { -			results.push_back((*file)->getName()); +	for (SaveFileCache::const_iterator file = _saveFileCache.begin(), end = _saveFileCache.end(); file != end; ++file) { +		if (file->_key.matchString(pattern, true)) { +			results.push_back(file->_key);  		}  	} @@ -83,68 +76,81 @@ Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &  }  Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) { -	// Ensure that the savepath is valid. If not, generate an appropriate error. -	Common::String savePathName = getSavePath(); -	checkPath(Common::FSNode(savePathName)); +	// Assure the savefile name cache is up-to-date. +	assureCached(getSavePath());  	if (getError().getCode() != Common::kNoError) -		return 0; - -	// recreate FSNode since checkPath may have changed/created the directory -	Common::FSNode savePath(savePathName); +		return nullptr; -	Common::FSNode file = savePath.getChild(filename); -	if (!file.exists()) -		return 0; - -	// Open the file for reading -	Common::SeekableReadStream *sf = file.createReadStream(); - -	return Common::wrapCompressedReadStream(sf); +	SaveFileCache::const_iterator file = _saveFileCache.find(filename); +	if (file == _saveFileCache.end()) { +		return nullptr; +	} else { +		// Open the file for loading. +		Common::SeekableReadStream *sf = file->_value.createReadStream(); +		return Common::wrapCompressedReadStream(sf); +	}  }  Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename, bool compress) { -	// Ensure that the savepath is valid. If not, generate an appropriate error. -	Common::String savePathName = getSavePath(); -	checkPath(Common::FSNode(savePathName)); +	// Assure the savefile name cache is up-to-date. +	const Common::String savePathName = getSavePath(); +	assureCached(savePathName);  	if (getError().getCode() != Common::kNoError) -		return 0; +		return nullptr; -	// recreate FSNode since checkPath may have changed/created the directory -	Common::FSNode savePath(savePathName); +	// Obtain node. +	SaveFileCache::const_iterator file = _saveFileCache.find(filename); +	Common::FSNode fileNode; -	Common::FSNode file = savePath.getChild(filename); +	// If the file did not exist before, we add it to the cache. +	if (file == _saveFileCache.end()) { +		const Common::FSNode savePath(savePathName); +		fileNode = savePath.getChild(filename); +	} else { +		fileNode = file->_value; +	} -	// Open the file for saving -	Common::WriteStream *sf = file.createWriteStream(); +	// Open the file for saving. +	Common::WriteStream *const sf = fileNode.createWriteStream(); +	Common::OutSaveFile *const result = compress ? Common::wrapCompressedWriteStream(sf) : sf; -	return compress ? Common::wrapCompressedWriteStream(sf) : sf; +	// Add file to cache now that it exists. +	_saveFileCache[filename] = Common::FSNode(fileNode.getPath()); + +	return result;  }  bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) { -	Common::String savePathName = getSavePath(); -	checkPath(Common::FSNode(savePathName)); +	// Assure the savefile name cache is up-to-date. +	assureCached(getSavePath());  	if (getError().getCode() != Common::kNoError)  		return false; -	// recreate FSNode since checkPath may have changed/created the directory -	Common::FSNode savePath(savePathName); - -	Common::FSNode file = savePath.getChild(filename); - -	// FIXME: remove does not exist on all systems. If your port fails to -	// compile because of this, please let us know (scummvm-devel or Fingolfin). -	// There is a nicely portable workaround, too: Make this method overloadable. -	if (remove(file.getPath().c_str()) != 0) { +	// Obtain node if exists. +	SaveFileCache::const_iterator file = _saveFileCache.find(filename); +	if (file == _saveFileCache.end()) { +		return false; +	} else { +		const Common::FSNode fileNode = file->_value; +		// Remove from cache, this invalidates the 'file' iterator. +		_saveFileCache.erase(file); +		file = _saveFileCache.end(); + +		// FIXME: remove does not exist on all systems. If your port fails to +		// compile because of this, please let us know (scummvm-devel). +		// There is a nicely portable workaround, too: Make this method overloadable. +		if (remove(fileNode.getPath().c_str()) != 0) {  #ifndef _WIN32_WCE -		if (errno == EACCES) -			setError(Common::kWritePermissionDenied, "Search or write permission denied: "+file.getName()); +			if (errno == EACCES) +				setError(Common::kWritePermissionDenied, "Search or write permission denied: "+fileNode.getName()); -		if (errno == ENOENT) -			setError(Common::kPathDoesNotExist, "removeSavefile: '"+file.getName()+"' does not exist or path is invalid"); +			if (errno == ENOENT) +				setError(Common::kPathDoesNotExist, "removeSavefile: '"+fileNode.getName()+"' does not exist or path is invalid");  #endif -		return false; -	} else { -		return true; +			return false; +		} else { +			return true; +		}  	}  } @@ -171,4 +177,43 @@ Common::String DefaultSaveFileManager::getSavePath() const {  	return dir;  } +void DefaultSaveFileManager::assureCached(const Common::String &savePathName) { +	// Check that path exists and is usable. +	checkPath(Common::FSNode(savePathName)); + +	if (_cachedDirectory == savePathName) { +		return; +	} + +	_saveFileCache.clear(); +	_cachedDirectory.clear(); + +	if (getError().getCode() != Common::kNoError) { +		warning("DefaultSaveFileManager::assureCached: Can not cache path '%s': '%s'", savePathName.c_str(), getErrorDesc().c_str()); +		return; +	} + +	// FSNode can cache its members, thus create it after checkPath to reflect +	// actual file system state. +	const Common::FSNode savePath(savePathName); + +	Common::FSList children; +	if (!savePath.getChildren(children, Common::FSNode::kListFilesOnly)) { +		return; +	} + +	// Build the savefile name cache. +	for (Common::FSList::const_iterator file = children.begin(), end = children.end(); file != end; ++file) { +		if (_saveFileCache.contains(file->getName())) { +			warning("DefaultSaveFileManager::assureCached: Name clash when building cache, ignoring file '%s'", file->getName().c_str()); +		} else { +			_saveFileCache[file->getName()] = *file; +		} +	} + +	// Only now store that we cached 'savePathName' to indicate we successfully +	// cached the directory. +	_cachedDirectory = savePathName; +} +  #endif // !defined(DISABLE_DEFAULT_SAVEFILEMANAGER) diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h index 81f45f96b8..bf4ca0229d 100644 --- a/backends/saves/default/default-saves.h +++ b/backends/saves/default/default-saves.h @@ -27,6 +27,7 @@  #include "common/savefile.h"  #include "common/str.h"  #include "common/fs.h" +#include "common/hashmap.h"  /**   * Provides a default savefile manager implementation for common platforms. @@ -54,6 +55,30 @@ protected:  	 * Sets the internal error and error message accordingly.  	 */  	virtual void checkPath(const Common::FSNode &dir); + +	/** +	 * Assure that the given save path is cached. +	 * +	 * @param savePathName  String representation of save path to cache. +	 */ +	void assureCached(const Common::String &savePathName); + +	typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SaveFileCache; + +	/** +	 * Cache of all the save files in the currently cached directory. +	 * +	 * Modify with caution because we only re-cache when the save path changed! +	 * This needs to be updated inside at least openForSaving and +	 * removeSavefile. +	 */ +	SaveFileCache _saveFileCache; + +private: +	/** +	 * The currently cached directory. +	 */ +	Common::String _cachedDirectory;  };  #endif diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp index 0192b1dc03..f3339fb917 100644 --- a/backends/taskbar/win32/win32-taskbar.cpp +++ b/backends/taskbar/win32/win32-taskbar.cpp @@ -28,8 +28,22 @@  #if defined(WIN32) && defined(USE_TASKBAR) +// HACK: To get __MINGW64_VERSION_foo defines we need to manually include +// _mingw.h in this file because we do not include any system headers at this +// point on purpose. The defines are required to detect whether this is a +// classic MinGW toolchain or a MinGW-w64 based one. +#if defined(__MINGW32__) +#include <_mingw.h> +#endif +  // Needed for taskbar functions -#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__) +// HACK: MinGW-w64 based toolchains include the symbols we require in their +// headers. The 32 bit incarnation only defines __MINGW32__. This leads to +// build breakage due to clashes with our compat header. Luckily MinGW-w64 +// based toolchains define __MINGW64_VERSION_foo macros inside _mingw.h, +// which is included from all system headers. Thus we abuse that to detect +// them. +#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)  	#include "backends/taskbar/win32/mingw-compat.h"  #else  	// We use functionality introduced with Win7 in this file.  | 
