diff --git a/backends/fs/posix-drives/posix-drives-fs-factory.cpp b/backends/fs/posix-drives/posix-drives-fs-factory.cpp index 848d527c6b8..371d3b87e33 100644 --- a/backends/fs/posix-drives/posix-drives-fs-factory.cpp +++ b/backends/fs/posix-drives/posix-drives-fs-factory.cpp @@ -20,7 +20,7 @@ * */ -#if defined(POSIX) +#if defined(POSIX) || defined(PSP2) #define FORBIDDEN_SYMBOL_ALLOW_ALL @@ -43,8 +43,12 @@ AbstractFSNode *DrivesPOSIXFilesystemFactory::makeRootFileNode() const { } AbstractFSNode *DrivesPOSIXFilesystemFactory::makeCurrentDirectoryFileNode() const { +#if defined(PSP2) // The Vita does not have getcwd + return makeRootFileNode(); +#else char buf[MAXPATHLEN]; - return getcwd(buf, MAXPATHLEN) ? new DrivePOSIXFilesystemNode(buf, _config) : nullptr; + return getcwd(buf, MAXPATHLEN) ? new DrivePOSIXFilesystemNode(buf, _config) : makeRootFileNode(); +#endif } AbstractFSNode *DrivesPOSIXFilesystemFactory::makeFileNodePath(const Common::String &path) const { diff --git a/backends/fs/posix-drives/posix-drives-fs.cpp b/backends/fs/posix-drives/posix-drives-fs.cpp index 43297f15b14..4ad5a3bbf60 100644 --- a/backends/fs/posix-drives/posix-drives-fs.cpp +++ b/backends/fs/posix-drives/posix-drives-fs.cpp @@ -20,7 +20,7 @@ * */ -#if defined(POSIX) +#if defined(POSIX) || defined(PSP2) #define FORBIDDEN_SYMBOL_ALLOW_ALL diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp index a908729dd7e..a6cc818eae8 100644 --- a/backends/fs/posix/posix-fs.cpp +++ b/backends/fs/posix/posix-fs.cpp @@ -42,11 +42,9 @@ #include #endif #ifdef PSP2 -#include "backends/fs/psp2/psp2-dirent.h" #define mkdir sceIoMkdir -#else -#include #endif +#include #include #include #include @@ -83,16 +81,6 @@ void POSIXFilesystemNode::setFlags() { POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p) { assert(p.size() > 0); -#ifdef PSP2 - if (p == "/") { - _isDirectory = true; - _isValid = false; - _path = p; - _displayName = p; - return; - } -#endif - // Expand "~/" to the value of the HOME env variable if (p.hasPrefix("~/") || p == "~") { const char *home = getenv("HOME"); @@ -183,15 +171,6 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo return true; } #endif -#ifdef PSP2 - if (_path == "/") { - POSIXFilesystemNode *entry1 = new POSIXFilesystemNode("ux0:"); - myList.push_back(entry1); - POSIXFilesystemNode *entry2 = new POSIXFilesystemNode("uma0:"); - myList.push_back(entry2); - return true; - } -#endif #if defined(__ANDROID__) && !defined(ANDROIDSDL) if (_path == "/") { @@ -287,10 +266,6 @@ AbstractFSNode *POSIXFilesystemNode::getParent() const { // This is a root directory of a drive return makeNode("/"); // return a virtual root for a list of drives #endif -#ifdef PSP2 - if (_path.hasSuffix(":")) - return makeNode("/"); -#endif const char *start = _path.c_str(); const char *end = start + _path.size(); diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 48404cdecaf..3842922c428 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -91,6 +91,7 @@ public: virtual void showOverlay() = 0; virtual void hideOverlay() = 0; + virtual bool isOverlayVisible() const = 0; virtual Graphics::PixelFormat getOverlayFormat() const = 0; virtual void clearOverlay() = 0; virtual void grabOverlay(void *buf, int pitch) const = 0; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index fab949e3d06..d3ee0790edc 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -84,6 +84,7 @@ public: virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override; int16 getOverlayWidth() const override; int16 getOverlayHeight() const override; + virtual bool isOverlayVisible() const override { return _overlayVisible; } /* Render the passed Surfaces besides the game texture. * This is used for widescreen support in the Grim engine. diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 12dddea4c22..974d036cfc2 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -62,6 +62,7 @@ public: virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override; virtual int16 getOverlayWidth() const override { return _overlayscreen->w; } virtual int16 getOverlayHeight() const override { return _overlayscreen->h; } + virtual bool isOverlayVisible() const override { return _overlayVisible; } /* Render the passed Surfaces besides the game texture. * This is used for widescreen support in the Grim engine. diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h index 4125a861ba1..203e69d833a 100644 --- a/backends/graphics/windowed.h +++ b/backends/graphics/windowed.h @@ -77,6 +77,8 @@ public: _forceRedraw = true; } + virtual bool isOverlayVisible() const override { return _overlayVisible; } + virtual void setShakePos(int shakeXOffset, int shakeYOffset) override { if (_gameScreenShakeXOffset != shakeXOffset || _gameScreenShakeYOffset != shakeYOffset) { _gameScreenShakeXOffset = shakeXOffset; diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp index 16cff80f310..f66d5d3e3fa 100644 --- a/backends/keymapper/keymap.cpp +++ b/backends/keymapper/keymap.cpp @@ -365,10 +365,12 @@ bool Keymap::areMappingsIdentical(const Array &mappingsA, const S // Assumes array values are not duplicated, but registerMapping and addDefaultInputMapping ensure that uint foundCount = 0; + uint validDefaultMappings = 0; for (uint i = 0; i < mappingsB.size(); i++) { // We resolve the hardware input to make sure it is not a default for some hardware we don't have currently HardwareInput mappingB = _hardwareInputSet->findHardwareInput(mappingsB[i]); if (mappingB.type == kHardwareInputTypeInvalid) continue; + validDefaultMappings++; for (uint j = 0; j < mappingsA.size(); j++) { if (mappingsA[j].id == mappingB.id) { @@ -378,7 +380,7 @@ bool Keymap::areMappingsIdentical(const Array &mappingsA, const S } } - return foundCount == mappingsA.size(); + return foundCount == mappingsA.size() && foundCount == validDefaultMappings; } } // End of namespace Common diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h index 60ca0912a26..6cb115d941e 100644 --- a/backends/keymapper/keymapper.h +++ b/backends/keymapper/keymapper.h @@ -106,6 +106,7 @@ public: * Keymaps with the global type are always enabled */ void setEnabledKeymapType(Keymap::KeymapType type); + Keymap::KeymapType enabledKeymapType() const { return _enabledKeymapType; } /** * Enable/disable the keymapper @@ -159,6 +160,27 @@ private: void resetInputState(); }; +/** + * RAII helper to temporarily enable a keymap type + */ +class KeymapTypeEnabler { +public: + KeymapTypeEnabler(Keymapper *keymapper, Keymap::KeymapType keymapType) : + _keymapper(keymapper) { + assert(keymapper); + _previousKeymapType = keymapper->enabledKeymapType(); + keymapper->setEnabledKeymapType(keymapType); + } + + ~KeymapTypeEnabler() { + _keymapper->setEnabledKeymapType(_previousKeymapType); + } + +private: + Keymapper *_keymapper; + Keymap::KeymapType _previousKeymapType; +}; + class DelayedEventSource : public EventSource { public: // EventSource API diff --git a/backends/keymapper/virtual-mouse.cpp b/backends/keymapper/virtual-mouse.cpp index 552fdbd1ee3..b9d81ec6a66 100644 --- a/backends/keymapper/virtual-mouse.cpp +++ b/backends/keymapper/virtual-mouse.cpp @@ -65,7 +65,7 @@ bool VirtualMouse::pollEvent(Event &event) { // Adjust the speed of the cursor according to the virtual screen resolution Common::Rect screenSize; - if (g_gui.isActive()) { + if (g_system->isOverlayVisible()) { screenSize = Common::Rect(g_system->getOverlayWidth(), g_system->getOverlayHeight()); } else { screenSize = Common::Rect(g_system->getWidth(), g_system->getHeight()); diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index 856b0de05ea..108f64cc1cd 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -219,6 +219,10 @@ void ModularGraphicsBackend::hideOverlay() { _graphicsManager->hideOverlay(); } +bool ModularGraphicsBackend::isOverlayVisible() const { + return _graphicsManager->isOverlayVisible(); +} + Graphics::PixelFormat ModularGraphicsBackend::getOverlayFormat() const { return _graphicsManager->getOverlayFormat(); } diff --git a/backends/modular-backend.h b/backends/modular-backend.h index 30d8934d925..aefa8285404 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -106,6 +106,7 @@ public: virtual void showOverlay() override final; virtual void hideOverlay() override final; + virtual bool isOverlayVisible() const override final; virtual Graphics::PixelFormat getOverlayFormat() const override final; virtual void clearOverlay() override final; virtual void grabOverlay(void *buf, int pitch) override final; diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp index 267448c859d..74cf1f26314 100644 --- a/backends/vkeybd/virtual-keyboard.cpp +++ b/backends/vkeybd/virtual-keyboard.cpp @@ -26,6 +26,8 @@ #include "backends/vkeybd/virtual-keyboard.h" +#include "backends/keymapper/keymapper.h" +#include "backends/keymapper/keymap.h" #include "backends/vkeybd/virtual-keyboard-gui.h" #include "backends/vkeybd/virtual-keyboard-parser.h" #include "backends/vkeybd/keycode-descriptions.h" @@ -230,7 +232,11 @@ void VirtualKeyboard::show() { } switchMode(_initialMode); - _kbdGUI->run(); + + { + KeymapTypeEnabler guiKeymap(_system->getEventManager()->getKeymapper(), Keymap::kKeymapTypeGui); + _kbdGUI->run(); + } if (_submitKeys) { EventManager *eventMan = _system->getEventManager(); diff --git a/base/plugins.cpp b/base/plugins.cpp index 6892df1a5ff..d54f2da22ad 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -159,7 +159,9 @@ PluginList FilePluginProvider::getPlugins() { Common::FSList pluginDirs; // Add the default directories + #ifndef WIN32 pluginDirs.push_back(Common::FSNode(".")); + #endif pluginDirs.push_back(Common::FSNode("plugins")); // Add the provider's custom directories diff --git a/common/macresman.cpp b/common/macresman.cpp index 917bb278543..49c4545b7d0 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -116,15 +116,20 @@ String MacResManager::computeResForkMD5AsString(uint32 length) const { } bool MacResManager::open(const String &fileName) { + return open(fileName, SearchMan); +} + +bool MacResManager::open(const String &fileName, Archive &archive) { close(); #ifdef MACOSX // Check the actual fork on a Mac computer - String fullPath = ConfMan.get("path") + "/" + fileName + "/..namedfork/rsrc"; - FSNode resFsNode = FSNode(fullPath); - if (resFsNode.exists()) { + const ArchiveMemberPtr archiveMember = archive.getMember(fileName); + const Common::FSNode *plainFsNode = dynamic_cast(archiveMember.get()); + if (plainFsNode) { + String fullPath = plainFsNode->getPath() + "/..namedfork/rsrc"; + FSNode resFsNode = FSNode(fullPath); SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); - if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = fileName; return true; @@ -134,111 +139,37 @@ bool MacResManager::open(const String &fileName) { } #endif - File *file = new File(); - // Prefer standalone files first, starting with raw forks - if (file->open(fileName + ".rsrc") && loadFromRawFork(*file)) { + SeekableReadStream *stream = archive.createReadStreamForMember(fileName + ".rsrc"); + if (stream && loadFromRawFork(*stream)) { _baseFileName = fileName; return true; } - file->close(); + delete stream; // Then try for AppleDouble using Apple's naming - if (file->open(constructAppleDoubleName(fileName)) && loadFromAppleDouble(*file)) { + stream = archive.createReadStreamForMember(constructAppleDoubleName(fileName)); + if (stream && loadFromAppleDouble(*stream)) { _baseFileName = fileName; return true; } - file->close(); + delete stream; // Check .bin for MacBinary next - if (file->open(fileName + ".bin") && loadFromMacBinary(*file)) { + stream = archive.createReadStreamForMember(fileName + ".bin"); + if (stream && loadFromMacBinary(*stream)) { _baseFileName = fileName; return true; } - file->close(); + delete stream; // As a last resort, see if just the data fork exists - if (file->open(fileName)) { + stream = archive.createReadStreamForMember(fileName); + if (stream) { _baseFileName = fileName; // Maybe file is in MacBinary but without .bin extension? // Check it here - if (isMacBinary(*file)) { - file->seek(0); - if (loadFromMacBinary(*file)) - return true; - } - - file->seek(0); - _stream = file; - return true; - } - - delete file; - - // The file doesn't exist - return false; -} - -bool MacResManager::open(const FSNode &path, const String &fileName) { - close(); - -#ifdef MACOSX - // Check the actual fork on a Mac computer - String fullPath = path.getPath() + "/" + fileName + "/..namedfork/rsrc"; - FSNode resFsNode = FSNode(fullPath); - if (resFsNode.exists()) { - SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); - - if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { - _baseFileName = fileName; - return true; - } - - delete macResForkRawStream; - } -#endif - - // Prefer standalone files first, starting with raw forks - FSNode fsNode = path.getChild(fileName + ".rsrc"); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromRawFork(*stream)) { - _baseFileName = fileName; - return true; - } - delete stream; - } - - // Then try for AppleDouble using Apple's naming - fsNode = path.getChild(constructAppleDoubleName(fileName)); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromAppleDouble(*stream)) { - _baseFileName = fileName; - return true; - } - delete stream; - } - - // Check .bin for MacBinary next - fsNode = path.getChild(fileName + ".bin"); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - if (loadFromMacBinary(*stream)) { - _baseFileName = fileName; - return true; - } - delete stream; - } - - // As a last resort, see if just the data fork exists - fsNode = path.getChild(fileName); - if (fsNode.exists() && !fsNode.isDirectory()) { - SeekableReadStream *stream = fsNode.createReadStream(); - _baseFileName = fileName; - - // FIXME: Is this really needed? if (isMacBinary(*stream)) { stream->seek(0); if (loadFromMacBinary(*stream)) diff --git a/common/macresman.h b/common/macresman.h index 6ae3fd36dcd..6ac831fe2e7 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -68,14 +68,14 @@ public: bool open(const String &fileName); /** - * Open a Mac data/resource fork pair. + * Open a Mac data/resource fork pair from within the given archive. * * @param path The path that holds the forks * @param fileName The base file name of the file * @note This will check for the raw resource fork, MacBinary, and AppleDouble formats. * @return True on success */ - bool open(const FSNode &path, const String &fileName); + bool open(const String &fileName, Archive &archive); /** * See if a Mac data/resource fork pair exists. diff --git a/common/platform.cpp b/common/platform.cpp index 8d78c477011..1c88860196d 100644 --- a/common/platform.cpp +++ b/common/platform.cpp @@ -59,6 +59,7 @@ const PlatformDescription g_platforms[] = { { "os2", "os2", "os2", "OS/2", kPlatformOS2 }, { "beos", "beos", "beos", "BeOS", kPlatformBeOS }, { "ppc", "ppc", "ppc", "PocketPC", kPlatformPocketPC }, + { "megadrive", "genesis", "md", "Mega Drive/Genesis", kPlatformMegaDrive }, { nullptr, nullptr, nullptr, "Default", kPlatformUnknown } }; diff --git a/common/platform.h b/common/platform.h index 5f7e08596ae..5d8b96070b7 100644 --- a/common/platform.h +++ b/common/platform.h @@ -64,6 +64,7 @@ enum Platform { kPlatformOS2, kPlatformBeOS, kPlatformPocketPC, + kPlatformMegaDrive, kPlatformUnknown = -1 }; diff --git a/common/system.h b/common/system.h index cb1955275f9..3e36b7684e0 100644 --- a/common/system.h +++ b/common/system.h @@ -1134,6 +1134,9 @@ public: /** Deactivate the overlay mode. */ virtual void hideOverlay() = 0; + /** Returns true if the overlay mode is activated, false otherwise. */ + virtual bool isOverlayVisible() const = 0; + /** * Returns the pixel format description of the overlay. * @see Graphics::PixelFormat diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 48203e8fe56..17b0161999b 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -169,7 +169,7 @@ bool XMLParser::parseActiveKey(bool closed) { if (layout->children.contains(key->name)) { key->layout = layout->children[key->name]; - StringMap localMap = key->values; + const StringMap &localMap = key->values; int keyCount = localMap.size(); for (List::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) { diff --git a/configure b/configure index af8c7770b66..5d38427e400 100755 --- a/configure +++ b/configure @@ -219,6 +219,7 @@ _nasm=auto _optimization_level= _default_optimization_level=-O2 _nuked_opl=no +_builtin_resources=yes # Default commands _ranlib=ranlib _strip=strip @@ -1032,6 +1033,8 @@ Optional Features: --enable-tts build support for text to speech --disable-tts don't build support for text to speech --disable-bink don't build with Bink video support + --no-builtin-resources do not include additional resources (e.g. engine data, fonts) + into the ResidualVM binary Optional Libraries: --with-alsa-prefix=DIR prefix where alsa is installed (optional) @@ -1474,6 +1477,9 @@ for ac_option in $@; do --enable-tsan) _enable_tsan=yes ;; + --no-builtin-resources) + _builtin_resources=no + ;; --with-sdl-prefix=*) arg=`echo $ac_option | cut -d '=' -f 2` _sdlpath="$arg:$arg/bin" @@ -2555,6 +2561,9 @@ case $_host_os in append_var LIBS "-lcitro3d" ;; amigaos*) + if test "$_debug_build" = no; then + _optimization_level=-O2 + fi append_var LDFLAGS "-Wl,--export-dynamic" append_var LDFLAGS "-L/sdk/local/newlib/lib" # We have to use 'long' for our 4 byte typedef because AmigaOS already typedefs (u)int32 @@ -2566,24 +2575,6 @@ case $_host_os in _port_mk="backends/platform/sdl/amigaos/amigaos.mk" _nuked_opl=no ;; - morphos*) - if test "$_debug_build" = no; then - _optimization_level=-O2 - fi - append_var LDFLAGS "-Wl,--export-dynamic" - append_var LDFLAGS "-L/usr/local/lib" - append_var CXXFLAGS "-D__MORPHOS_SHAREDLIBS" - # We have to use 'long' for our 4 byte typedef because MorphOS already typedefs (u)int32 - # as (unsigned) long, and consequently we'd get a compiler error otherwise. - type_4_byte='long' - # Supress format warnings as the long 4 byte causes noisy warnings. - append_var CXXFLAGS "-Wno-format" - add_line_to_config_mk 'MORPHOS = 1' - _port_mk="backends/platform/sdl/morphos/morphos.mk" - # for use SDL2 - _sdlconfig=sdl2-config - _nuked_opl=no - ;; android) case $_host in android-arm-v7a) @@ -2647,10 +2638,13 @@ case $_host_os in # which will allow for calls larger than 32MB. The linker # will discard the calls if they are not needed, but we # need to ensure the compiler emits them in the first place. + # Also the executable has grown to a size where using -Os is necessary to avoid a + # 'virtual memory exhausted' error when running the executable. case $_host_cpu in powerpc*) append_var CFLAGS "-mlongcall" append_var CXXFLAGS "-mlongcall" + _optimization_level=-Os ;; esac @@ -2863,7 +2857,7 @@ EOF append_var LIBS "-specs=ds_arm9.specs" append_var LIBS "-lnds9" ;; - freebsd*) + freebsd* | openbsd*) append_var LDFLAGS "-L/usr/local/lib" append_var CXXFLAGS "-I/usr/local/include" ;; @@ -2923,6 +2917,24 @@ EOF append_var DEFINES "-D_GNU_SOURCE" append_var DEFINES "-D_ISOC11_SOURCE" ;; + morphos*) + if test "$_debug_build" = no; then + _optimization_level=-O2 + fi + append_var LDFLAGS "-Wl,--export-dynamic" + append_var LDFLAGS "-L/usr/local/lib" + append_var CXXFLAGS "-D__MORPHOS_SHAREDLIBS" + # We have to use 'long' for our 4 byte typedef because MorphOS already typedefs (u)int32 + # as (unsigned) long, and consequently we'd get a compiler error otherwise. + type_4_byte='long' + # Supress format warnings as the long 4 byte causes noisy warnings. + append_var CXXFLAGS "-Wno-format" + add_line_to_config_mk 'MORPHOS = 1' + _port_mk="backends/platform/sdl/morphos/morphos.mk" + # for use SDL2 + _sdlconfig=sdl2-config + _nuked_opl=no + ;; msys) echo ERROR: Using the MSYS shell in msys mode is not supported. Please use the MSYS shell in mingw mode instead. exit 1 @@ -3975,7 +3987,7 @@ _mak_plugins=' PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/ds/plugin.ld -mthumb-interwork -mfloat-abi=soft ' ;; - freebsd*) + freebsd* | openbsd*) _plugin_prefix="lib" _plugin_suffix=".so" append_var CXXFLAGS "-fPIC" @@ -4164,7 +4176,7 @@ int main(void) { return 0; } EOF cc_check -lsapi -lole32 && _tts=yes ;; - linux* | freebsd*) + linux* | freebsd* | openbsd*) cat > $TMPC << EOF #include int main(void) { return 0; } @@ -5614,7 +5626,7 @@ if test "$_tts" = "no"; then echo "no" else case $_host_os in - linux* | freebsd*) + linux* | freebsd* | openbsd*) echo "speech dispatcher" _tts=yes define_in_config_if_yes $_tts 'USE_SPEECH_DISPATCHER' @@ -5660,6 +5672,11 @@ else fi define_in_config_if_yes $_updates 'USE_UPDATES' +# +# Check whether to create a build with all resources files linked into the binary +# +define_in_config_if_yes "$_builtin_resources" 'BUILTIN_RESOURCES' + # # Check whether to activate engines (ResidualVM specific) # diff --git a/devtools/create_translations/create_translations.cpp b/devtools/create_translations/create_translations.cpp index 685eb21c2b1..db6af5b3ac6 100644 --- a/devtools/create_translations/create_translations.cpp +++ b/devtools/create_translations/create_translations.cpp @@ -122,6 +122,12 @@ int main(int argc, char *argv[]) { } } + if (!numLangs) { + fprintf(stderr, "ERROR: No valid translation files\n"); + fprintf(stderr, "usage: create_translations lang1.po [lang2.po ...]\n"); + return -1; + } + for (int i = 0; i < numLangs; i++) { if (!translations[i]->useUTF8()) { fprintf(stderr, "ERROR: Po Language file for: \"%s\", named as \"%s\" is not encoded in UTF-8\n", translations[i]->languageName(), translations[i]->language()); diff --git a/devtools/encode-macbinary.sh b/devtools/encode-macbinary.sh index e9465c10d7f..25b2b5f1b7e 100755 --- a/devtools/encode-macbinary.sh +++ b/devtools/encode-macbinary.sh @@ -14,8 +14,9 @@ Mode 1: Operate in MacBinary encoding mode Mode 2: - $0 + $0 [jap] Operate in disk dumping mode + Optionally specify 'jap' for using 'recode' for converting Japanese file names Miscellaneous: -h, --help display this help and exit @@ -23,6 +24,7 @@ EOF } path= +jap= macbinarydump() { mypath=`realpath $0` @@ -45,31 +47,52 @@ macbinarydump() { } hfsdump() { - IFS=$'\n' mypath=`realpath $0` - for i in `hls -F1a` - do + if [[ jap == "jap" ]] ; then + flist=`hls -F1a|recode SJIS..utf-8` + else + flist=`hls -F1a` + fi + + echo "$flist" | while read i ; do + if [[ jap == "jap" ]] ; then + macname=`echo "$i"|recode utf-8..SJIS` + else + macname="$i" + fi + + # Guard empty directories + if [[ "$i" == "" ]] ; then + continue + fi + if [[ "$i" =~ ":" ]] ; then - dir="${i%?}" - hcd "$dir" - mkdir "$dir" - cd "$dir" - bash $mypath hfsutils-phase2 "$path:$i" + dir="${i%?}" # Strip trailing ':' + dir="${dir//\//:}" # Files could contain '/', replace those with ':' + macdir="${macname%?}" + hcd "$macdir" + mkdir -- "$dir" + cd -- "$dir" + bash $mypath $jap hfsutils-phase2 "$path:$i" hcd :: cd .. else echo -ne "$path$i... \r" # Executable files have star at their end. Strip it if [[ "$i" =~ \*$ ]] ; then + macfile="${macname%?}" file="${i%?}" else + macfile="$macname" file="$i" fi - fileunix="$file" - # Files count contain stars - file="${file//\*/\\*}" - hcopy -m "$file" "./$fileunix" + fileunix="${file//\//:}" # Files could contain '/', replace those with ':' + + # Files could contain '*', '{', so backslash them to avoid globbing + macfile="${macfile//\*/\\*}" + macfile="${macfile//{/\\{}" + hcopy -m -- "$macfile" "./$fileunix" fi done } @@ -82,7 +105,7 @@ for parm in "$@" ; do done # for parm in ... if [[ $1 == "macbinary" ]] ; then - if test ! `type macbinary >/dev/null 2>/dev/null` ; then + if ! `command -v macbinary >/dev/null 2>/dev/null` ; then echo "macbinary not found. Exiting" exit 1 fi @@ -104,6 +127,16 @@ if [ "$#" -lt 1 ] ; then exit 1 fi +if [[ $1 == "jap" ]] ; then + if ! `command -v recode >/dev/null 2>/dev/null` ; then + echo "recode not found. Exiting" + exit 1 + fi + + jap=jap + shift +fi + if [[ $1 == "hfsutils-phase2" ]] ; then path=$2 hfsdump diff --git a/dists/engine-data/fonts.dat b/dists/engine-data/fonts.dat index 793256c4898..4632f9d88e9 100644 Binary files a/dists/engine-data/fonts.dat and b/dists/engine-data/fonts.dat differ diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index d220abf55ac..58b162805a0 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -35,6 +35,45 @@ #include "engines/advancedDetector.h" #include "engines/obsolete.h" +/** + * Adapter to be able to use Common::Archive based code from the AD. + */ +class FileMapArchive : public Common::Archive { +public: + FileMapArchive(const AdvancedMetaEngine::FileMap &fileMap) : _fileMap(fileMap) {} + + bool hasFile(const Common::String &name) const override { + return _fileMap.contains(name); + } + + int listMembers(Common::ArchiveMemberList &list) const override { + int files = 0; + for (AdvancedMetaEngine::FileMap::const_iterator it = _fileMap.begin(); it != _fileMap.end(); ++it) { + list.push_back(Common::ArchiveMemberPtr(new Common::FSNode(it->_value))); + ++files; + } + + return files; + } + + const Common::ArchiveMemberPtr getMember(const Common::String &name) const override { + AdvancedMetaEngine::FileMap::const_iterator it = _fileMap.find(name); + if (it == _fileMap.end()) { + return Common::ArchiveMemberPtr(); + } + + return Common::ArchiveMemberPtr(new Common::FSNode(it->_value)); + } + + Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override { + Common::FSNode fsNode = _fileMap[name]; + return fsNode.createReadStream(); + } + +private: + const AdvancedMetaEngine::FileMap &_fileMap; +}; + static Common::String sanitizeName(const char *name) { Common::String res; @@ -355,14 +394,16 @@ void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSL } } -bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const { +bool AdvancedMetaEngine::getFileProperties(const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const { // FIXME/TODO: We don't handle the case that a file is listed as a regular // file and as one with resource fork. if (game.flags & ADGF_MACRESFORK) { + FileMapArchive fileMapArchive(allFiles); + Common::MacResManager macResMan; - if (!macResMan.open(parent, fname)) + if (!macResMan.open(fname, fileMapArchive)) return false; fileProps.md5 = macResMan.computeResForkMD5AsString(_md5Bytes); @@ -407,7 +448,7 @@ ADDetectedGames AdvancedMetaEngine::detectGame(const Common::FSNode &parent, con continue; FileProperties tmp; - if (getFileProperties(parent, allFiles, *g, fname, tmp)) { + if (getFileProperties(allFiles, *g, fname, tmp)) { debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str()); } @@ -510,7 +551,7 @@ ADDetectedGames AdvancedMetaEngine::detectGame(const Common::FSNode &parent, con return matched; } -ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const { +ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const { const ADFileBasedFallback *ptr; const char* const* filenames; @@ -546,7 +587,7 @@ ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, for (filenames = ptr->filenames; *filenames; ++filenames) { FileProperties tmp; - if (getFileProperties(fslist.begin()->getParent(), allFiles, *agdesc, *filenames, tmp)) + if (getFileProperties(allFiles, *agdesc, *filenames, tmp)) game.matchedFiles[*filenames] = tmp; } diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index ee8b7cbfd78..941f59d4976 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -305,7 +305,7 @@ protected: * @param fileBasedFallback a list of ADFileBasedFallback records, zero-terminated * @param filesProps if not 0, return a map of properties for all detected files here */ - ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const; + ADDetectedGame detectGameFilebased(const FileMap &allFiles, const ADFileBasedFallback *fileBasedFallback) const; /** * Compose a hashmap of all files in fslist. @@ -314,10 +314,12 @@ protected: void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName = Common::String()) const; /** Get the properties (size and MD5) of this file. */ - bool getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const; + bool getFileProperties(const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const; /** Convert an AD game description into the shared game description format */ virtual DetectedGame toDetectedGame(const ADDetectedGame &adGame) const; + + friend class FileMapArchive; // for FileMap }; #endif diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp index 4884c8be32a..2a8bc127bfe 100644 --- a/engines/metaengine.cpp +++ b/engines/metaengine.cpp @@ -37,20 +37,16 @@ #include "graphics/managed_surface.h" #include "graphics/thumbnail.h" -const char *MetaEngine::getSavegameFile(int saveGameIdx, const char *target) const { - static char buffer[200]; - - snprintf(buffer, sizeof(buffer), "%s.s%02d", target == nullptr ? getEngineId() : target, saveGameIdx); - - return buffer; -} - -const char *MetaEngine::getSavegamePattern(const char *target) const { - static char buffer[200]; - - snprintf(buffer, sizeof(buffer), "%s.s##", target == nullptr ? getEngineId() : target); - - return buffer; +Common::String MetaEngine::getSavegameFile(int saveGameIdx, const char *target) const { + if (saveGameIdx == kSavegameFilePattern) { + // Pattern requested + const char *pattern = hasFeature(kSavesUseExtendedFormat) ? "%s.###" : "%s.s##"; + return Common::String::format(pattern, target == nullptr ? getEngineId() : target); + } else { + // Specific filename requested + const char *pattern = hasFeature(kSavesUseExtendedFormat) ? "%s.%03d" : "%s.s%02d"; + return Common::String::format(pattern, target == nullptr ? getEngineId() : target, saveGameIdx); + } } Common::KeymapArray MetaEngine::initKeymaps(const char *target) const { @@ -274,7 +270,7 @@ SaveStateList MetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; - Common::String pattern(getSavegamePattern(target)); + Common::String pattern(getSavegameFilePattern(target)); filenames = saveFileMan->listSavefiles(pattern); diff --git a/engines/metaengine.h b/engines/metaengine.h index dabc3ce2891..7e9657b7cfd 100644 --- a/engines/metaengine.h +++ b/engines/metaengine.h @@ -67,6 +67,8 @@ struct ExtraGuiOption { typedef Common::Array ExtraGuiOptions; +enum { kSavegameFilePattern = -99 }; + #define EXTENDED_SAVE_VERSION 4 struct ExtendedSavegameHeader { @@ -244,7 +246,8 @@ public: * @return maximum save slot number supported */ virtual int getMaximumSaveSlot() const { - return 0; + // For games using the new save format, assume 99 slots by default + return hasFeature(kSavesUseExtendedFormat) ? 99 : 0; } /** @@ -273,19 +276,23 @@ public: virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; /** - * Returns name of the save file for given slot and optional target. + * Returns name of the save file for given slot and optional target, + * or a pattern for matching filenames against * - * @param saveGameIdx index of the save + * @param saveGameIdx index of the save, or kSavegameFilePattern + * for returning a filename pattern * @param target game target. If omitted, then the engine id is used */ - virtual const char *getSavegameFile(int saveGameIdx, const char *target = nullptr) const; + virtual Common::String getSavegameFile(int saveGameIdx, const char *target = nullptr) const; /** * Returns pattern for save files. * * @param target game target. If omitted, then the engine id is used */ - virtual const char *getSavegamePattern(const char *target = nullptr) const; + Common::String getSavegameFilePattern(const char *target = nullptr) const { + return getSavegameFile(kSavegameFilePattern, target); + } /** * Return the keymap used by the target. diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp index 8df8a53b9f9..5dcf005459d 100644 --- a/graphics/conversion.cpp +++ b/graphics/conversion.cpp @@ -29,6 +29,25 @@ namespace Graphics { // TODO: YUV to RGB conversion function +// Function to blit a rect +void copyBlit(byte *dst, const byte *src, + const uint dstPitch, const uint srcPitch, + const uint w, const uint h, + const uint bytesPerPixel) { + if (dst == src) + return; + + if (dstPitch == srcPitch && ((w * bytesPerPixel) == dstPitch)) { + memcpy(dst, src, dstPitch * h); + } else { + for (uint i = 0; i < h; ++i) { + memcpy(dst, src, w * bytesPerPixel); + dst += dstPitch; + src += srcPitch; + } + } +} + namespace { template @@ -111,18 +130,7 @@ bool crossBlit(byte *dst, const byte *src, // Don't perform unnecessary conversion if (srcFmt == dstFmt) { - if (dst != src) { - if (dstPitch == srcPitch && ((w * dstFmt.bytesPerPixel) == dstPitch)) { - memcpy(dst, src, dstPitch * h); - } else { - for (uint i = 0; i < h; ++i) { - memcpy(dst, src, w * dstFmt.bytesPerPixel); - dst += dstPitch; - src += srcPitch; - } - } - } - + copyBlit(dst, src, dstPitch, srcPitch, w, h, dstFmt.bytesPerPixel); return true; } diff --git a/graphics/conversion.h b/graphics/conversion.h index 1e5486864a1..b0b376babdb 100644 --- a/graphics/conversion.h +++ b/graphics/conversion.h @@ -45,6 +45,22 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) { // TODO: generic YUV to RGB blit +/** + * Blits a rectangle. + * + * @param dst the buffer which will recieve the converted graphics data + * @param src the buffer containing the original graphics data + * @param dstPitch width in bytes of one full line of the dest buffer + * @param srcPitch width in bytes of one full line of the source buffer + * @param w the width of the graphics data + * @param h the height of the graphics data + * @param bytesPerPixel the number of bytes per pixel + */ +void copyBlit(byte *dst, const byte *src, + const uint dstPitch, const uint srcPitch, + const uint w, const uint h, + const uint bytesPerPixel); + /** * Blits a rectangle from one graphical format to another. * diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index a22c4ee0b51..27b391071af 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -28,6 +28,7 @@ #include "common/tokenizer.h" #include "common/translation.h" +#include "graphics/conversion.h" #include "graphics/cursorman.h" #include "graphics/fontman.h" #include "graphics/surface.h" @@ -224,7 +225,11 @@ ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) : _cursorHotspotX = _cursorHotspotY = 0; _cursorWidth = _cursorHeight = 0; +#ifndef USE_RGB_COLOR + _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); + _cursorTransparent = 255; _cursorPalSize = 0; +#endif // We prefer files in archive bundles over the common search paths. _themeFiles.add("default", &SearchMan, 0, false); @@ -398,8 +403,10 @@ void ThemeEngine::refresh() { _system->showOverlay(); if (_useCursor) { +#ifndef USE_RGB_COLOR CursorMan.replaceCursorPalette(_cursorPal, 0, _cursorPalSize); - CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true); +#endif + CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, _cursorTransparent, true, &_cursorFormat); } } } @@ -518,10 +525,23 @@ bool ThemeEngine::addTextData(const Common::String &drawDataId, TextData textId, return true; } -bool ThemeEngine::addFont(TextData textId, const Common::String &file, const Common::String &scalableFile, const int pointsize) { +bool ThemeEngine::addFont(TextData textId, const Common::String &language, const Common::String &file, const Common::String &scalableFile, const int pointsize) { if (textId == -1) return false; + if (!language.empty() && !language.equals("*")) { +#ifdef USE_TRANSLATION + Common::String cl = TransMan.getCurrentLanguage(); + if (!cl.matchString(language, true)) + return true; // Skip + + if (_texts[textId] != nullptr) // We already loaded something + return true; +#else + return true; // Safely ignore +#endif + } + if (_texts[textId] != nullptr) delete _texts[textId]; @@ -1481,20 +1501,11 @@ void ThemeEngine::applyScreenShading(ShadingStyle style) { } bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY) { - if (!_system->hasFeature(OSystem::kFeatureCursorPalette)) - return true; - // Try to locate the specified file among all loaded bitmaps const Graphics::Surface *cursor = _bitmaps[filename]; if (!cursor) return false; -#ifdef USE_RGB_COLOR - _cursorFormat.bytesPerPixel = 1; - _cursorFormat.rLoss = _cursorFormat.gLoss = _cursorFormat.bLoss = _cursorFormat.aLoss = 8; - _cursorFormat.rShift = _cursorFormat.gShift = _cursorFormat.bShift = _cursorFormat.aShift = 0; -#endif - // Set up the cursor parameters _cursorHotspotX = hotspotX; _cursorHotspotY = hotspotY; @@ -1502,6 +1513,23 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int _cursorWidth = cursor->w; _cursorHeight = cursor->h; +#ifdef USE_RGB_COLOR + _cursorFormat = cursor->format; + _cursorTransparent = _cursorFormat.RGBToColor(0xFF, 0, 0xFF); + + // Allocate a new buffer for the cursor + delete[] _cursor; + _cursor = new byte[_cursorWidth * _cursorHeight * _cursorFormat.bytesPerPixel]; + assert(_cursor); + Graphics::copyBlit(_cursor, (const byte *)cursor->getPixels(), + _cursorWidth * _cursorFormat.bytesPerPixel, cursor->pitch, + _cursorWidth, _cursorHeight, _cursorFormat.bytesPerPixel); + + _useCursor = true; +#else + if (!_system->hasFeature(OSystem::kFeatureCursorPalette)) + return true; + // Allocate a new buffer for the cursor delete[] _cursor; _cursor = new byte[_cursorWidth * _cursorHeight]; @@ -1559,6 +1587,7 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int _useCursor = true; _cursorPalSize = colorsFound; +#endif return true; } @@ -2008,15 +2037,19 @@ Common::String ThemeEngine::getThemeId(const Common::String &filename) { void ThemeEngine::showCursor() { if (_useCursor) { +#ifndef USE_RGB_COLOR CursorMan.pushCursorPalette(_cursorPal, 0, _cursorPalSize); - CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true); +#endif + CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, _cursorTransparent, true, &_cursorFormat); CursorMan.showMouse(true); } } void ThemeEngine::hideCursor() { if (_useCursor) { +#ifndef USE_RGB_COLOR CursorMan.popCursorPalette(); +#endif CursorMan.popCursor(); } } diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index e8d3fb48315..32492a8e31b 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -37,7 +37,7 @@ #include "graphics/pixelformat.h" -#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.38" +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.39" class OSystem; @@ -513,11 +513,12 @@ public: * filename. * * @param textId Identifier name for the font. + * @param language Wildcard for the language(s) to use. * @param file Filename of the non-scalable font version. * @param scalableFile Filename of the scalable version. (Optional) * @param pointsize Point size for the scalable font. (Optional) */ - bool addFont(TextData textId, const Common::String &file, const Common::String &scalableFile, const int pointsize); + bool addFont(TextData textId, const Common::String &language, const Common::String &file, const Common::String &scalableFile, const int pointsize); /** * Interface for the ThemeParser class: adds a text color value. @@ -743,9 +744,7 @@ protected: ImagesMap _bitmaps; AImagesMap _abitmaps; Graphics::PixelFormat _overlayFormat; -#ifdef USE_RGB_COLOR Graphics::PixelFormat _cursorFormat; -#endif /** List of all the dirty screens that must be blitted to the overlay. */ Common::List _dirtyScreen; @@ -762,13 +761,16 @@ protected: bool _useCursor; int _cursorHotspotX, _cursorHotspotY; + uint32 _cursorTransparent; + byte *_cursor; + uint _cursorWidth, _cursorHeight; +#ifndef USE_RGB_COLOR enum { MAX_CURS_COLORS = 255 }; - byte *_cursor; - uint _cursorWidth, _cursorHeight; byte _cursorPal[3 * MAX_CURS_COLORS]; byte _cursorPalSize; +#endif Common::Rect _clip; }; diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index 23feda7b79f..020e1091c45 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -179,16 +179,51 @@ bool ThemeParser::parserCallback_font(ParserNode *node) { return true; } - // Default to a point size of 12. - int pointsize = 12; - if (node->values.contains("point_size")) { - if (sscanf(node->values["point_size"].c_str(), "%d", &pointsize) != 1 || pointsize <= 0) - return parserError(Common::String::format("Font \"%s\" has invalid point size \"%s\"", node->values["id"].c_str(), node->values["point_size"].c_str())); + return true; +} + +bool ThemeParser::parserCallback_language(ParserNode *node) { + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; } - TextData textDataId = parseTextDataId(node->values["id"]); - if (!_theme->addFont(textDataId, node->values["file"], node->values["scalable_file"], pointsize)) - return parserError("Error loading Font in theme engine."); + TextData textDataId = parseTextDataId(getParentNode(node)->values["id"]); + + // Default to a point size of 12. + int pointsize = 12; + Common::String ps; + if (node->values.contains("point_size")) { + ps = node->values["point_size"]; + } else if (getParentNode(node)->values.contains("point_size")) { + ps = getParentNode(node)->values["point_size"]; + } + + if (!ps.empty()) { + if (sscanf(ps.c_str(), "%d", &pointsize) != 1 || pointsize <= 0) + return parserError(Common::String::format("Font \"%s\" has invalid point size \"%s\"", node->values["id"].c_str(), ps.c_str())); + } + + Common::String file; + if (node->values.contains("file")) { + file = node->values["file"]; + } else if (getParentNode(node)->values.contains("file")) { + file = getParentNode(node)->values["file"]; + } + + if (file.empty()) { + return parserError("Missing required property 'file' in either or "); + } + + Common::String scalableFile; + if (node->values.contains("scalable_file")) { + scalableFile = node->values["scalable_file"]; + } else if (getParentNode(node)->values.contains("scalable_file")) { + scalableFile = getParentNode(node)->values["scalable_file"]; + } + + if (!_theme->addFont(textDataId, node->values["id"], file, scalableFile, pointsize)) + return parserError("Error loading localized Font in theme engine."); return true; } diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h index 1b3004f1acc..f91bd26f451 100644 --- a/gui/ThemeParser.h +++ b/gui/ThemeParser.h @@ -63,10 +63,16 @@ protected: XML_KEY(fonts) XML_KEY(font) XML_PROP(id, true) - XML_PROP(file, true) + XML_PROP(file, false) XML_PROP(resolution, false) XML_PROP(scalable_file, false) XML_PROP(point_size, false) + XML_KEY(language) + XML_PROP(id, true) + XML_PROP(file, false) + XML_PROP(scalable_file, false) + XML_PROP(point_size, false) + KEY_END() KEY_END() XML_KEY(text_color) @@ -224,6 +230,7 @@ protected: bool parserCallback_font(ParserNode *node); bool parserCallback_text_color(ParserNode *node); bool parserCallback_fonts(ParserNode *node); + bool parserCallback_language(ParserNode *node); bool parserCallback_text(ParserNode *node); bool parserCallback_palette(ParserNode *node); bool parserCallback_color(ParserNode *node); diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index bf424cc70a3..27ebc6a853f 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -449,6 +449,11 @@ void GuiManager::runLoop() { #endif } +void GuiManager::exitLoop() { + while (!_dialogStack.empty()) + getTopDialog()->close(); +} + #pragma mark - void GuiManager::saveState() { diff --git a/gui/gui-manager.h b/gui/gui-manager.h index dea22189c94..29769900b81 100644 --- a/gui/gui-manager.h +++ b/gui/gui-manager.h @@ -75,6 +75,11 @@ public: // until no dialogs are active anymore. void runLoop(); + // If the GUI loop is running close all the dialogs causing the loop to finish. + // Typically you may want to use it after setting the ConfMan active domain to + // a game domain to cause the game to start. + void exitLoop(); + void processEvent(const Common::Event &event, Dialog *const activeDialog); Common::Keymap *getKeymap() const; void scheduleTopDialogRedraw(); diff --git a/gui/options.cpp b/gui/options.cpp index bbf15e2aa85..9072b6ac684 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -2459,12 +2459,12 @@ void GlobalOptionsDialog::apply() { else { ttsMan->setLanguage(newLang); } + _ttsVoiceSelectionPopUp->setSelected(0); } #else ttsMan->setLanguage("en"); #endif // USE_TRANSLATION - _ttsVoiceSelectionPopUp->setSelected(0); int volume = (ConfMan.getInt("speech_volume", "residualvm") * 100) / 256; if (ConfMan.hasKey("mute", "residualvm") && ConfMan.getBool("mute", "residualvm")) volume = 0; @@ -2914,7 +2914,7 @@ void GlobalOptionsDialog::setupCloudTab() { uint64 usedSpace = CloudMan.getStorageUsedSpace(_selectedStorageIndex); Common::String usedSpaceNumber, usedSpaceUnits; usedSpaceNumber = Common::getHumanReadableBytes(usedSpace, usedSpaceUnits); - _storageUsedSpace->setLabel(Common::U32String::format(Common::U32String("%s %S"), usedSpaceNumber.c_str(), _(usedSpaceUnits).c_str())); + _storageUsedSpace->setLabel(Common::U32String::format("%s %S", usedSpaceNumber.c_str(), _(usedSpaceUnits).c_str())); _storageUsedSpace->setVisible(shownConnectedInfo); } if (_storageSyncHint) { diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp index c4a28b7da51..54a8e2539bd 100644 --- a/gui/saveload-dialog.cpp +++ b/gui/saveload-dialog.cpp @@ -1133,14 +1133,12 @@ void SaveLoadChooserGrid::updateSaves() { // In save mode we disable the button, when it's write protected. // TODO: Maybe we should not display it at all then? - if (_saveMode && desc.getWriteProtectedFlag()) { + // We also disable and description the button if slot is locked + if ((_saveMode && desc.getWriteProtectedFlag()) || desc.getLocked()) { curButton.button->setEnabled(false); } else { curButton.button->setEnabled(true); } - - //that would make it look "disabled" if slot is locked - curButton.button->setEnabled(!desc.getLocked()); curButton.description->setEnabled(!desc.getLocked()); } diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 193593f6f17..0dbba5d7b8c 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -22,33 +22,34 @@ const char *defaultXML1 = "" "/>" "" "" -"" +"" +"" +"" "" -"" +"id='text_default'>" +"" +"" +"" +"" +"" "" -"" +"id='text_button'>" +"" +"" +"" +"" +"" "" +"id='text_normal'>" +"" +"" "" -"" +"file='fixed5x8.bdf'>" +"" +"" +"" +"" +"" "" diff --git a/gui/themes/modern.zip b/gui/themes/modern.zip index 617aeaf93c8..92f22923c04 100644 Binary files a/gui/themes/modern.zip and b/gui/themes/modern.zip differ diff --git a/gui/themes/modern/THEMERC b/gui/themes/modern/THEMERC index 390a9a54e04..b2ed311fcae 100644 --- a/gui/themes/modern/THEMERC +++ b/gui/themes/modern/THEMERC @@ -1 +1 @@ -[SCUMMVM_STX0.8.38:ResidualVM Modern Theme:No Author] +[SCUMMVM_STX0.8.39:ResidualVM Modern Theme:No Author] diff --git a/gui/themes/modern/modern_gfx.stx b/gui/themes/modern/modern_gfx.stx index 35059f56f8e..77fe023c32f 100644 --- a/gui/themes/modern/modern_gfx.stx +++ b/gui/themes/modern/modern_gfx.stx @@ -127,57 +127,85 @@ + file = 'helvb12.bdf'> + + + + + + + point_size = '11'> + + + + + + + file = 'helvb12.bdf'> + + + + + + + point_size = '11'> + + + + + + + file = 'helvb12.bdf'> + + + + + + + point_size = '11'> + + + + + + + point_size = '8'> + + + + + + + point_size = '12'> + + + point_size = '10'> + + + point_size = '8'> + +