[Scummvm-git-logs] scummvm branch-2-1 -> 3558a70ce0dca08b1d62e6489f0083e91418691a

bgK bastien.bouclet at gmail.com
Thu Nov 7 11:32:29 CET 2019


This automated email contains information about 27 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4806b26d7f GRAPHICS: Fix drawing rounded rectangle borders for the non AA renderer
886bb3276d 3DS: Embed ScummVM's support files in the package
2b3a5d246f 3DS: Fix OSystem::grabOverlay
0443d0ab3e 3DS: Fix creating the scummvm directory on the SD card
03e4240f7f 3DS: Don't immediately update the screen when enabling the overlay
4d69de802d 3DS: Change the audio thread to wait for the audio buffers to complete
6bff952050 GUI: Fix pressing escape erroneously saving the changes in the options dialog
98f3a4e640 3DS: Add files to be removed by 3ds_clean in 3ds.mk:
753d26e573 3DS: Fix hi-color cursors
be05540528 3DS: Upload the textures to VRAM in a separate frame
e4ef9d9379 MOHAWK: MYST: Fix misuse of OSystem::fillScreen
11a056f461 3DS: Set 'scummvm.romfs' to be removed by 3ds_clean in 3ds.mk
f4e1d1bca0 3DS: Avoid stat calls in DrivePOSIXFilesystemNode
393ce8d0c6 NETWORKING: Try loading the CA bundle from DATA_PATH
0e64097576 3DS: Use DATA_PATH to configure support files location
c159f7e1f5 3DS: Implement cloud sync support
6e8f7a8119 PS3: Implement the cloud synchronization features
f81e50e549 3DS: Add a make rule for a distributable package
3ea36876db 3DS: Implement magnify mode toggle on L and move keyboard to Y/DRIGHT
cbfec1156e 3DS: Some changes to magnify mode
a151356a5b 3DS: Reworked OSD message display
236d15ec3a 3DS: Fix centering of the game screen
4c8e83f23e 3DS: Update the list of third-party libraries
c67615a8cc 3DS: Improve the table of contents in the README.md file
01876ad3d9 3DS: Use the full resolution for the overlay on the top screen
f89ecdc149 3DS: Rework mouse cursor movement
3558a70ce0 3DS: Remove 3dstool dependency


Commit: 4806b26d7f4a089ad9b61818903e0b062a7ad426
    https://github.com/scummvm/scummvm/commit/4806b26d7f4a089ad9b61818903e0b062a7ad426
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:09:55+01:00

Commit Message:
GRAPHICS: Fix drawing rounded rectangle borders for the non AA renderer

The check for the clipping rect was in the non-clip version of the method,
and was using values not in screen-space.

Changed paths:
    graphics/VectorRendererSpec.cpp


diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index a13c281..9650e93 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -3081,9 +3081,6 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
 		while (x++ < (y - 2)) {
 			BE_ALGORITHM();
 
-			if (x < _clippingArea.left || x > _clippingArea.right) continue;
-			if (y < _clippingArea.top || y > _clippingArea.bottom) continue;
-
 			BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
 			BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
 			BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));


Commit: 886bb3276d7c14835c960aaaa0b6c9d74bece4c0
    https://github.com/scummvm/scummvm/commit/886bb3276d7c14835c960aaaa0b6c9d74bece4c0
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:12:26+01:00

Commit Message:
3DS: Embed ScummVM's support files in the package

(cherry picked from commit f22e07825f9dfeec96edffe8ef435ffbfb75ef84)

Changed paths:
  A backends/fs/posix-drives/posix-drives-fs-factory.cpp
  A backends/fs/posix-drives/posix-drives-fs-factory.h
  A backends/fs/posix-drives/posix-drives-fs.cpp
  A backends/fs/posix-drives/posix-drives-fs.h
    backends/module.mk
    backends/platform/3ds/3ds.mk
    backends/platform/3ds/README.md
    backends/platform/3ds/main.cpp
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h


diff --git a/backends/fs/posix-drives/posix-drives-fs-factory.cpp b/backends/fs/posix-drives/posix-drives-fs-factory.cpp
new file mode 100644
index 0000000..709b57c
--- /dev/null
+++ b/backends/fs/posix-drives/posix-drives-fs-factory.cpp
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(POSIX)
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/fs/posix-drives/posix-drives-fs-factory.h"
+#include "backends/fs/posix-drives/posix-drives-fs.h"
+
+#include <unistd.h>
+
+void DrivesPOSIXFilesystemFactory::addDrive(const Common::String &name) {
+	_drives.push_back(Common::normalizePath(name, '/'));
+}
+
+AbstractFSNode *DrivesPOSIXFilesystemFactory::makeRootFileNode() const {
+	return new DrivePOSIXFilesystemNode(_drives);
+}
+
+AbstractFSNode *DrivesPOSIXFilesystemFactory::makeCurrentDirectoryFileNode() const {
+	char buf[MAXPATHLEN];
+	return getcwd(buf, MAXPATHLEN) ? new DrivePOSIXFilesystemNode(buf, _drives) : nullptr;
+}
+
+AbstractFSNode *DrivesPOSIXFilesystemFactory::makeFileNodePath(const Common::String &path) const {
+	assert(!path.empty());
+	return new DrivePOSIXFilesystemNode(path, _drives);
+}
+
+#endif
diff --git a/backends/fs/posix-drives/posix-drives-fs-factory.h b/backends/fs/posix-drives/posix-drives-fs-factory.h
new file mode 100644
index 0000000..08b8b69
--- /dev/null
+++ b/backends/fs/posix-drives/posix-drives-fs-factory.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef POSIX_DRIVES_FILESYSTEM_FACTORY_H
+#define POSIX_DRIVES_FILESYSTEM_FACTORY_H
+
+#include "backends/fs/fs-factory.h"
+
+/**
+ * A FilesystemFactory implementation for filesystems with a special
+ * top-level directory with hard-coded entries but that otherwise
+ * implement the POSIX APIs.
+ *
+ * For used with paths like these:
+ * - 'sdcard:/games/scummvm.ini'
+ * - 'hdd1:/usr/bin'
+ */
+class DrivesPOSIXFilesystemFactory : public FilesystemFactory {
+public:
+	/**
+	 * Add a drive to the top-level directory
+	 */
+	void addDrive(const Common::String &name);
+
+protected:
+	// FilesystemFactory API
+	AbstractFSNode *makeRootFileNode() const override;
+	AbstractFSNode *makeCurrentDirectoryFileNode() const override;
+	AbstractFSNode *makeFileNodePath(const Common::String &path) const override;
+
+private:
+	Common::Array<Common::String> _drives;
+};
+
+#endif
diff --git a/backends/fs/posix-drives/posix-drives-fs.cpp b/backends/fs/posix-drives/posix-drives-fs.cpp
new file mode 100644
index 0000000..683ab19
--- /dev/null
+++ b/backends/fs/posix-drives/posix-drives-fs.cpp
@@ -0,0 +1,136 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(POSIX)
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/fs/posix-drives/posix-drives-fs.h"
+#include "common/algorithm.h"
+
+#include <dirent.h>
+
+DrivePOSIXFilesystemNode::DrivePOSIXFilesystemNode(const Common::String &path, const DrivesArray &drives) :
+		POSIXFilesystemNode(path),
+		_isPseudoRoot(false),
+		_drives(drives) {
+
+	if (isDrive(path)) {
+		_isDirectory = true;
+		_isValid = true;
+
+		// FIXME: Add a setting for deciding whether drive paths need to end with a slash
+		if (!_path.hasSuffix("/")) {
+			_path += "/";
+		}
+		return;
+	}
+}
+
+DrivePOSIXFilesystemNode::DrivePOSIXFilesystemNode(const DrivesArray &drives) :
+		_isPseudoRoot(true),
+		_drives(drives) {
+	_isDirectory = true;
+	_isValid = false;
+}
+
+AbstractFSNode *DrivePOSIXFilesystemNode::getChild(const Common::String &n) const {
+	if (!_isPseudoRoot) {
+		return POSIXFilesystemNode::getChild(n);
+	}
+
+	// Make sure the string contains no slashes
+	assert(!n.contains('/'));
+
+	Common::String newPath(_path);
+	if (_path.lastChar() != '/')
+		newPath += '/';
+	newPath += n;
+
+	return makeNode(newPath);
+}
+
+bool DrivePOSIXFilesystemNode::getChildren(AbstractFSList &list, AbstractFSNode::ListMode mode, bool hidden) const {
+	assert(_isDirectory);
+
+	if (_isPseudoRoot) {
+		for (uint i = 0; i < _drives.size(); i++) {
+			list.push_back(makeNode(_drives[i]));
+		}
+
+		return true;
+	} else {
+		DIR *dirp = opendir(_path.c_str());
+		struct dirent *dp;
+
+		if (!dirp)
+			return false;
+
+		while ((dp = readdir(dirp)) != nullptr) {
+			// Skip 'invisible' files if necessary
+			if (dp->d_name[0] == '.' && !hidden) {
+				continue;
+			}
+
+			// Skip '.' and '..' to avoid cycles
+			if ((dp->d_name[0] == '.' && dp->d_name[1] == 0) || (dp->d_name[0] == '.' && dp->d_name[1] == '.')) {
+				continue;
+			}
+
+			AbstractFSNode *child = getChild(dp->d_name);
+
+			// Honor the chosen mode
+			if ((mode == Common::FSNode::kListFilesOnly && child->isDirectory()) ||
+				(mode == Common::FSNode::kListDirectoriesOnly && !child->isDirectory())) {
+				delete child;
+				continue;
+			}
+
+			list.push_back(child);
+		}
+
+		closedir(dirp);
+
+		return true;
+	}
+}
+
+AbstractFSNode *DrivePOSIXFilesystemNode::getParent() const {
+	if (_isPseudoRoot) {
+		return nullptr;
+	}
+
+	if (isDrive(_path)) {
+		DrivePOSIXFilesystemNode *root = new DrivePOSIXFilesystemNode(_drives);
+		return root;
+	}
+
+	return POSIXFilesystemNode::getParent();
+}
+
+bool DrivePOSIXFilesystemNode::isDrive(const Common::String &path) const {
+	Common::String normalizedPath = Common::normalizePath(path, '/');
+	DrivesArray::const_iterator drive = Common::find(_drives.begin(), _drives.end(), normalizedPath);
+	return drive != _drives.end();
+}
+
+#endif //#if defined(POSIX)
diff --git a/backends/fs/posix-drives/posix-drives-fs.h b/backends/fs/posix-drives/posix-drives-fs.h
new file mode 100644
index 0000000..43c8942
--- /dev/null
+++ b/backends/fs/posix-drives/posix-drives-fs.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef POSIX_DRIVES_FILESYSTEM_H
+#define POSIX_DRIVES_FILESYSTEM_H
+
+#include "backends/fs/posix/posix-fs.h"
+
+/**
+ * POSIX file system node where the top-level directory is a hardcoded
+ * list of drives.
+ */
+class DrivePOSIXFilesystemNode : public POSIXFilesystemNode {
+protected:
+	AbstractFSNode *makeNode(const Common::String &path) const override {
+		return new DrivePOSIXFilesystemNode(path, _drives);
+	}
+
+public:
+	typedef Common::Array<Common::String> DrivesArray;
+
+	DrivePOSIXFilesystemNode(const Common::String &path, const DrivesArray &drives);
+	DrivePOSIXFilesystemNode(const DrivesArray &drives);
+
+	// POSIXFilesystemNode API
+	AbstractFSNode *getChild(const Common::String &n) const override;
+	bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const override;
+	AbstractFSNode *getParent() const override;
+
+private:
+	bool _isPseudoRoot;
+	const DrivesArray &_drives;
+
+	bool isDrive(const Common::String &path) const;
+};
+
+#endif
diff --git a/backends/module.mk b/backends/module.mk
index 771b3f8..2201e65 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -161,6 +161,8 @@ ifdef POSIX
 MODULE_OBJS += \
 	fs/posix/posix-fs.o \
 	fs/posix/posix-fs-factory.o \
+	fs/posix-drives/posix-drives-fs.o \
+	fs/posix-drives/posix-drives-fs-factory.o \
 	fs/chroot/chroot-fs-factory.o \
 	fs/chroot/chroot-fs.o \
 	plugins/posix/posix-provider.o \
diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index 7cb162f..dcb7b5e 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -21,21 +21,40 @@ clean: clean_3ds
 clean_3ds:
 	$(RM) $(TARGET).3dsx
 	$(RM) $(TARGET).cia
+	$(RM) -rf romfs
+
+romfs: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD)
+	@rm -rf romfs
+	@mkdir -p romfs
+	@cp $(DIST_FILES_THEMES) romfs/
+ifdef DIST_FILES_ENGINEDATA
+	@cp $(DIST_FILES_ENGINEDATA) romfs/
+endif
+ifdef DIST_FILES_NETWORKING
+	@cp $(DIST_FILES_NETWORKING) romfs/
+endif
+ifdef DIST_FILES_VKEYBD
+	@cp $(DIST_FILES_VKEYBD) romfs/
+endif
 
 $(TARGET).smdh: $(APP_ICON)
 	@smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
 	@echo built ... $(notdir $@)
 
-$(TARGET).3dsx: $(EXECUTABLE) $(TARGET).smdh
-	@3dsxtool $< $@ --smdh=$(TARGET).smdh
+$(TARGET).3dsx: $(EXECUTABLE) $(TARGET).smdh romfs
+	@3dsxtool $< $@ --smdh=$(TARGET).smdh --romfs=romfs
 	@echo built ... $(notdir $@)
 	
 $(TARGET).bnr: $(APP_BANNER_IMAGE) $(APP_BANNER_AUDIO)
 	@bannertool makebanner -o $@ -i $(APP_BANNER_IMAGE) -a $(APP_BANNER_AUDIO)
 	@echo built ... $(notdir $@)
-	
-$(TARGET).cia: $(EXECUTABLE) $(APP_RSF) $(TARGET).smdh $(TARGET).bnr
-	@makerom -f cia -target t -exefslogo -o $@ -elf $(EXECUTABLE) -rsf $(APP_RSF) -banner $(TARGET).bnr -icon $(TARGET).smdh
+
+$(TARGET).romfs: romfs
+	@3dstool -cvtf romfs $(TARGET).romfs --romfs-dir romfs
+	@echo built ... $(notdir $@)
+
+$(TARGET).cia: $(EXECUTABLE) $(APP_RSF) $(TARGET).smdh $(TARGET).bnr $(TARGET).romfs
+	@makerom -f cia -target t -exefslogo -o $@ -elf $(EXECUTABLE) -rsf $(APP_RSF) -banner $(TARGET).bnr -icon $(TARGET).smdh -romfs $(TARGET).romfs
 	@echo built ... $(notdir $@)
 
 #---------------------------------------------------------------------------------
diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index b45a2a6..95ce0f4 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -49,19 +49,7 @@ Not having this file will cause many problems with games that need audio, someti
 even crashing, so this is NOT considered optional.
 
 Using any CIA installation software (search elsewhere for that), you need to install
-the `scummvm.cia` file. Then, just like what is done with the 3DSX installation, you
-need to extract all ScummVM 3DS files (`scummvm.cia` excluded) to the root of your SD
-card so that all files reside in the `/3ds/scummvm/` directory.
-
-1.3) Additional files
----------------------
-In order to use the Virtual Keyboard, you need to get the:
-`backends/vkeybd/packs/vkeybd_small.zip` file from ScummVM's repository, and
-place it on your SD card, in the `/3ds/scummvm/kb` folder.
-
-In case you want a translated GUI, you need to get the:
-`scummvm/gui/themes/translations.dat` file from ScummVM's repository, and place
-it on your SD card, in the `/3ds/scummvm/themes` folder.
+the `scummvm.cia` file.
 
 2.0) Controls
 -------------
@@ -229,7 +217,7 @@ Additionally compile to specific formats to be used on the 3DS:
 Assuming everything was successful, you'll be able to find the binary
 files in the root of your scummvm folder.
 
-Note: for the CIA format, you will need the 'makerom' and 'bannertool' tools which are
+Note: for the CIA format, you will need the '3dstool', 'makerom' and 'bannertool' tools which are
 not supplied with devkitPro.
 
 4.3) Warning for build sizes
diff --git a/backends/platform/3ds/main.cpp b/backends/platform/3ds/main.cpp
index dc89faa..ce549b6 100644
--- a/backends/platform/3ds/main.cpp
+++ b/backends/platform/3ds/main.cpp
@@ -27,6 +27,7 @@ int main(int argc, char *argv[]) {
 	// Initialize basic libctru stuff
 	gfxInitDefault();
 	cfguInit();
+	romfsInit();
 	osSetSpeedupEnable(true);
 // 	consoleInit(GFX_TOP, NULL);
 
@@ -50,6 +51,7 @@ int main(int argc, char *argv[]) {
 		gspLcdExit();
 	}
 
+	romfsExit();
 	cfguExit();
 	gfxExit();
 	return res;
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index c42e208..0e5cb7b 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -36,8 +36,8 @@
 #include "common/str.h"
 #include "config.h"
 
-#include "backends/fs/posix/posix-fs-factory.h"
-#include "backends/fs/posix/posix-fs.h"
+#include "backends/fs/posix-drives/posix-drives-fs-factory.h"
+#include "backends/fs/posix-drives/posix-drives-fs.h"
 #include <unistd.h>
 #include <time.h>
 
@@ -77,8 +77,13 @@ OSystem_3DS::OSystem_3DS():
 	sleeping(false)
 {
 	chdir("sdmc:/");
-	_fsFactory = new POSIXFilesystemFactory();
-	Posix::assureDirectoryExists("/3ds/scummvm/saves/");
+
+	DrivesPOSIXFilesystemFactory *fsFactory = new DrivesPOSIXFilesystemFactory();
+	fsFactory->addDrive("sdmc:");
+	fsFactory->addDrive("romfs:");
+	_fsFactory = fsFactory;
+
+	Posix::assureDirectoryExists("sdmc:/3ds/scummvm/saves/");
 }
 
 OSystem_3DS::~OSystem_3DS() {
@@ -101,15 +106,11 @@ void OSystem_3DS::initBackend() {
 	ConfMan.registerDefault("aspect_ratio", true);
 	if (!ConfMan.hasKey("vkeybd_pack_name"))
 		ConfMan.set("vkeybd_pack_name", "vkeybd_small");
-	if (!ConfMan.hasKey("vkeybdpath"))
-		ConfMan.set("vkeybdpath", "/3ds/scummvm/kb");
-	if (!ConfMan.hasKey("themepath"))
-		ConfMan.set("themepath", "/3ds/scummvm");
 	if (!ConfMan.hasKey("gui_theme"))
 		ConfMan.set("gui_theme", "builtin");
 
 	_timerManager = new DefaultTimerManager();
-	_savefileManager = new DefaultSaveFileManager("/3ds/scummvm/saves/");
+	_savefileManager = new DefaultSaveFileManager("sdmc:/3ds/scummvm/saves/");
 
 	initGraphics();
 	initAudio();
@@ -125,7 +126,11 @@ void OSystem_3DS::updateConfig() {
 }
 
 Common::String OSystem_3DS::getDefaultConfigFileName() {
-	return "/3ds/scummvm/scummvm.ini";
+	return "sdmc:/3ds/scummvm/scummvm.ini";
+}
+
+void OSystem_3DS::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+	s.add("RomFS", new Common::FSDirectory("romfs:/"), priority);
 }
 
 uint32 OSystem_3DS::getMillis(bool skipRecord) {
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 6901295..28d21c3 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -88,6 +88,7 @@ public:
 	virtual void quit();
 
 	virtual Common::String getDefaultConfigFileName();
+	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
 
 	// Graphics
 	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;


Commit: 2b3a5d246f35056e35c2d57a29471f331104878b
    https://github.com/scummvm/scummvm/commit/2b3a5d246f35056e35c2d57a29471f331104878b
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:12:26+01:00

Commit Message:
3DS: Fix OSystem::grabOverlay

Fixes the transparency effects in the GUI.

(cherry picked from commit dfc0a5127e354ea959edc508db2316505785d85e)

Changed paths:
    backends/platform/3ds/osystem-graphics.cpp


diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 15fabc7..8e7ae89 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -415,8 +415,11 @@ void OSystem_3DS::clearOverlay() {
 }
 
 void OSystem_3DS::grabOverlay(void *buf, int pitch) {
+	byte *dst = (byte *)buf;
+
 	for (int y = 0; y < getOverlayHeight(); ++y) {
-		memcpy(buf, _overlay.getBasePtr(0, y), pitch);
+		memcpy(dst, _overlay.getBasePtr(0, y), getOverlayWidth() * _pfGameTexture.bytesPerPixel);
+		dst += pitch;
 	}
 }
 


Commit: 0443d0ab3e63107b284ee5f23facfe19e0737f9c
    https://github.com/scummvm/scummvm/commit/0443d0ab3e63107b284ee5f23facfe19e0737f9c
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:13:11+01:00

Commit Message:
3DS: Fix creating the scummvm directory on the SD card

(cherry picked from commit 0f9cdfc0b8ee386173a32dce0f73e7e48b5a4598)

Changed paths:
    backends/platform/3ds/osystem.cpp


diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index 0e5cb7b..8f896ad 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -83,7 +83,7 @@ OSystem_3DS::OSystem_3DS():
 	fsFactory->addDrive("romfs:");
 	_fsFactory = fsFactory;
 
-	Posix::assureDirectoryExists("sdmc:/3ds/scummvm/saves/");
+	Posix::assureDirectoryExists("/3ds/scummvm/saves/");
 }
 
 OSystem_3DS::~OSystem_3DS() {


Commit: 03e4240f7f62ee8e9649f1fefc8a70a33e039ead
    https://github.com/scummvm/scummvm/commit/03e4240f7f62ee8e9649f1fefc8a70a33e039ead
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:14:13+01:00

Commit Message:
3DS: Don't immediately update the screen when enabling the overlay

Fixes the overlay dirty buffer being visible for a frame when opening
the GUI while in-game.

(cherry picked from commit 650da9eb5bfa8960a6eea1baa0158465311b0960)

Changed paths:
    backends/platform/3ds/osystem-graphics.cpp


diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 8e7ae89..2bad1f5 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -397,13 +397,11 @@ void OSystem_3DS::updateFocus() {
 void OSystem_3DS::showOverlay() {
 	_overlayVisible = true;
 	updateSize();
-	updateScreen();
 }
 
 void OSystem_3DS::hideOverlay() {
 	_overlayVisible = false;
 	updateSize();
-	updateScreen();
 }
 
 Graphics::PixelFormat OSystem_3DS::getOverlayFormat() const {
@@ -446,7 +444,7 @@ bool OSystem_3DS::showMouse(bool visible) {
 void OSystem_3DS::warpMouse(int x, int y) {
 	_cursorX = x;
 	_cursorY = y;
-	warning("x:%d y:%d", x, y);
+
 	// TODO: adjust for _cursorScalable ?
 	int offsetx = 0;
 	int offsety = 0;


Commit: 4d69de802dee9e068090aef0507c1fe5fe3715e1
    https://github.com/scummvm/scummvm/commit/4d69de802dee9e068090aef0507c1fe5fe3715e1
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:14:13+01:00

Commit Message:
3DS: Change the audio thread to wait for the audio buffers to complete

Fixes the regular pop sounds caused by buffer underruns / clobbering of
the previous implementation.

(cherry picked from commit c71fa02bf5c6a154d4d3a029664769e870d3394f)

Changed paths:
    backends/platform/3ds/osystem-audio.cpp


diff --git a/backends/platform/3ds/osystem-audio.cpp b/backends/platform/3ds/osystem-audio.cpp
index 5826237..043aaf1 100644
--- a/backends/platform/3ds/osystem-audio.cpp
+++ b/backends/platform/3ds/osystem-audio.cpp
@@ -31,18 +31,16 @@ static void audioThreadFunc(void *arg) {
 	Audio::MixerImpl *mixer = (Audio::MixerImpl *)arg;
 	OSystem_3DS *osys = (OSystem_3DS *)g_system;
 
-	int i;
 	const int channel = 0;
 	int bufferIndex = 0;
-	const int bufferCount = 3;
-	const int bufferSize = 80000; // Can't be too small, based on delayMillis duration
+	const int bufferCount = 2;
 	const int sampleRate = mixer->getOutputRate();
-	int sampleLen = 0;
-	uint32 lastTime = osys->getMillis(true);
-	uint32 time = lastTime;
+	const int bufferSamples = 1024;
+	const int bufferSize = bufferSamples * 4;
+
 	ndspWaveBuf buffers[bufferCount];
 
-	for (i = 0; i < bufferCount; ++i) {
+	for (int i = 0; i < bufferCount; ++i) {
 		memset(&buffers[i], 0, sizeof(ndspWaveBuf));
 		buffers[i].data_vaddr = linearAlloc(bufferSize);
 		buffers[i].looping = false;
@@ -55,27 +53,25 @@ static void audioThreadFunc(void *arg) {
 	ndspChnSetFormat(channel, NDSP_FORMAT_STEREO_PCM16);
 
 	while (!osys->exiting) {
-		osys->delayMillis(100); // Note: Increasing the delay requires a bigger buffer
-
-		time = osys->getMillis(true);
-		sampleLen = (time - lastTime) * 22 * 4; // sampleRate / 1000 * channelCount * sizeof(int16);
-		lastTime = time;
+		svcSleepThread(5000 * 1000); // Wake up the thread every 5 ms
 
-		if (!osys->sleeping && sampleLen > 0) {
-			bufferIndex++;
-			bufferIndex %= bufferCount;
-			ndspWaveBuf *buf = &buffers[bufferIndex];
+		if (osys->sleeping) continue;
 
-			buf->nsamples = mixer->mixCallback(buf->data_adpcm, sampleLen);
+		ndspWaveBuf *buf = &buffers[bufferIndex];
+		if (buf->status == NDSP_WBUF_FREE || buf->status == NDSP_WBUF_DONE) {
+			buf->nsamples = mixer->mixCallback(buf->data_adpcm, bufferSize);
 			if (buf->nsamples > 0) {
 				DSP_FlushDataCache(buf->data_vaddr, bufferSize);
 				ndspChnWaveBufAdd(channel, buf);
 			}
+
+			bufferIndex++;
+			bufferIndex %= bufferCount;
 		}
 	}
 
-	for (i = 0; i < bufferCount; ++i)
-		linearFree(buffers[i].data_pcm8);
+	for (int i = 0; i < bufferCount; ++i)
+		linearFree(buffers[i].data_pcm16);
 }
 
 void OSystem_3DS::initAudio() {


Commit: 6bff952050d51cd38a8d8d8431f41b756b9a78c2
    https://github.com/scummvm/scummvm/commit/6bff952050d51cd38a8d8d8431f41b756b9a78c2
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:14:48+01:00

Commit Message:
GUI: Fix pressing escape erroneously saving the changes in the options dialog

Pressing escape sets the dialog result to -1.

(cherry picked from commit 358d95e9096dd80203c8417e3c099fe7b063de14)

Changed paths:
    gui/options.cpp


diff --git a/gui/options.cpp b/gui/options.cpp
index 8e44551..cac682c 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -759,7 +759,7 @@ void OptionsDialog::apply() {
 }
 
 void OptionsDialog::close() {
-	if (getResult())
+	if (getResult() > 0)
 		apply();
 
 	Dialog::close();


Commit: 98f3a4e64072676487c82c153fc6b3cf74e7c3b3
    https://github.com/scummvm/scummvm/commit/98f3a4e64072676487c82c153fc6b3cf74e7c3b3
Author: Michael Ball (ballm4788 at gmail.com)
Date: 2019-11-07T11:15:41+01:00

Commit Message:
3DS: Add files to be removed by 3ds_clean in 3ds.mk:
backends/platform/3ds/shader.shbin (byproduct of "make"),
backends/platform/3ds/shader_shbin.h (byproduct of "make"),
$(TARGET).smdh (aka scummvm.smdh, byproduct of "make scummvm.3dsx"),
$(TARGET).bnr (aka scummvm.bnr, byproduct of "make scummvm.cia")

(cherry picked from commit 2d2a46ac9a224530846cc42d6afe6adf37f9f73a)

Changed paths:
    backends/platform/3ds/3ds.mk


diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index dcb7b5e..0466722 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -19,7 +19,11 @@ LDFLAGS  += -specs=3dsx.specs $(ARCH) -L$(DEVKITPRO)/libctru/lib -L$(DEVKITPRO)/
 clean: clean_3ds
 
 clean_3ds:
+	$(RM) backends/platform/3ds/shader.shbin
+	$(RM) backends/platform/3ds/shader_shbin.h
+	$(RM) $(TARGET).smdh
 	$(RM) $(TARGET).3dsx
+	$(RM) $(TARGET).bnr
 	$(RM) $(TARGET).cia
 	$(RM) -rf romfs
 


Commit: 753d26e5733722457e050da7c76c70dce57dbb96
    https://github.com/scummvm/scummvm/commit/753d26e5733722457e050da7c76c70dce57dbb96
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:15:41+01:00

Commit Message:
3DS: Fix hi-color cursors

(cherry picked from commit 755afd82f43b7c27bb48c2ce8e4b2dcd55b7422f)

Changed paths:
    backends/platform/3ds/osystem-graphics.cpp


diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 2bad1f5..9dd9c5a 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -481,7 +481,7 @@ void OSystem_3DS::setMouseCursor(const void *buf, uint w, uint h,
 	}
 
 	if ( w != 0 && h != 0 ) {
-		_cursor.copyRectToSurface(buf, w, 0, 0, w, h);
+		_cursor.copyRectToSurface(buf, w * _pfCursor.bytesPerPixel, 0, 0, w, h);
 	}
 
 	flushCursor();
@@ -496,6 +496,29 @@ void OSystem_3DS::setCursorPalette(const byte *colors, uint start, uint num) {
 	flushCursor();
 }
 
+namespace {
+template<typename SrcColor>
+void applyKeyColor(Graphics::Surface *src, Graphics::Surface *dst, const SrcColor keyColor) {
+	assert(dst->format.bytesPerPixel == 4);
+	assert((dst->w >= src->w) && (dst->h >= src->h));
+
+	for (uint y = 0; y < src->h; ++y) {
+		SrcColor *srcPtr = (SrcColor *)src->getBasePtr(0, y);
+		uint32 *dstPtr = (uint32 *)dst->getBasePtr(0, y);
+
+		for (uint x = 0; x < src->w; ++x) {
+			const SrcColor color = *srcPtr++;
+
+			if (color == keyColor) {
+				*dstPtr = 0;
+			}
+
+			dstPtr++;
+		}
+	}
+}
+} // End of anonymous namespace
+
 void OSystem_3DS::flushCursor() {
 	if (_cursor.getPixels()) {
 		Graphics::Surface *converted = _cursor.convertTo(_pfGameTexture, _cursorPaletteEnabled ? _cursorPalette : _palette);
@@ -505,17 +528,11 @@ void OSystem_3DS::flushCursor() {
 		delete converted;
 
 		if (_pfCursor.bytesPerPixel == 1) {
-			uint* dest = (uint*) _cursorTexture.getPixels();
-			byte* src = (byte*) _cursor.getPixels();
-			for (int y = 0; y < _cursor.h; ++y) {
-				for (int x = 0; x < _cursor.w; ++x) {
-					if (*src++ == _cursorKeyColor)
-						*dest++ = 0;
-					else
-						dest++;
-				}
-				dest += _cursorTexture.w - _cursorTexture.actualWidth;
-			}
+			applyKeyColor<byte>(&_cursor, &_cursorTexture, _cursorKeyColor);
+		} else if (_pfCursor.bytesPerPixel == 2) {
+			applyKeyColor<uint16>(&_cursor, &_cursorTexture, _cursorKeyColor);
+		} else if (_pfCursor.bytesPerPixel == 4) {
+			applyKeyColor<uint32>(&_cursor, &_cursorTexture, _cursorKeyColor);
 		}
 	}
 }


Commit: be05540528ff548df12a740e189f379dc30a0bfc
    https://github.com/scummvm/scummvm/commit/be05540528ff548df12a740e189f379dc30a0bfc
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:16:15+01:00

Commit Message:
3DS: Upload the textures to VRAM in a separate frame

So rendering waits for the textures to finish uploading before using
them. Fixes glitchy mouse pointer in Riven.

(cherry picked from commit e9b1df95ffeff6f63d29786060bad70f1f89cea0)

Changed paths:
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/sprite.cpp
    backends/platform/3ds/sprite.h


diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 9dd9c5a..c143417 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -265,13 +265,22 @@ void OSystem_3DS::unlockScreen() {
 }
 
 void OSystem_3DS::updateScreen() {
-
 	if (sleeping || exiting)
 		return;
 
 // 	updateFocus();
 
-	C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
+	C3D_FrameBegin(0);
+		_gameTopTexture.transfer();
+		if (_overlayVisible) {
+			_overlay.transfer();
+		}
+		if (_cursorVisible && config.showCursor) {
+			_cursorTexture.transfer();
+		}
+	C3D_FrameEnd(0);
+
+	C3D_FrameBegin(0);
 		// Render top screen
 		C3D_RenderTargetClear(_renderTargetTop, C3D_CLEAR_ALL, 0x00000000, 0);
 		C3D_FrameDrawOn(_renderTargetTop);
@@ -279,7 +288,6 @@ void OSystem_3DS::updateScreen() {
 			C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionTop);
 			C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameTopTexture.getMatrix());
 			_gameTopTexture.render();
-			_gameTopTexture.render();
 			if (_overlayVisible && config.screen == kScreenTop) {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
 				_overlay.render();
@@ -297,7 +305,6 @@ void OSystem_3DS::updateScreen() {
 			C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _projectionLocation, &_projectionBottom);
 			C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _gameBottomTexture.getMatrix());
 			_gameTopTexture.render();
-			_gameTopTexture.render();
 			if (_overlayVisible) {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
 				_overlay.render();
diff --git a/backends/platform/3ds/sprite.cpp b/backends/platform/3ds/sprite.cpp
index 78082f3..b2785e2 100644
--- a/backends/platform/3ds/sprite.cpp
+++ b/backends/platform/3ds/sprite.cpp
@@ -100,13 +100,15 @@ void Sprite::convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte
 	//
 }
 
-void Sprite::render() {
+void Sprite::transfer() {
 	if (dirtyPixels) {
 		dirtyPixels = false;
 		GSPGPU_FlushDataCache(pixels, w * h * format.bytesPerPixel);
 		C3D_SyncDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), TEXTURE_TRANSFER_FLAGS);
-// 		gspWaitForPPF();
 	}
+}
+
+void Sprite::render() {
 	C3D_TexBind(0, &texture);
 
 	C3D_BufInfo *bufInfo = C3D_GetBufInfo();
diff --git a/backends/platform/3ds/sprite.h b/backends/platform/3ds/sprite.h
index 35c048c..1e9c0b4 100644
--- a/backends/platform/3ds/sprite.h
+++ b/backends/platform/3ds/sprite.h
@@ -46,6 +46,7 @@ public:
 	void create(uint16 width, uint16 height, const Graphics::PixelFormat &format);
 	void free();
 	void convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte *palette = 0);
+	void transfer();
 	void render();
 	void clear(uint32 color = 0);
 	void markDirty(){ dirtyPixels = true; }


Commit: e4ef9d9379e4b48e6b7f1ef3316abed560ebe5fe
    https://github.com/scummvm/scummvm/commit/e4ef9d9379e4b48e6b7f1ef3316abed560ebe5fe
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:16:15+01:00

Commit Message:
MOHAWK: MYST: Fix misuse of OSystem::fillScreen

OSystem::fillScreen is documented to only accept values between 0 and
255, and thus cannot be sanely used for hi-color graphics. This is
probably an unfortunate leftover of when hi-color support was added.

Fixes videos playing on a white background on the 3DS.

(cherry picked from commit d810bb7451ba5335a3f3ff7cb4b7b8ebd529b446)

Changed paths:
    engines/mohawk/myst_graphics.cpp


diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp
index 55a92b2..b5222c6 100644
--- a/engines/mohawk/myst_graphics.cpp
+++ b/engines/mohawk/myst_graphics.cpp
@@ -892,10 +892,15 @@ void MystGraphics::replaceImageWithRect(uint16 destImage, uint16 sourceImage, co
 }
 
 void MystGraphics::clearScreen() {
-	if (_vm->getFeatures() & GF_ME)
-		_vm->_system->fillScreen(_pixelFormat.RGBToColor(0, 0, 0));
-	else
-		_vm->_system->fillScreen(0);
+	Graphics::Surface *screen = _vm->_system->lockScreen();
+	if (screen) {
+		if (_vm->getFeatures() & GF_ME)
+			screen->fillRect(_viewport, _pixelFormat.RGBToColor(0, 0, 0));
+		else
+			screen->fillRect(_viewport, 0);
+
+		_vm->_system->unlockScreen();
+	}
 }
 
 } // End of namespace Mohawk


Commit: 11a056f461327a67c471bc62b89eb8268fb0c849
    https://github.com/scummvm/scummvm/commit/11a056f461327a67c471bc62b89eb8268fb0c849
Author: Michael Ball (ballm4788 at gmail.com)
Date: 2019-11-07T11:16:54+01:00

Commit Message:
3DS: Set 'scummvm.romfs' to be removed by 3ds_clean in 3ds.mk

(cherry picked from commit 8b201aa8d6e7bf5ffc80b165f57cabcbed3ecde1)

Changed paths:
    backends/platform/3ds/3ds.mk


diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index 0466722..99303f5 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -24,6 +24,7 @@ clean_3ds:
 	$(RM) $(TARGET).smdh
 	$(RM) $(TARGET).3dsx
 	$(RM) $(TARGET).bnr
+	$(RM) $(TARGET).romfs
 	$(RM) $(TARGET).cia
 	$(RM) -rf romfs
 


Commit: f4e1d1bca0f9b0ed6cc61c1bd05e559ccc485b45
    https://github.com/scummvm/scummvm/commit/f4e1d1bca0f9b0ed6cc61c1bd05e559ccc485b45
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:16:54+01:00

Commit Message:
3DS: Avoid stat calls in DrivePOSIXFilesystemNode

(cherry picked from commit 8fb57967d75b5ef9911fbbbf15eb25b43458c997)

Changed paths:
    backends/fs/posix-drives/posix-drives-fs.cpp
    backends/fs/posix-drives/posix-drives-fs.h
    backends/fs/posix/posix-fs.h


diff --git a/backends/fs/posix-drives/posix-drives-fs.cpp b/backends/fs/posix-drives/posix-drives-fs.cpp
index 683ab19..d48792e 100644
--- a/backends/fs/posix-drives/posix-drives-fs.cpp
+++ b/backends/fs/posix-drives/posix-drives-fs.cpp
@@ -53,10 +53,8 @@ DrivePOSIXFilesystemNode::DrivePOSIXFilesystemNode(const DrivesArray &drives) :
 	_isValid = false;
 }
 
-AbstractFSNode *DrivePOSIXFilesystemNode::getChild(const Common::String &n) const {
-	if (!_isPseudoRoot) {
-		return POSIXFilesystemNode::getChild(n);
-	}
+DrivePOSIXFilesystemNode *DrivePOSIXFilesystemNode::getChildWithKnownType(const Common::String &n, bool isDirectory) const {
+	assert(_isDirectory);
 
 	// Make sure the string contains no slashes
 	assert(!n.contains('/'));
@@ -66,7 +64,21 @@ AbstractFSNode *DrivePOSIXFilesystemNode::getChild(const Common::String &n) cons
 		newPath += '/';
 	newPath += n;
 
-	return makeNode(newPath);
+	DrivePOSIXFilesystemNode *child = new DrivePOSIXFilesystemNode(_drives);
+	child->_path = newPath;
+	child->_isValid = true;
+	child->_isPseudoRoot = false;
+	child->_isDirectory = isDirectory;
+	child->_displayName = n;
+
+	return child;
+}
+
+AbstractFSNode *DrivePOSIXFilesystemNode::getChild(const Common::String &n) const {
+	DrivePOSIXFilesystemNode *child = getChildWithKnownType(n, false);
+	child->setFlags();
+
+	return child;
 }
 
 bool DrivePOSIXFilesystemNode::getChildren(AbstractFSList &list, AbstractFSNode::ListMode mode, bool hidden) const {
@@ -96,7 +108,16 @@ bool DrivePOSIXFilesystemNode::getChildren(AbstractFSList &list, AbstractFSNode:
 				continue;
 			}
 
-			AbstractFSNode *child = getChild(dp->d_name);
+			AbstractFSNode *child = nullptr;
+
+#if !defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
+			if (dp->d_type == DT_DIR || dp->d_type == DT_REG) {
+				child = getChildWithKnownType(dp->d_name, dp->d_type == DT_DIR);
+			} else
+#endif
+			{
+				child = getChild(dp->d_name);
+			}
 
 			// Honor the chosen mode
 			if ((mode == Common::FSNode::kListFilesOnly && child->isDirectory()) ||
diff --git a/backends/fs/posix-drives/posix-drives-fs.h b/backends/fs/posix-drives/posix-drives-fs.h
index 43c8942..04d21b4 100644
--- a/backends/fs/posix-drives/posix-drives-fs.h
+++ b/backends/fs/posix-drives/posix-drives-fs.h
@@ -50,6 +50,7 @@ private:
 	bool _isPseudoRoot;
 	const DrivesArray &_drives;
 
+	DrivePOSIXFilesystemNode *getChildWithKnownType(const Common::String &n, bool isDirectory) const;
 	bool isDrive(const Common::String &path) const;
 };
 
diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h
index 9751ab7..6a67a61 100644
--- a/backends/fs/posix/posix-fs.h
+++ b/backends/fs/posix/posix-fs.h
@@ -70,7 +70,7 @@ public:
 	virtual Common::WriteStream *createWriteStream();
 	virtual bool createDirectory();
 
-private:
+protected:
 	/**
 	 * Tests and sets the _isValid and _isDirectory flags, using the stat() function.
 	 */


Commit: 393ce8d0c6f861fa4047a5385c58ef1256e4cc42
    https://github.com/scummvm/scummvm/commit/393ce8d0c6f861fa4047a5385c58ef1256e4cc42
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
NETWORKING: Try loading the CA bundle from DATA_PATH

(cherry picked from commit 6fa7322a6a21e8f5ce5bd976da098761eca1f831)

Changed paths:
    backends/networking/curl/connectionmanager.cpp
    backends/networking/curl/connectionmanager.h
    backends/networking/curl/networkreadstream.cpp


diff --git a/backends/networking/curl/connectionmanager.cpp b/backends/networking/curl/connectionmanager.cpp
index 34a9701..1c399aa 100644
--- a/backends/networking/curl/connectionmanager.cpp
+++ b/backends/networking/curl/connectionmanager.cpp
@@ -26,6 +26,7 @@
 #include "backends/networking/curl/connectionmanager.h"
 #include "backends/networking/curl/networkreadstream.h"
 #include "common/debug.h"
+#include "common/fs.h"
 #include "common/system.h"
 #include "common/timer.h"
 
@@ -98,6 +99,29 @@ uint32 ConnectionManager::getCloudRequestsPeriodInMicroseconds() {
 	return TIMER_INTERVAL * CLOUD_PERIOD;
 }
 
+const char *ConnectionManager::getCaCertPath() {
+#if defined(DATA_PATH)
+	static enum {
+		kNotInitialized,
+		kFileNotFound,
+		kFileExists
+	} state = kNotInitialized;
+
+	if (state == kNotInitialized) {
+		Common::FSNode node(DATA_PATH"/cacert.pem");
+		state = node.exists() ? kFileExists : kFileNotFound;
+	}
+
+	if (state == kFileExists) {
+		return DATA_PATH"/cacert.pem";
+	} else {
+		return nullptr;
+	}
+#else
+	return nullptr;
+#endif
+}
+
 //private goes here:
 
 void connectionsThread(void *ignored) {
diff --git a/backends/networking/curl/connectionmanager.h b/backends/networking/curl/connectionmanager.h
index 6c261b8..a01d115 100644
--- a/backends/networking/curl/connectionmanager.h
+++ b/backends/networking/curl/connectionmanager.h
@@ -118,6 +118,9 @@ public:
 	Common::String urlEncode(Common::String s) const;
 
 	static uint32 getCloudRequestsPeriodInMicroseconds();
+
+	/** Return the path to the CA certificates bundle. */
+	static const char *getCaCertPath();
 };
 
 /** Shortcut for accessing the connection manager. */
diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp
index 59d2a54..e401389 100644
--- a/backends/networking/curl/networkreadstream.cpp
+++ b/backends/networking/curl/networkreadstream.cpp
@@ -88,6 +88,11 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, const byt
 	curl_easy_setopt(_easy, CURLOPT_SSL_VERIFYPEER, 0);
 #endif
 
+	const char *caCertPath = ConnMan.getCaCertPath();
+	if (caCertPath) {
+		curl_easy_setopt(_easy, CURLOPT_CAINFO, caCertPath);
+	}
+
 #if LIBCURL_VERSION_NUM >= 0x072000
 	// CURLOPT_XFERINFOFUNCTION introduced in libcurl 7.32.0
 	// CURLOPT_PROGRESSFUNCTION is used as a backup plan in case older version is used
@@ -144,6 +149,11 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::H
 	curl_easy_setopt(_easy, CURLOPT_SSL_VERIFYPEER, 0);
 #endif
 
+	const char *caCertPath = ConnMan.getCaCertPath();
+	if (caCertPath) {
+		curl_easy_setopt(_easy, CURLOPT_CAINFO, caCertPath);
+	}
+
 #if LIBCURL_VERSION_NUM >= 0x072000
 	// CURLOPT_XFERINFOFUNCTION introduced in libcurl 7.32.0
 	// CURLOPT_PROGRESSFUNCTION is used as a backup plan in case older version is used


Commit: 0e64097576a5984ce453f1d20945e1ce654caeab
    https://github.com/scummvm/scummvm/commit/0e64097576a5984ce453f1d20945e1ce654caeab
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Use DATA_PATH to configure support files location

(cherry picked from commit 2d11974c28b50c5c0a65be71caa4c93be24ab468)

Changed paths:
    backends/platform/3ds/osystem.cpp
    configure


diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index 8f896ad..041685d 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -130,7 +130,7 @@ Common::String OSystem_3DS::getDefaultConfigFileName() {
 }
 
 void OSystem_3DS::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
-	s.add("RomFS", new Common::FSDirectory("romfs:/"), priority);
+	s.add("RomFS", new Common::FSDirectory(DATA_PATH"/"), priority);
 }
 
 uint32 OSystem_3DS::getMillis(bool skipRecord) {
diff --git a/configure b/configure
index 4575a18..71580d7 100755
--- a/configure
+++ b/configure
@@ -1532,6 +1532,12 @@ case $_host in
 	_host_os=3ds
 	_host_cpu=arm
 	_host_alias=arm-none-eabi
+
+	test "x$prefix" = xNONE && prefix=romfs:
+
+	datarootdir='${prefix}'
+	datadir='${datarootdir}'
+	docdir='${prefix}/doc'
 	;;
 android | android-arm | android-v7a | android-arm-v7a | ouya)
 	_host_os=android


Commit: c159f7e1f5a896de986e624f2f6613ff7de1e18a
    https://github.com/scummvm/scummvm/commit/c159f7e1f5a896de986e624f2f6613ff7de1e18a
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Implement cloud sync support

(cherry picked from commit 036d61cbd62dc7907f4eeb36764bef9f794588f4)

Changed paths:
    backends/platform/3ds/3ds.mk
    backends/platform/3ds/README.md
    backends/platform/3ds/main.cpp
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h
    backends/platform/3ds/sprite.cpp


diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index 99303f5..3e3eb4c 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -28,7 +28,7 @@ clean_3ds:
 	$(RM) $(TARGET).cia
 	$(RM) -rf romfs
 
-romfs: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD)
+romfs: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_3DS_EXTRA_FILES)
 	@rm -rf romfs
 	@mkdir -p romfs
 	@cp $(DIST_FILES_THEMES) romfs/
@@ -41,6 +41,9 @@ endif
 ifdef DIST_FILES_VKEYBD
 	@cp $(DIST_FILES_VKEYBD) romfs/
 endif
+ifdef DIST_3DS_EXTRA_FILES
+	@cp -a $(DIST_3DS_EXTRA_FILES) romfs/
+endif
 
 $(TARGET).smdh: $(APP_ICON)
 	@smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
@@ -49,7 +52,7 @@ $(TARGET).smdh: $(APP_ICON)
 $(TARGET).3dsx: $(EXECUTABLE) $(TARGET).smdh romfs
 	@3dsxtool $< $@ --smdh=$(TARGET).smdh --romfs=romfs
 	@echo built ... $(notdir $@)
-	
+
 $(TARGET).bnr: $(APP_BANNER_IMAGE) $(APP_BANNER_AUDIO)
 	@bannertool makebanner -o $@ -i $(APP_BANNER_IMAGE) -a $(APP_BANNER_AUDIO)
 	@echo built ... $(notdir $@)
diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index 95ce0f4..f0cf1b6 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -202,6 +202,12 @@ Note: In more recent codebases of ScummVM, you may or may not need to set the fo
 ```$ export PKG_CONFIG_LIBDIR=$PORTLIBS/lib/pkgconfig```
 See above for $PORTLIBS.
 
+ScummVM doesn't provide the CA certificates bundle required by the cloud synchronization features.
+You need to download it from the curl website: https://curl.haxx.se/ca/cacert.pem, and instruct
+the build system to package it in the binary:
+```$ export DIST_3DS_EXTRA_FILES=/path/to/cacert.pem```
+The name of the file must be `cacert.pem`.
+
 From the root of the scummvm repository:
 ```
  $ ./configure --host=3ds
diff --git a/backends/platform/3ds/main.cpp b/backends/platform/3ds/main.cpp
index ce549b6..18df14b 100644
--- a/backends/platform/3ds/main.cpp
+++ b/backends/platform/3ds/main.cpp
@@ -22,6 +22,7 @@
 
 #include "osystem.h"
 #include <3ds.h>
+#include <malloc.h>
 
 int main(int argc, char *argv[]) {
 	// Initialize basic libctru stuff
@@ -31,6 +32,12 @@ int main(int argc, char *argv[]) {
 	osSetSpeedupEnable(true);
 // 	consoleInit(GFX_TOP, NULL);
 
+#ifdef USE_LIBCURL
+	const uint32 soc_sharedmem_size = 0x10000;
+	void *soc_sharedmem = memalign(0x1000, soc_sharedmem_size);
+	socInit((u32 *)soc_sharedmem, soc_sharedmem_size);
+#endif
+
 	g_system = new _3DS::OSystem_3DS();
 	assert(g_system);
 
@@ -51,6 +58,9 @@ int main(int argc, char *argv[]) {
 		gspLcdExit();
 	}
 
+#ifdef USE_LIBCURL
+	socExit();
+#endif
 	romfsExit();
 	cfguExit();
 	gfxExit();
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index c143417..2ae32f8 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -86,6 +86,7 @@ void OSystem_3DS::destroyGraphics() {
 	_gameTopTexture.free();
 	_gameBottomTexture.free();
 	_overlay.free();
+	_activityIcon.free();
 
 	shaderProgramFree(&_program);
 	DVLB_Free(_dvlb);
@@ -278,6 +279,7 @@ void OSystem_3DS::updateScreen() {
 		if (_cursorVisible && config.showCursor) {
 			_cursorTexture.transfer();
 		}
+		_activityIcon.transfer();
 	C3D_FrameEnd(0);
 
 	C3D_FrameBegin(0);
@@ -292,6 +294,11 @@ void OSystem_3DS::updateScreen() {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
 				_overlay.render();
 			}
+			if (_activityIcon.getPixels() && config.screen == kScreenTop) {
+				_activityIcon.setPosition(400 - _activityIcon.actualWidth, 0);
+				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _activityIcon.getMatrix());
+				_activityIcon.render();
+			}
 			if (_cursorVisible && config.showCursor && config.screen == kScreenTop) {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
 				_cursorTexture.render();
@@ -309,6 +316,11 @@ void OSystem_3DS::updateScreen() {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _overlay.getMatrix());
 				_overlay.render();
 			}
+			if (_activityIcon.getPixels()) {
+				_activityIcon.setPosition(320 - _activityIcon.actualWidth, 0);
+				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _activityIcon.getMatrix());
+				_activityIcon.render();
+			}
 			if (_cursorVisible && config.showCursor) {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
 				_cursorTexture.render();
@@ -434,6 +446,22 @@ void OSystem_3DS::copyRectToOverlay(const void *buf, int pitch, int x,
 	_overlay.markDirty();
 }
 
+void OSystem_3DS::displayActivityIconOnOSD(const Graphics::Surface *icon) {
+	if (!icon) {
+		_activityIcon.free();
+	} else {
+		if (!_activityIcon.getPixels() || icon->w != _activityIcon.w || icon->h != _activityIcon.h) {
+			_activityIcon.create(icon->w, icon->h, _pfGameTexture);
+		}
+
+		Graphics::Surface *converted = icon->convertTo(_pfGameTexture);
+		_activityIcon.copyRectToSurface(*converted, 0, 0, Common::Rect(converted->w, converted->h));
+		_activityIcon.markDirty();
+		converted->free();
+		delete converted;
+	}
+}
+
 int16 OSystem_3DS::getOverlayHeight() {
 	return 240;
 }
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index 041685d..e1186e4 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -193,7 +193,7 @@ void OSystem_3DS::fatalError() {
 }
 
 void OSystem_3DS::logMessage(LogMessageType::Type type, const char *message) {
-	printf("3DS log: %s\n", message);
+	printf("%s", message);
 }
 
 } // namespace _3DS
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 28d21c3..89271e1 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -126,6 +126,7 @@ public:
 	virtual int16 getOverlayHeight();
 	virtual int16 getOverlayWidth();
 	virtual void displayMessageOnOSD(const char *msg);
+	void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
 
 	bool showMouse(bool visible);
 	void warpMouse(int x, int y);
@@ -176,6 +177,7 @@ private:
 	Sprite _gameTopTexture;
 	Sprite _gameBottomTexture;
 	Sprite _overlay;
+	Sprite _activityIcon;
 
 	int _screenShakeOffset;
 	bool _overlayVisible;
diff --git a/backends/platform/3ds/sprite.cpp b/backends/platform/3ds/sprite.cpp
index b2785e2..1f2c72e 100644
--- a/backends/platform/3ds/sprite.cpp
+++ b/backends/platform/3ds/sprite.cpp
@@ -101,7 +101,7 @@ void Sprite::convertToInPlace(const Graphics::PixelFormat &dstFormat, const byte
 }
 
 void Sprite::transfer() {
-	if (dirtyPixels) {
+	if (pixels && dirtyPixels) {
 		dirtyPixels = false;
 		GSPGPU_FlushDataCache(pixels, w * h * format.bytesPerPixel);
 		C3D_SyncDisplayTransfer((u32*)pixels, GX_BUFFER_DIM(w, h), (u32*)texture.data, GX_BUFFER_DIM(w, h), TEXTURE_TRANSFER_FLAGS);
@@ -123,15 +123,19 @@ void Sprite::clear(uint32 color) {
 }
 
 void Sprite::setScale (float x, float y) {
-	scaleX = x;
-	scaleY = y;
-	dirtyMatrix = true;
+	if (x != scaleX || y != scaleY) {
+		scaleX = x;
+		scaleY = y;
+		dirtyMatrix = true;
+	}
 }
 
 void Sprite::setPosition(int x, int y) {
-	posX = x;
-	posY = y;
-	dirtyMatrix = true;
+	if (x != posX || y != posY) {
+		posX = x;
+		posY = y;
+		dirtyMatrix = true;
+	}
 }
 
 C3D_Mtx* Sprite::getMatrix() {


Commit: 6e8f7a81193400fef4bf54a53748636884f69f71
    https://github.com/scummvm/scummvm/commit/6e8f7a81193400fef4bf54a53748636884f69f71
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
PS3: Implement the cloud synchronization features

(cherry picked from commit 0b74f984de1847e7b76e83592486fc7154f78c85)

Changed paths:
    backends/platform/sdl/ps3/ps3-main.cpp
    backends/platform/sdl/ps3/ps3.mk
    dists/ps3/readme-ps3.md


diff --git a/backends/platform/sdl/ps3/ps3-main.cpp b/backends/platform/sdl/ps3/ps3-main.cpp
index 2777497..23dc7402 100644
--- a/backends/platform/sdl/ps3/ps3-main.cpp
+++ b/backends/platform/sdl/ps3/ps3-main.cpp
@@ -20,14 +20,21 @@
  *
  */
 
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
 #include "common/scummsys.h"
 
 #include "backends/platform/sdl/ps3/ps3.h"
 #include "backends/plugins/sdl/sdl-provider.h"
 #include "base/main.h"
 
+#include <net/net.h>
+
 int main(int argc, char *argv[]) {
 
+#ifdef USE_LIBCURL
+	netInitialize();
+#endif
+
 	// Create our OSystem instance
 	g_system = new OSystem_PS3();
 	assert(g_system);
@@ -45,5 +52,9 @@ int main(int argc, char *argv[]) {
 	// Free OSystem
 	g_system->destroy();
 
+#ifdef USE_LIBCURL
+	netDeinitialize();
+#endif
+
 	return res;
 }
diff --git a/backends/platform/sdl/ps3/ps3.mk b/backends/platform/sdl/ps3/ps3.mk
index d660281..94885d2 100644
--- a/backends/platform/sdl/ps3/ps3.mk
+++ b/backends/platform/sdl/ps3/ps3.mk
@@ -15,6 +15,9 @@ endif
 ifdef DIST_FILES_VKEYBD
 	cp $(DIST_FILES_VKEYBD) ps3pkg/USRDIR/data/
 endif
+ifdef DIST_PS3_EXTRA_FILES
+	@cp -a $(DIST_PS3_EXTRA_FILES) ps3pkg/USRDIR/data/
+endif
 	cp $(DIST_FILES_DOCS) ps3pkg/USRDIR/doc/
 	cp $(srcdir)/dists/ps3/readme-ps3.md ps3pkg/USRDIR/doc/
 	cp $(srcdir)/dists/ps3/ICON0.PNG ps3pkg/
diff --git a/dists/ps3/readme-ps3.md b/dists/ps3/readme-ps3.md
index 698c925..e4d39df 100644
--- a/dists/ps3/readme-ps3.md
+++ b/dists/ps3/readme-ps3.md
@@ -51,6 +51,10 @@ The dependencies needed to build it are :
 - SDL from https://bitbucket.org/bgK/sdl_psl1ght
 - ScummVM from https://github.com/scummvm/scummvm
 
+ScummVM doesn't provide the CA certificates bundle required by the cloud synchronization features.
+It can be downloaded from the curl website: https://curl.haxx.se/ca/cacert.pem, and packaged in the binary using:
+```$ export DIST_PS3_EXTRA_FILES=/path/to/cacert.pem```
+
 Once all the dependencies are correctly setup, an installable package can be obtained from source by issuing the following command :
 
 ./configure --host=ps3 && make ps3pkg


Commit: f81e50e549a0cbc40cd59e01486c0bea575955be
    https://github.com/scummvm/scummvm/commit/f81e50e549a0cbc40cd59e01486c0bea575955be
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Add a make rule for a distributable package

(cherry picked from commit cc721bced5d93024fed62822d8dbded5c85d4056)

Changed paths:
    backends/platform/3ds/3ds.mk


diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index 3e3eb4c..52a1b04 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -14,7 +14,7 @@ CXXFLAGS += -std=gnu++11
 ASFLAGS  += -mfloat-abi=hard
 LDFLAGS  += -specs=3dsx.specs $(ARCH) -L$(DEVKITPRO)/libctru/lib -L$(DEVKITPRO)/portlibs/3ds/lib
 
-.PHONY: clean_3ds
+.PHONY: clean_3ds dist_3ds
 
 clean: clean_3ds
 
@@ -27,6 +27,7 @@ clean_3ds:
 	$(RM) $(TARGET).romfs
 	$(RM) $(TARGET).cia
 	$(RM) -rf romfs
+	$(RM) -rf dist_3ds
 
 romfs: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_3DS_EXTRA_FILES)
 	@rm -rf romfs
@@ -65,6 +66,14 @@ $(TARGET).cia: $(EXECUTABLE) $(APP_RSF) $(TARGET).smdh $(TARGET).bnr $(TARGET).r
 	@makerom -f cia -target t -exefslogo -o $@ -elf $(EXECUTABLE) -rsf $(APP_RSF) -banner $(TARGET).bnr -icon $(TARGET).smdh -romfs $(TARGET).romfs
 	@echo built ... $(notdir $@)
 
+dist_3ds: $(TARGET).cia $(TARGET).3dsx $(DIST_FILES_DOCS)
+	@rm -rf dist_3ds
+	@mkdir -p dist_3ds
+	@cp $(TARGET).3dsx $(TARGET).cia dist_3ds/
+	@cp $(DIST_FILES_DOCS) dist_3ds/
+	@cp $(srcdir)/backends/platform/3ds/README.md dist_3ds/README-3DS.md
+	@echo built ... $(notdir $@)
+
 #---------------------------------------------------------------------------------
 # rules for assembling GPU shaders
 #---------------------------------------------------------------------------------


Commit: 3ea36876db16c43ac1b38eda9316256a36044e05
    https://github.com/scummvm/scummvm/commit/3ea36876db16c43ac1b38eda9316256a36044e05
Author: Michael Ball (ballm4788 at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Implement magnify mode toggle on L and move keyboard to Y/DRIGHT

(cherry picked from commit 78de5724047f56bd3ecbfb9ab423bb6c943f6589)

Changed paths:
    backends/platform/3ds/README.md
    backends/platform/3ds/osystem-events.cpp
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h
    backends/platform/3ds/sprite.cpp
    backends/platform/3ds/sprite.h


diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index f0cf1b6..ee0aaaa 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -12,6 +12,7 @@ Table of Contents:
  * 2.1 Default key mappings
  * 2.2 Hover mode
  * 2.3 Drag mode
+ * 2.4 Magnify mode
 
 3.0) Supported Games
 
@@ -64,7 +65,8 @@ depending on if you're right or left-handed.
 | A / D-left | Left-click                     |
 | X / D-up   | Right-click                    |
 | B / D-down | ESC (skips cutscenes and such) |
-| L          | Use virtual keyboard           |
+| Y / D-right| Use virtual keyboard           |
+| L          | Toggle magnify mode on/off     |
 | R          | Toggle hover/drag modes        |
 | Start      | Open game menu                 |
 | Select     | Open 3DS config menu           |
@@ -81,6 +83,31 @@ mouse button without using buttons mapped to right/left-click.
 Every time you touch and release the touchscreen, you are simulating the click and
 release of the mouse buttons. At the moment, this is only a left-click.
 
+2.4) Magnify mode
+-----------------
+Due to the low resolutions of the 3DS's two screens (400x240 for the top, and 320x240
+for the bottom), games that run at a higher resolution will inevitably lose some visual
+detail from being scaled down. This can result in situations where essential information
+is undiscernable, such as text. Magnify mode increases the scale factor of the top screen
+back to 1; the bottom screen remains unchanged. The touchscreen can then be used to change
+which part of the game display is being magnified. This can all be done even in situations
+where the cursor is disabled, such as during full-motion video (FMV) segments.
+
+When activating magnify mode, touchscreen controls are automatically switched to hover
+mode; this is to reduce the risk of the user accidentally inputting a click when changing
+the magnified area via dragging the stylus. Clicking can still be done at will as in normal
+hover mode. Turning off magnify mode will revert controls back to what was being used
+previously (ex: if drag mode was in use prior to activating magnify mode, drag mode will
+be reactivated upon exiting magnify mode), as well as restore the top screen's previous
+scale factor.
+
+Currently magnify mode can only be used when the following conditions are met:
+ - In the 3DS config menu, "Use Screen" is set to "Both"
+ - A game is currently being played
+ - The horizontal and/or vertical resolution in-game is greater than that of the top screen
+
+Magnify mode cannot be used in the Launcher menu.
+
 3.0) Supported Games
 --------------------
 The full game engine compatibility list can be found here:
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index de0f584..0e635f0 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -33,6 +33,7 @@ namespace _3DS {
 
 static Common::Mutex *eventMutex;
 static InputMode inputMode = MODE_DRAG;
+static InputMode savedInputMode = MODE_DRAG;
 static aptHookCookie cookie;
 static bool optionMenuOpening = false;
 static Common::String messageOSD;
@@ -146,13 +147,41 @@ static void eventThreadFunc(void *arg) {
 		}
 
 		// Button events
+		if (keysPressed & KEY_L) {
+			if (osys->getWidth() >= 400 || osys->getHeight() >= 240) {
+				if (osys->getMagnifyMode() == MODE_MAGOFF) {
+					osys->setMagnifyMode(MODE_MAGON);
+					if (inputMode == MODE_DRAG) {
+						inputMode = MODE_HOVER;
+						osys->displayMessageOnOSD("Magnify Mode On. Switching to Hover Mode...");
+					} else
+						osys->displayMessageOnOSD("Magnify Mode On");
+				} else {
+					osys->setMagnifyMode(MODE_MAGOFF);
+					osys->updateSize();
+					if (savedInputMode == MODE_DRAG) {
+						inputMode = savedInputMode;
+						osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode...");
+					} else
+						osys->displayMessageOnOSD("Magnify Mode Off");
+				}
+			} else {
+				if (osys->getWidth() == 0 || osys->getHeight() == 0) {
+					osys->displayMessageOnOSD("Magnify Mode cannot be activated in Launcher.");
+				} else
+					osys->displayMessageOnOSD("In-game resolution too small to magnify.");
+			}
+		}
 		if (keysPressed & KEY_R) {
 			if (inputMode == MODE_DRAG) {
-				inputMode = MODE_HOVER;
+				inputMode = savedInputMode = MODE_HOVER;
 				osys->displayMessageOnOSD("Hover Mode");
 			} else {
-				inputMode = MODE_DRAG;
-				osys->displayMessageOnOSD("Drag Mode");
+				if (osys->getMagnifyMode() == MODE_MAGOFF) {
+					inputMode = savedInputMode = MODE_DRAG;
+					osys->displayMessageOnOSD("Drag Mode");
+				} else
+					osys->displayMessageOnOSD("Cannot Switch to Drag Mode while Magnify Mode is On");
 			}
 		}
 		if (keysPressed & KEY_A || keysPressed & KEY_DLEFT || keysReleased & KEY_A || keysReleased & KEY_DLEFT) {
@@ -165,6 +194,16 @@ static void eventThreadFunc(void *arg) {
 				event.type = Common::EVENT_LBUTTONUP;
 			pushEventQueue(eventQueue, event);
 		}
+		if (keysPressed & KEY_B || keysReleased & KEY_B || keysPressed & KEY_DDOWN || keysReleased & KEY_DDOWN) {
+			if (keysPressed & KEY_B || keysPressed & KEY_DDOWN)
+				event.type = Common::EVENT_KEYDOWN;
+			else
+				event.type = Common::EVENT_KEYUP;
+			event.kbd.keycode = Common::KEYCODE_ESCAPE;
+			event.kbd.ascii = Common::ASCII_ESCAPE;
+			event.kbd.flags = 0;
+			pushEventQueue(eventQueue, event);
+		}
 		if (keysPressed & KEY_X || keysPressed & KEY_DUP || keysReleased & KEY_X || keysReleased & KEY_DUP) {
 			// SIMULATE RIGHT CLICK
 			event.mouse.x = lastTouch.px;
@@ -175,7 +214,7 @@ static void eventThreadFunc(void *arg) {
 				event.type = Common::EVENT_RBUTTONUP;
 			pushEventQueue(eventQueue, event);
 		}
-		if (keysPressed & KEY_L) {
+		if (keysPressed & KEY_Y || keysPressed & KEY_DRIGHT) {
 			event.type = Common::EVENT_VIRTUAL_KEYBOARD;
 			pushEventQueue(eventQueue, event);
 		}
@@ -187,15 +226,18 @@ static void eventThreadFunc(void *arg) {
 			if (!optionMenuOpened)
 				optionMenuOpening = true;
 		}
-		if (keysPressed & KEY_B || keysReleased & KEY_B || keysPressed & KEY_DDOWN || keysReleased & KEY_DDOWN) {
-			if (keysPressed & KEY_B || keysPressed & KEY_DDOWN)
-				event.type = Common::EVENT_KEYDOWN;
-			else
-				event.type = Common::EVENT_KEYUP;
-			event.kbd.keycode = Common::KEYCODE_ESCAPE;
-			event.kbd.ascii = Common::ASCII_ESCAPE;
-			event.kbd.flags = 0;
-			pushEventQueue(eventQueue, event);
+
+		// If magnify mode is on when returning to Launcher, turn it off
+		if (g_system->getEventManager()->shouldRTL()) {
+			if (osys->getMagnifyMode() == MODE_MAGON) {
+				osys->setMagnifyMode(MODE_MAGOFF);
+				osys->updateSize();
+				if (savedInputMode == MODE_DRAG) {
+					inputMode = savedInputMode;
+					osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode.\nReturning to Launcher...");
+				} else
+					osys->displayMessageOnOSD("Magnify Mode Off. Returning to Launcher...");
+			}
 		}
 
 		// TODO: EVENT_PREDICTIVE_DIALOG
@@ -268,6 +310,10 @@ void OSystem_3DS::transformPoint(touchPosition &point) {
 	}
 }
 
+void OSystem_3DS::setMagnifyMode(MagnifyMode mode) {
+	_magnifyMode = mode;
+}
+
 void OSystem_3DS::displayMessageOnOSD(const char *msg) {
 	messageOSD = msg;
 	showMessageOSD = true;
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 2ae32f8..59ee346 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -149,6 +149,8 @@ void OSystem_3DS::initSize(uint width, uint height,
 	_gameHeight = height;
 	_gameTopTexture.create(width, height, _pfGameTexture);
 	_overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
+	_topHalfWidth = _topWidth / 2;
+	_topHalfHeight = _topHeight / 2;
 
 	if (format) {
 		debug("pixelformat: %d %d %d %d %d", format->bytesPerPixel, format->rBits(), format->gBits(), format->bBits(), format->aBits());
@@ -196,6 +198,8 @@ void OSystem_3DS::updateSize() {
 	}
 	_gameTopTexture.setPosition(_gameTopX, _gameTopY);
 	_gameBottomTexture.setPosition(_gameBottomX, _gameBottomY);
+	_gameTopTexture.setOffset(0, 0);
+	_gameBottomTexture.setOffset(0, 0);
 	if (_overlayVisible)
 		_cursorTexture.setScale(1.f, 1.f);
 	else if (config.screen == kScreenTop)
@@ -273,6 +277,17 @@ void OSystem_3DS::updateScreen() {
 
 	C3D_FrameBegin(0);
 		_gameTopTexture.transfer();
+		if (_magnifyMode == MODE_MAGON) {
+			_topX = (_cursorX < _topHalfWidth) ?
+				0 : ((_cursorX < (_gameWidth - _topHalfWidth)) ?
+				_cursorX - _topHalfWidth : _gameWidth - _topWidth);
+			_topY = (_cursorY < _topHalfHeight) ?
+				0 : ((_cursorY < _gameHeight - _topHalfHeight) ?
+				_cursorY - _topHalfHeight : _gameHeight - _topHeight);
+			_gameTopTexture.setScale(1.f,1.f);
+			_gameTopTexture.setPosition(0,0);
+			_gameTopTexture.setOffset(_topX, _topY);
+		}
 		if (_overlayVisible) {
 			_overlay.transfer();
 		}
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index e1186e4..aa0b3a7 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -72,7 +72,12 @@ OSystem_3DS::OSystem_3DS():
 	_gameBottomY(0),
 	_gameWidth(320),
 	_gameHeight(240),
+	_topX(0),
+	_topY(0),
+	_topWidth(400),
+	_topHeight(240),
 	_overlayVisible(false),
+	_magnifyMode(MODE_MAGOFF),
 	exiting(false),
 	sleeping(false)
 {
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 89271e1..544c900 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -44,6 +44,11 @@ enum {
 	GFX_NEAREST = 1
 };
 
+enum MagnifyMode {
+	MODE_MAGON,
+	MODE_MAGOFF,
+};
+
 enum InputMode {
 	MODE_HOVER,
 	MODE_DRAG,
@@ -143,6 +148,9 @@ public:
 	void updateFocus();
 	void updateConfig();
 	void updateSize();
+	void setMagnifyMode(MagnifyMode mode);
+	MagnifyMode getMagnifyMode(){ return _magnifyMode; }
+
 
 private:
 	void initGraphics();
@@ -162,6 +170,9 @@ private:
 	u16 _gameWidth, _gameHeight;
 	u16 _gameTopX, _gameTopY;
 	u16 _gameBottomX, _gameBottomY;
+	u16 _topWidth, _topHeight;
+	u16 _topHalfWidth, _topHalfHeight;
+	u16 _topX, _topY;
 
 	// Audio
 	Thread audioThread;
@@ -218,6 +229,7 @@ private:
 	float _cursorDeltaX, _cursorDeltaY;
 	int _cursorHotspotX, _cursorHotspotY;
 	uint32 _cursorKeyColor;
+	MagnifyMode _magnifyMode;
 };
 
 } // namespace _3DS
diff --git a/backends/platform/3ds/sprite.cpp b/backends/platform/3ds/sprite.cpp
index 1f2c72e..bbccf94 100644
--- a/backends/platform/3ds/sprite.cpp
+++ b/backends/platform/3ds/sprite.cpp
@@ -42,6 +42,8 @@ Sprite::Sprite()
 	, actualHeight(0)
 	, posX(0)
 	, posY(0)
+	, offsetX(0)
+	, offsetY(0)
 	, scaleX(1.f)
 	, scaleY(1.f)
 {
@@ -85,7 +87,6 @@ void Sprite::create(uint16 width, uint16 height, const Graphics::PixelFormat &f)
 	memcpy(vertices, tmp, sizeof(vertex) * 4);
 }
 
-
 void Sprite::free() {
 	linearFree(vertices);
 	linearFree(pixels);
@@ -138,12 +139,18 @@ void Sprite::setPosition(int x, int y) {
 	}
 }
 
+void Sprite::setOffset(uint16 x, uint16 y) {
+	offsetX = x;
+	offsetY = y;
+	dirtyMatrix = true;
+}
+
 C3D_Mtx* Sprite::getMatrix() {
 	if (dirtyMatrix) {
 		dirtyMatrix = false;
 		Mtx_Identity(&modelview);
 		Mtx_Scale(&modelview, scaleX, scaleY, 1.f);
-		Mtx_Translate(&modelview, posX, posY, 0, true);
+		Mtx_Translate(&modelview, posX - offsetX, posY - offsetY, 0, true);
 	}
 	return &modelview;
 }
diff --git a/backends/platform/3ds/sprite.h b/backends/platform/3ds/sprite.h
index 1e9c0b4..a7d8b77 100644
--- a/backends/platform/3ds/sprite.h
+++ b/backends/platform/3ds/sprite.h
@@ -52,9 +52,12 @@ public:
 	void markDirty(){ dirtyPixels = true; }
 
 	void setPosition(int x, int y);
+	void setOffset(uint16 x, uint16 y);
 	void setScale(float x, float y);
 	float getScaleX(){ return scaleX; }
 	float getScaleY(){ return scaleY; }
+	int getPosX(){ return posX; }
+	int getPosY(){ return posY; }
 	C3D_Mtx* getMatrix();
 
 	uint16 actualWidth;
@@ -68,6 +71,8 @@ private:
 	vertex* vertices;
 	int posX;
 	int posY;
+	uint16 offsetX;
+	uint16 offsetY;
 	float scaleX;
 	float scaleY;
 };


Commit: cbfec1156e37975c494d6a9400f91f07cc26cbf2
    https://github.com/scummvm/scummvm/commit/cbfec1156e37975c494d6a9400f91f07cc26cbf2
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Some changes to magnify mode

(cherry picked from commit 886be5178e5a6281792cf94e21b716f6fa5a0606)

Changed paths:
    backends/platform/3ds/osystem-events.cpp
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/osystem.h


diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index 0e635f0..c2239f4 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -24,6 +24,7 @@
 
 #include "osystem.h"
 #include "backends/timer/default/default-timer.h"
+#include "gui/gui-manager.h"
 #include "engines/engine.h"
 #include "gui.h"
 #include "options-dialog.h"
@@ -148,28 +149,33 @@ static void eventThreadFunc(void *arg) {
 
 		// Button events
 		if (keysPressed & KEY_L) {
-			if (osys->getWidth() >= 400 || osys->getHeight() >= 240) {
+			if (g_gui.isActive()) {
+				// TODO: Prevent the magnify effect from updating while the GUI is active
+				osys->displayMessageOnOSD("Magnify Mode cannot be activated in menus.");
+			} else if (config.screen != kScreenBoth && osys->getMagnifyMode() == MODE_MAGOFF) {
+				// TODO: Automatically enable both screens while magnify mode is on
+				osys->displayMessageOnOSD("Magnify Mode can only be activated\n when both screens are enabled.");
+			} else if (osys->getWidth() <= 400 && osys->getHeight() <= 240) {
+				osys->displayMessageOnOSD("In-game resolution too small to magnify.");
+			} else {
 				if (osys->getMagnifyMode() == MODE_MAGOFF) {
 					osys->setMagnifyMode(MODE_MAGON);
 					if (inputMode == MODE_DRAG) {
 						inputMode = MODE_HOVER;
 						osys->displayMessageOnOSD("Magnify Mode On. Switching to Hover Mode...");
-					} else
+					} else {
 						osys->displayMessageOnOSD("Magnify Mode On");
+					}
 				} else {
 					osys->setMagnifyMode(MODE_MAGOFF);
 					osys->updateSize();
 					if (savedInputMode == MODE_DRAG) {
 						inputMode = savedInputMode;
 						osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode...");
-					} else
+					} else {
 						osys->displayMessageOnOSD("Magnify Mode Off");
+					}
 				}
-			} else {
-				if (osys->getWidth() == 0 || osys->getHeight() == 0) {
-					osys->displayMessageOnOSD("Magnify Mode cannot be activated in Launcher.");
-				} else
-					osys->displayMessageOnOSD("In-game resolution too small to magnify.");
 			}
 		}
 		if (keysPressed & KEY_R) {
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 59ee346..93cc30c 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -274,20 +274,10 @@ void OSystem_3DS::updateScreen() {
 		return;
 
 // 	updateFocus();
+	updateMagnify();
 
 	C3D_FrameBegin(0);
 		_gameTopTexture.transfer();
-		if (_magnifyMode == MODE_MAGON) {
-			_topX = (_cursorX < _topHalfWidth) ?
-				0 : ((_cursorX < (_gameWidth - _topHalfWidth)) ?
-				_cursorX - _topHalfWidth : _gameWidth - _topWidth);
-			_topY = (_cursorY < _topHalfHeight) ?
-				0 : ((_cursorY < _gameHeight - _topHalfHeight) ?
-				_cursorY - _topHalfHeight : _gameHeight - _topHeight);
-			_gameTopTexture.setScale(1.f,1.f);
-			_gameTopTexture.setPosition(0,0);
-			_gameTopTexture.setOffset(_topX, _topY);
-		}
 		if (_overlayVisible) {
 			_overlay.transfer();
 		}
@@ -428,6 +418,25 @@ void OSystem_3DS::updateFocus() {
 	}
 }
 
+void OSystem_3DS::updateMagnify() {
+	if (_magnifyMode == MODE_MAGON && config.screen != kScreenBoth) {
+		// Only allow to magnify when both screens are enabled
+		_magnifyMode = MODE_MAGOFF;
+	}
+
+	if (_magnifyMode == MODE_MAGON) {
+		_topX = (_cursorX < _topHalfWidth) ?
+			0 : ((_cursorX < (_gameWidth - _topHalfWidth)) ?
+			_cursorX - _topHalfWidth : _gameWidth - _topWidth);
+		_topY = (_cursorY < _topHalfHeight) ?
+			0 : ((_cursorY < _gameHeight - _topHalfHeight) ?
+			_cursorY - _topHalfHeight : _gameHeight - _topHeight);
+		_gameTopTexture.setScale(1.f,1.f);
+		_gameTopTexture.setPosition(0,0);
+		_gameTopTexture.setOffset(_topX, _topY);
+	}
+}
+
 void OSystem_3DS::showOverlay() {
 	_overlayVisible = true;
 	updateSize();
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 544c900..a1c6782 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -146,6 +146,7 @@ public:
 	void setCursorDelta(float deltaX, float deltaY);
 
 	void updateFocus();
+	void updateMagnify();
 	void updateConfig();
 	void updateSize();
 	void setMagnifyMode(MagnifyMode mode);


Commit: a151356a5b657e8fe48beb9dbdfd3b140a77465d
    https://github.com/scummvm/scummvm/commit/a151356a5b657e8fe48beb9dbdfd3b140a77465d
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Reworked OSD message display

So the game remains interactive while OSD message are displayed.

(cherry picked from commit 3fcbbbef44da830dc7fc54c6f0ef0cb98b45f858)

Changed paths:
    backends/platform/3ds/osystem-events.cpp
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/osystem.h


diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index c2239f4..8c06187 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -37,8 +37,6 @@ static InputMode inputMode = MODE_DRAG;
 static InputMode savedInputMode = MODE_DRAG;
 static aptHookCookie cookie;
 static bool optionMenuOpening = false;
-static Common::String messageOSD;
-static bool showMessageOSD = false;
 
 static void pushEventQueue(Common::Queue<Common::Event> *queue, Common::Event &event) {
 	Common::StackLock lock(*eventMutex);
@@ -320,18 +318,7 @@ void OSystem_3DS::setMagnifyMode(MagnifyMode mode) {
 	_magnifyMode = mode;
 }
 
-void OSystem_3DS::displayMessageOnOSD(const char *msg) {
-	messageOSD = msg;
-	showMessageOSD = true;
-}
-
 bool OSystem_3DS::pollEvent(Common::Event &event) {
-	if (showMessageOSD) {
-		showMessageOSD = false;
-		StatusMessageDialog dialog(messageOSD, 800);
-		dialog.runModal();
-	}
-
 	aptMainLoop(); // Call apt hook when necessary
 
 	if (optionMenuOpening) {
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 93cc30c..e464f49 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -24,6 +24,7 @@
 #include "backends/platform/3ds/osystem.h"
 #include "backends/platform/3ds/shader_shbin.h"
 #include "common/rect.h"
+#include "graphics/fontman.h"
 #include "options-dialog.h"
 #include "config.h"
 
@@ -276,6 +277,10 @@ void OSystem_3DS::updateScreen() {
 // 	updateFocus();
 	updateMagnify();
 
+	if (_osdMessage.getPixels() && _osdMessageEndTime <= getMillis(true)) {
+		_osdMessage.free();
+	}
+
 	C3D_FrameBegin(0);
 		_gameTopTexture.transfer();
 		if (_overlayVisible) {
@@ -284,6 +289,7 @@ void OSystem_3DS::updateScreen() {
 		if (_cursorVisible && config.showCursor) {
 			_cursorTexture.transfer();
 		}
+		_osdMessage.transfer();
 		_activityIcon.transfer();
 	C3D_FrameEnd(0);
 
@@ -304,6 +310,11 @@ void OSystem_3DS::updateScreen() {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _activityIcon.getMatrix());
 				_activityIcon.render();
 			}
+			if (_osdMessage.getPixels() && config.screen == kScreenTop) {
+				_osdMessage.setPosition((400 - _osdMessage.actualWidth) / 2, (240 - _osdMessage.actualHeight) / 2);
+				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _osdMessage.getMatrix());
+				_osdMessage.render();
+			}
 			if (_cursorVisible && config.showCursor && config.screen == kScreenTop) {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
 				_cursorTexture.render();
@@ -326,6 +337,11 @@ void OSystem_3DS::updateScreen() {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _activityIcon.getMatrix());
 				_activityIcon.render();
 			}
+			if (_osdMessage.getPixels()) {
+				_osdMessage.setPosition((320 - _osdMessage.actualWidth) / 2, (240 - _osdMessage.actualHeight) / 2);
+				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _osdMessage.getMatrix());
+				_osdMessage.render();
+			}
 			if (_cursorVisible && config.showCursor) {
 				C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, _modelviewLocation, _cursorTexture.getMatrix());
 				_cursorTexture.render();
@@ -470,6 +486,57 @@ void OSystem_3DS::copyRectToOverlay(const void *buf, int pitch, int x,
 	_overlay.markDirty();
 }
 
+void OSystem_3DS::displayMessageOnOSD(const char *msg) {
+	// The font we are going to use:
+	const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
+	if (!font) {
+		warning("No available font to render OSD messages");
+		return;
+	}
+
+	// Split the message into separate lines.
+	Common::Array<Common::String> lines;
+	const char *ptr;
+	for (ptr = msg; *ptr; ++ptr) {
+		if (*ptr == '\n') {
+			lines.push_back(Common::String(msg, ptr - msg));
+			msg = ptr + 1;
+		}
+	}
+	lines.push_back(Common::String(msg, ptr - msg));
+
+	// Determine a rect which would contain the message string (clipped to the
+	// screen dimensions).
+	const int vOffset = 6;
+	const int lineSpacing = 1;
+	const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
+	int width = 0;
+	int height = lineHeight * lines.size() + 2 * vOffset;
+	uint i;
+	for (i = 0; i < lines.size(); i++) {
+		width = MAX(width, font->getStringWidth(lines[i]) + 14);
+	}
+
+	// Clip the rect
+	if (width > getOverlayWidth())
+		width = getOverlayWidth();
+	if (height > getOverlayHeight())
+		height = getOverlayHeight();
+
+	_osdMessage.create(width, height, _pfGameTexture);
+	_osdMessage.fillRect(Common::Rect(width, height), _pfGameTexture.ARGBToColor(200, 0, 0, 0));
+
+	// Render the message, centered, and in white
+	for (i = 0; i < lines.size(); i++) {
+		font->drawString(&_osdMessage, lines[i],
+		                 0, 0 + i * lineHeight + vOffset + lineSpacing, width,
+		                 _pfGameTexture.RGBToColor(255, 255, 255),
+		                 Graphics::kTextAlignCenter);
+	}
+
+	_osdMessageEndTime = getMillis(true) + kOSDMessageDuration;
+}
+
 void OSystem_3DS::displayActivityIconOnOSD(const Graphics::Surface *icon) {
 	if (!icon) {
 		_activityIcon.free();
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index a1c6782..51aa40a 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -130,7 +130,7 @@ public:
 	                       int h);
 	virtual int16 getOverlayHeight();
 	virtual int16 getOverlayWidth();
-	virtual void displayMessageOnOSD(const char *msg);
+	void displayMessageOnOSD(const char *msg) override;
 	void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
 
 	bool showMouse(bool visible);
@@ -190,6 +190,12 @@ private:
 	Sprite _gameBottomTexture;
 	Sprite _overlay;
 	Sprite _activityIcon;
+	Sprite _osdMessage;
+
+	enum {
+		kOSDMessageDuration = 800
+	};
+	uint32 _osdMessageEndTime;
 
 	int _screenShakeOffset;
 	bool _overlayVisible;


Commit: 236d15ec3a8b54d218c300be76eb7fbf55f8e139
    https://github.com/scummvm/scummvm/commit/236d15ec3a8b54d218c300be76eb7fbf55f8e139
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Fix centering of the game screen

(cherry picked from commit 4810a5d8d35c5caa79f9a3a1e93d882de32b2d87)

Changed paths:
    backends/platform/3ds/osystem-graphics.cpp


diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index e464f49..fc55c5e 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -178,23 +178,23 @@ void OSystem_3DS::updateSize() {
 			float r = 400.f / _gameWidth;
 			_gameTopTexture.setScale(r, r);
 			_gameTopX = 0;
-			_gameTopY = (240.f - r * _gameHeight) / 2.f;
+			_gameTopY = (240.f / r - _gameHeight) / 2.f;
 		} else {
 			float r = 240.f / _gameHeight;
 			_gameTopTexture.setScale(r, r);
 			_gameTopY = 0;
-			_gameTopX = (400.f - r * _gameWidth) / 2.f;
+			_gameTopX = (400.f / r - _gameWidth) / 2.f;
 		}
 		if (ratio > 320.f / 240.f) {
 			float r = 320.f / _gameWidth;
 			_gameBottomTexture.setScale(r, r);
 			_gameBottomX = 0;
-			_gameBottomY = (240.f - r * _gameHeight) / 2.f;
+			_gameBottomY = (240.f / r - _gameHeight) / 2.f;
 		} else {
 			float r = 240.f / _gameHeight;
 			_gameBottomTexture.setScale(r, r);
 			_gameBottomY = 0;
-			_gameBottomX = (320.f - r * _gameWidth) / 2.f;
+			_gameBottomX = (320.f / r - _gameWidth) / 2.f;
 		}
 	}
 	_gameTopTexture.setPosition(_gameTopX, _gameTopY);


Commit: 4c8e83f23e4ea7e38cbe6bba53739e3ad1862601
    https://github.com/scummvm/scummvm/commit/4c8e83f23e4ea7e38cbe6bba53739e3ad1862601
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Update the list of third-party libraries

(cherry picked from commit 2c491243f5ddf101ea600bb1233a809d8ea0bf68)

Changed paths:
    backends/platform/3ds/README.md


diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index ee0aaaa..7f54075 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -148,10 +148,12 @@ The following libraries can be downloaded with pacman:
 |  libmad       |  3ds-libmad           |
 |  libogg       |  3ds-libogg           |
 |  tremor       |  3ds-libvorbisidec    |
+|  flac         |  3ds-flac             |
+|  curl         |  3ds-curl             |
 
-At the moment of writing, `faad` and `flac` are not in the devkitPro 3DS pacman
-repository. They can be compiled by following the instructions in the section below,
-in case they cannot be found through pacman.
+At the moment of writing, `faad` is not in the devkitPro 3DS pacman repository. It
+can be compiled by following the instructions in the section below, in case it cannot
+be found through pacman.
 
 The following pacman packages are also recommended:
  - `3ds-dev`
@@ -203,21 +205,6 @@ In the source directory of the library:
  $ export LDFLAGS="-L$PORTLIBS/lib"
  ```
 
-4.1.3) Note on FLAC:
---------------------
-At the moment of writing, the `libflac` library cannot be compiled for the 3DS out of the box.
-However, the following patch (for the Nintendo Switch) can be adapted and applied to it:
-https://github.com/devkitPro/pacman-packages/tree/master/switch/flac
-
-Afterwards, the library can be built with:
-```
- $  CFLAGS="${CFLAGS} -D__3DS__ " \
-    ./configure --prefix="${PORTLIBS_PREFIX}" --host=arm-none-eabi \
-    --disable-shared --enable-static \
-    --disable-xmms-plugin --disable-cpplibs \
-    --disable-sse --without-ogg
-```
-
 4.2) Compiling ScummVM
 ----------------------
 Do the following in a fresh terminal.


Commit: c67615a8cc7906750474923577370d02574e9203
    https://github.com/scummvm/scummvm/commit/c67615a8cc7906750474923577370d02574e9203
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2019-11-07T11:18:48+01:00

Commit Message:
3DS: Improve the table of contents in the README.md file

(cherry picked from commit 56e5bd0d7702f448af7c414dba9f635c84c79913)

Changed paths:
    backends/platform/3ds/README.md


diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index 7f54075..b933a9f 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -3,26 +3,24 @@ ScummVM 3DS README
 
 Table of Contents:
 ------------------
-1.0) Installation
- * 1.1 3DSX installation
- * 1.2 CIA installation
- * 1.3 Additional files
-
-2.0) Controls
- * 2.1 Default key mappings
- * 2.2 Hover mode
- * 2.3 Drag mode
- * 2.4 Magnify mode
-
-3.0) Supported Games
-
-4.0) Compiling
- * 4.1 Prerequisites
- * * 4.1.1 Compiling third-party libraries
- * * 4.1.2 Manually setting up the environment
- * * 4.1.3 Note on FLAC
- * 4.2 Compiling ScummVM
- * 4.3 Warning for build sizes
+[1.0) Installation](#10-installation)
+ * [1.1 3DSX installation](#11-3dsx-installation)
+ * [1.2 CIA installation](#12-cia-installation)
+
+[2.0) Controls](#20-controls)
+ * [2.1 Default key mappings](#21-default-key-mappings)
+ * [2.2 Hover mode](#22-hover-mode)
+ * [2.3 Drag mode](#23-drag-mode)
+ * [2.4 Magnify mode](#24-magnify-mode)
+
+[3.0) Supported Games](#30-supported-games)
+
+[4.0) Compiling](#40-compiling)
+ * [4.1 Prerequisites](#41-prerequisites)
+ * * [4.1.1 Compiling third-party libraries](#411-compiling-third-party-libraries)
+ * * [4.1.2 Manually setting up the environment](#412-manually-setting-up-the-environment)
+ * [4.2 Compiling ScummVM](#42-compiling-scummvm)
+ * [4.3 Warning for build sizes](#43-warning-for-build-sizes)
 
 1.0) Installation
 -----------------


Commit: 01876ad3d91fb5291dd13f75f898921132c212a5
    https://github.com/scummvm/scummvm/commit/01876ad3d91fb5291dd13f75f898921132c212a5
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:20:08+01:00

Commit Message:
3DS: Use the full resolution for the overlay on the top screen

(cherry picked from commit 6901ee0242c128d3b6026f83a10da4ca90e265e0)

Changed paths:
  R backends/platform/3ds/gui.cpp
  R backends/platform/3ds/gui.h
    backends/platform/3ds/module.mk
    backends/platform/3ds/options-dialog.cpp
    backends/platform/3ds/options-dialog.h
    backends/platform/3ds/osystem-events.cpp
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h
    po/POTFILES


diff --git a/backends/platform/3ds/gui.cpp b/backends/platform/3ds/gui.cpp
deleted file mode 100644
index 0883d5a..0000000
--- a/backends/platform/3ds/gui.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "backends/platform/3ds/gui.h"
-#include "common/system.h"
-
-StatusMessageDialog* StatusMessageDialog::_opened = 0;
-
-StatusMessageDialog::StatusMessageDialog(const Common::String &message, uint32 duration)
-	: MessageDialog(message, 0, 0) {
-	_timer = g_system->getMillis() + duration;
-	if (_opened)
-		_opened->close();
-	_opened = this;
-}
-
-void StatusMessageDialog::handleTickle() {
-	MessageDialog::handleTickle();
-	if (g_system->getMillis() > _timer)
-		close();
-}
-
-void StatusMessageDialog::close() {
-    GUI::Dialog::close();
-	if (_opened)
-		_opened = 0;
-}
diff --git a/backends/platform/3ds/gui.h b/backends/platform/3ds/gui.h
deleted file mode 100644
index 8e82c6c..0000000
--- a/backends/platform/3ds/gui.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GUI_3DS_H
-#define GUI_3DS_H
-
-#include "gui/message.h"
-
-class StatusMessageDialog : public GUI::MessageDialog {
-public:
-	StatusMessageDialog(const Common::String &message, uint32 duration);
-
-	void handleTickle();
-
-protected:
-	virtual void close();
-
-	uint32 _timer;
-	static StatusMessageDialog* _opened;
-};
-
-#endif // GUI_3DS_H
diff --git a/backends/platform/3ds/module.mk b/backends/platform/3ds/module.mk
index 3eb15ae..16fbd5f 100644
--- a/backends/platform/3ds/module.mk
+++ b/backends/platform/3ds/module.mk
@@ -4,7 +4,6 @@ MODULE_OBJS := \
 	main.o \
 	shader.shbin.o \
 	sprite.o \
-	gui.o \
 	config.o \
 	options-dialog.o \
 	osystem.o \
diff --git a/backends/platform/3ds/options-dialog.cpp b/backends/platform/3ds/options-dialog.cpp
index a6be649..d57daa7 100644
--- a/backends/platform/3ds/options-dialog.cpp
+++ b/backends/platform/3ds/options-dialog.cpp
@@ -61,7 +61,7 @@ OptionsDialog::OptionsDialog() : GUI::Dialog(20, 20, 280, 200) {
 	_screenRadioGroup->setValue(config.screen);
 
 	new GUI::StaticTextWidget(this, 0, 100, 110, 15, _("C-Pad Sensitivity:"), Graphics::kTextAlignRight);
-	_sensitivity = new GUI::SliderWidget(this, 115, 100, 160, 15, "TODO: Add tooltip", 1);
+	_sensitivity = new GUI::SliderWidget(this, 115, 100, 160, 15);
 	_sensitivity->setMinValue(-15);
 	_sensitivity->setMaxValue(30);
 	_sensitivity->setValue(config.sensitivity);
@@ -72,20 +72,41 @@ OptionsDialog::~OptionsDialog() {
 	optionMenuOpened = false;
 }
 
-void OptionsDialog::updateConfigManager() {
-	config.showCursor = _showCursorCheckbox->getState();
-	config.snapToBorder = _snapToBorderCheckbox->getState();
-	config.stretchToFit = _stretchToFitCheckbox->getState();
-	config.sensitivity = _sensitivity->getValue();
-	config.screen = _screenRadioGroup->getValue();
-	saveConfig();
-	loadConfig();
+bool OptionsDialog::getShowCursor() const {
+	return _showCursorCheckbox->getState();
+}
+
+bool OptionsDialog::getSnapToBorder() const {
+	return _snapToBorderCheckbox->getState();
+}
+
+bool OptionsDialog::getStretchToFit() const {
+	return _stretchToFitCheckbox->getState();
+}
+
+int OptionsDialog::getSensitivity() const {
+	return _sensitivity->getValue();
+}
+
+int OptionsDialog::getScreen() const {
+	return _screenRadioGroup->getValue();
+}
+
+void OptionsDialog::reflowLayout() {
+	const int screenW = g_system->getOverlayWidth();
+	const int screenH = g_system->getOverlayHeight();
+
+	// Center the dialog
+	_x = (screenW - getWidth()) / 2;
+	_y = (screenH - getHeight()) / 2;
+
+	GUI::Dialog::reflowLayout();
 }
 
 void OptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
 	switch(cmd) {
 	case GUI::kOKCmd:
-		updateConfigManager();
+		setResult(1);
 		// Fall through
 	case GUI::kCloseCmd:
 		close();
diff --git a/backends/platform/3ds/options-dialog.h b/backends/platform/3ds/options-dialog.h
index d8c0d7b..68ff75e 100644
--- a/backends/platform/3ds/options-dialog.h
+++ b/backends/platform/3ds/options-dialog.h
@@ -50,9 +50,16 @@ public:
 	OptionsDialog();
 	~OptionsDialog();
 
+	// GuiObject API
+	void reflowLayout() override;
+
+	bool getShowCursor() const;
+	bool getSnapToBorder() const;
+	bool getStretchToFit() const;
+	int getSensitivity() const;
+	int getScreen() const;
 protected:
-	virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
-	void updateConfigManager();
+	void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
 
 	GUI::SliderWidget *_sensitivity;
 	GUI::CheckboxWidget *_showCursorCheckbox;
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index 8c06187..fb30d66 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -22,13 +22,14 @@
 
 #define FORBIDDEN_SYMBOL_EXCEPTION_time_h
 
-#include "osystem.h"
+#include "backends/platform/3ds/osystem.h"
+
+#include "backends/platform/3ds/config.h"
+#include "backends/platform/3ds/options-dialog.h"
 #include "backends/timer/default/default-timer.h"
-#include "gui/gui-manager.h"
+#include "common/translation.h"
 #include "engines/engine.h"
-#include "gui.h"
-#include "options-dialog.h"
-#include "config.h"
+#include "gui/gui-manager.h"
 
 namespace _3DS {
 
@@ -149,29 +150,29 @@ static void eventThreadFunc(void *arg) {
 		if (keysPressed & KEY_L) {
 			if (g_gui.isActive()) {
 				// TODO: Prevent the magnify effect from updating while the GUI is active
-				osys->displayMessageOnOSD("Magnify Mode cannot be activated in menus.");
+				osys->displayMessageOnOSD(_("Magnify Mode cannot be activated in menus."));
 			} else if (config.screen != kScreenBoth && osys->getMagnifyMode() == MODE_MAGOFF) {
 				// TODO: Automatically enable both screens while magnify mode is on
-				osys->displayMessageOnOSD("Magnify Mode can only be activated\n when both screens are enabled.");
+				osys->displayMessageOnOSD(_("Magnify Mode can only be activated\n when both screens are enabled."));
 			} else if (osys->getWidth() <= 400 && osys->getHeight() <= 240) {
-				osys->displayMessageOnOSD("In-game resolution too small to magnify.");
+				osys->displayMessageOnOSD(_("In-game resolution too small to magnify."));
 			} else {
 				if (osys->getMagnifyMode() == MODE_MAGOFF) {
 					osys->setMagnifyMode(MODE_MAGON);
 					if (inputMode == MODE_DRAG) {
 						inputMode = MODE_HOVER;
-						osys->displayMessageOnOSD("Magnify Mode On. Switching to Hover Mode...");
+						osys->displayMessageOnOSD(_("Magnify Mode On. Switching to Hover Mode..."));
 					} else {
-						osys->displayMessageOnOSD("Magnify Mode On");
+						osys->displayMessageOnOSD(_("Magnify Mode On"));
 					}
 				} else {
 					osys->setMagnifyMode(MODE_MAGOFF);
 					osys->updateSize();
 					if (savedInputMode == MODE_DRAG) {
 						inputMode = savedInputMode;
-						osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode...");
+						osys->displayMessageOnOSD(_("Magnify Mode Off. Reactivating Drag Mode..."));
 					} else {
-						osys->displayMessageOnOSD("Magnify Mode Off");
+						osys->displayMessageOnOSD(_("Magnify Mode Off"));
 					}
 				}
 			}
@@ -179,13 +180,13 @@ static void eventThreadFunc(void *arg) {
 		if (keysPressed & KEY_R) {
 			if (inputMode == MODE_DRAG) {
 				inputMode = savedInputMode = MODE_HOVER;
-				osys->displayMessageOnOSD("Hover Mode");
+				osys->displayMessageOnOSD(_("Hover Mode"));
 			} else {
 				if (osys->getMagnifyMode() == MODE_MAGOFF) {
 					inputMode = savedInputMode = MODE_DRAG;
-					osys->displayMessageOnOSD("Drag Mode");
+					osys->displayMessageOnOSD(_("Drag Mode"));
 				} else
-					osys->displayMessageOnOSD("Cannot Switch to Drag Mode while Magnify Mode is On");
+					osys->displayMessageOnOSD(_("Cannot Switch to Drag Mode while Magnify Mode is On"));
 			}
 		}
 		if (keysPressed & KEY_A || keysPressed & KEY_DLEFT || keysReleased & KEY_A || keysReleased & KEY_DLEFT) {
@@ -238,9 +239,9 @@ static void eventThreadFunc(void *arg) {
 				osys->updateSize();
 				if (savedInputMode == MODE_DRAG) {
 					inputMode = savedInputMode;
-					osys->displayMessageOnOSD("Magnify Mode Off. Reactivating Drag Mode.\nReturning to Launcher...");
+					osys->displayMessageOnOSD(_("Magnify Mode Off. Reactivating Drag Mode.\nReturning to Launcher..."));
 				} else
-					osys->displayMessageOnOSD("Magnify Mode Off. Returning to Launcher...");
+					osys->displayMessageOnOSD(_("Magnify Mode Off. Returning to Launcher..."));
 			}
 		}
 
@@ -309,8 +310,12 @@ void OSystem_3DS::destroyEvents() {
 
 void OSystem_3DS::transformPoint(touchPosition &point) {
 	if (!_overlayVisible) {
-		point.px = static_cast<float>(point.px) / _gameBottomTexture.getScaleX() - _gameBottomX;
-		point.py = static_cast<float>(point.py) / _gameBottomTexture.getScaleY() - _gameBottomY;
+		point.px = static_cast<float>(point.px) / _gameBottomTexture.getScaleX() - _gameBottomTexture.getPosX();
+		point.py = static_cast<float>(point.py) / _gameBottomTexture.getScaleY() - _gameBottomTexture.getPosY();
+	} else {
+		if (config.screen == kScreenTop) {
+			point.px = (uint32) point.px * 400 / 320; // TODO: Fix horizontal speed
+		}
 	}
 }
 
@@ -323,12 +328,7 @@ bool OSystem_3DS::pollEvent(Common::Event &event) {
 
 	if (optionMenuOpening) {
 		optionMenuOpening = false;
-		OptionsDialog dialog;
-		if (g_engine)
-			g_engine->pauseEngine(true);
-		dialog.runModal();
-		if (g_engine)
-			g_engine->pauseEngine(false);
+		runOptionsDialog();
 	}
 
 	Common::StackLock lock(*eventMutex);
@@ -340,4 +340,31 @@ bool OSystem_3DS::pollEvent(Common::Event &event) {
 	return true;
 }
 
+void OSystem_3DS::runOptionsDialog() {
+	OptionsDialog dialog;
+	if (g_engine)
+		g_engine->pauseEngine(true);
+	int result = dialog.runModal();
+	if (g_engine)
+		g_engine->pauseEngine(false);
+
+	if (result > 0) {
+		int oldScreen = config.screen;
+
+		config.showCursor   = dialog.getShowCursor();
+		config.snapToBorder = dialog.getSnapToBorder();
+		config.stretchToFit = dialog.getStretchToFit();
+		config.sensitivity  = dialog.getSensitivity();
+		config.screen       = dialog.getScreen();
+
+		saveConfig();
+		loadConfig();
+
+		if (config.screen != oldScreen) {
+			_screenChangeId++;
+			g_gui.checkScreenChange();
+		}
+	}
+}
+
 } // namespace _3DS
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index fc55c5e..8fb92f4 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -146,10 +146,16 @@ int OSystem_3DS::getGraphicsMode() const {
 void OSystem_3DS::initSize(uint width, uint height,
                                    const Graphics::PixelFormat *format) {
 	debug("3ds initsize w:%d h:%d", width, height);
+	int oldScreen = config.screen;
+	loadConfig();
+	if (config.screen != oldScreen) {
+		_screenChangeId++;
+	}
+
 	_gameWidth = width;
 	_gameHeight = height;
 	_gameTopTexture.create(width, height, _pfGameTexture);
-	_overlay.create(getOverlayWidth(), getOverlayHeight(), _pfGameTexture);
+	_overlay.create(400, 320, _pfGameTexture);
 	_topHalfWidth = _topWidth / 2;
 	_topHalfHeight = _topHeight / 2;
 
@@ -558,7 +564,7 @@ int16 OSystem_3DS::getOverlayHeight() {
 }
 
 int16 OSystem_3DS::getOverlayWidth() {
-	return 320;
+	return config.screen == kScreenTop ? 400 : 320;
 }
 
 bool OSystem_3DS::showMouse(bool visible) {
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index aa0b3a7..2003795 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -77,6 +77,7 @@ OSystem_3DS::OSystem_3DS():
 	_topWidth(400),
 	_topHeight(240),
 	_overlayVisible(false),
+	_screenChangeId(0),
 	_magnifyMode(MODE_MAGOFF),
 	exiting(false),
 	sleeping(false)
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 51aa40a..70cd475 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -105,7 +105,7 @@ public:
 	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
 	void initSize(uint width, uint height,
 	              const Graphics::PixelFormat *format = NULL);
-	virtual int getScreenChangeID() const { return 0; };
+	virtual int getScreenChangeID() const { return _screenChangeId; };
 
 	void beginGFXTransaction();
 	OSystem::TransactionError endGFXTransaction();
@@ -152,7 +152,6 @@ public:
 	void setMagnifyMode(MagnifyMode mode);
 	MagnifyMode getMagnifyMode(){ return _magnifyMode; }
 
-
 private:
 	void initGraphics();
 	void destroyGraphics();
@@ -160,6 +159,7 @@ private:
 	void destroyAudio();
 	void initEvents();
 	void destroyEvents();
+	void runOptionsDialog();
 
 	void flushGameScreen();
 	void flushCursor();
@@ -199,6 +199,7 @@ private:
 
 	int _screenShakeOffset;
 	bool _overlayVisible;
+	int _screenChangeId;
 
 	DVLB_s *_dvlb;
 	shaderProgram_s _program;
diff --git a/po/POTFILES b/po/POTFILES
index 94b14e7..dcce351 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -75,6 +75,8 @@ backends/networking/sdl_net/handlers/uploadfilehandler.cpp
 backends/networking/sdl_net/handlerutils.cpp
 backends/networking/sdl_net/localwebserver.cpp
 backends/networking/sdl_net/uploadfileclienthandler.cpp
+backends/platform/3ds/options-dialog.cpp
+backends/platform/3ds/osystem-events.cpp
 backends/platform/ds/arm9/source/dsoptions.cpp
 backends/platform/ios7/ios7_osys_events.cpp
 backends/platform/iphone/osys_events.cpp


Commit: f89ecdc149de8d31e0ee12d3d4e815ddb8e6f752
    https://github.com/scummvm/scummvm/commit/f89ecdc149de8d31e0ee12d3d4e815ddb8e6f752
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2019-11-07T11:20:12+01:00

Commit Message:
3DS: Rework mouse cursor movement

- Fix clipping the cursor position
- Ensure the mouse has the same vertical and horizontal speed

(cherry picked from commit 652722e760fab2959c74e2fa65452f334c8b8478)

Changed paths:
    backends/platform/3ds/osystem-events.cpp
    backends/platform/3ds/osystem-graphics.cpp
    backends/platform/3ds/osystem.h
    backends/platform/3ds/sprite.h


diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index fb30d66..1ee550e 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -51,8 +51,6 @@ static void eventThreadFunc(void *arg) {
 	uint32 touchStartTime = osys->getMillis();
 	touchPosition lastTouch = {0, 0};
 	bool isRightClick = false;
-	float cursorX = 0;
-	float cursorY = 0;
 	float cursorDeltaX = 0;
 	float cursorDeltaY = 0;
 	int circleDeadzone = 20;
@@ -93,8 +91,7 @@ static void eventThreadFunc(void *arg) {
 				if (touch.py > 239 - borderSnapZone)
 					touch.py = 239;
 			}
-			cursorX = touch.px;
-			cursorY = touch.py;
+
 			osys->transformPoint(touch);
 
 			osys->warpMouse(touch.px, touch.py);
@@ -130,16 +127,14 @@ static void eventThreadFunc(void *arg) {
 				pushEventQueue(eventQueue, event);
 			}
 		} else if (cursorDeltaX != 0 || cursorDeltaY != 0) {
-			cursorX += cursorDeltaX;
-			cursorY -= cursorDeltaY;
-			if (cursorX < 0) cursorX = 0;
-			if (cursorY < 0) cursorY = 0;
-			if (cursorX > 320) cursorX = 320;
-			if (cursorY > 240) cursorY = 240;
-			lastTouch.px = cursorX;
-			lastTouch.py = cursorY;
-			osys->transformPoint(lastTouch);
+			float scaleRatio = osys->getScaleRatio();
+
+			lastTouch.px += cursorDeltaX / scaleRatio;
+			lastTouch.py -= cursorDeltaY / scaleRatio;
+
+			osys->clipPoint(lastTouch);
 			osys->warpMouse(lastTouch.px, lastTouch.py);
+
 			event.mouse.x = lastTouch.px;
 			event.mouse.y = lastTouch.py;
 			event.type = Common::EVENT_MOUSEMOVE;
@@ -312,10 +307,18 @@ void OSystem_3DS::transformPoint(touchPosition &point) {
 	if (!_overlayVisible) {
 		point.px = static_cast<float>(point.px) / _gameBottomTexture.getScaleX() - _gameBottomTexture.getPosX();
 		point.py = static_cast<float>(point.py) / _gameBottomTexture.getScaleY() - _gameBottomTexture.getPosY();
+	}
+
+	clipPoint(point);
+}
+
+void OSystem_3DS::clipPoint(touchPosition &point) {
+	if (_overlayVisible) {
+		point.px = CLIP<uint16>(point.px, 0, getOverlayWidth()  - 1);
+		point.py = CLIP<uint16>(point.py, 0, getOverlayHeight() - 1);
 	} else {
-		if (config.screen == kScreenTop) {
-			point.px = (uint32) point.px * 400 / 320; // TODO: Fix horizontal speed
-		}
+		point.px = CLIP<uint16>(point.px, 0, _gameTopTexture.actualWidth  - 1);
+		point.py = CLIP<uint16>(point.py, 0, _gameTopTexture.actualHeight - 1);
 	}
 }
 
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 8fb92f4..c3864c1 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -233,6 +233,16 @@ OSystem::TransactionError OSystem_3DS::endGFXTransaction() {
 	return OSystem::kTransactionSuccess;
 }
 
+float OSystem_3DS::getScaleRatio() const {
+	if (_overlayVisible) {
+		return 1.0;
+	} else if (config.screen == kScreenTop) {
+		return _gameTopTexture.getScaleX();
+	} else {
+		return _gameBottomTexture.getScaleX();
+	}
+}
+
 void OSystem_3DS::setPalette(const byte *colors, uint start, uint num) {
 	assert(start + num <= 256);
 	memcpy(_palette + 3 * start, colors, 3 * num);
@@ -578,18 +588,17 @@ void OSystem_3DS::warpMouse(int x, int y) {
 	_cursorY = y;
 
 	// TODO: adjust for _cursorScalable ?
-	int offsetx = 0;
-	int offsety = 0;
 	x -= _cursorHotspotX;
 	y -= _cursorHotspotY;
+
+	int offsetx = 0;
+	int offsety = 0;
 	if (!_overlayVisible) {
-		offsetx += config.screen == kScreenTop ? _gameTopX : _gameBottomX;
-		offsety += config.screen == kScreenTop ? _gameTopY : _gameBottomY;
+		offsetx = config.screen == kScreenTop ? _gameTopTexture.getPosX() : _gameBottomTexture.getPosX();
+		offsety = config.screen == kScreenTop ? _gameTopTexture.getPosY() : _gameBottomTexture.getPosY();
 	}
-	float scalex = config.screen == kScreenTop ? (float)_gameTopTexture.actualWidth / _gameWidth : 1.f;
-	float scaley = config.screen == kScreenTop ? (float)_gameTopTexture.actualHeight / _gameHeight : 1.f;
-	_cursorTexture.setPosition(scalex * x + offsetx,
-							   scaley * y + offsety);
+
+	_cursorTexture.setPosition(x + offsetx, y + offsety);
 }
 
 void OSystem_3DS::setCursorDelta(float deltaX, float deltaY) {
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 70cd475..c15c353 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -111,6 +111,7 @@ public:
 	OSystem::TransactionError endGFXTransaction();
 	int16 getHeight(){ return _gameHeight; }
 	int16 getWidth(){ return _gameWidth; }
+	float getScaleRatio() const;
 	void setPalette(const byte *colors, uint start, uint num);
 	void grabPalette(byte *colors, uint start, uint num) const;
 	void copyRectToScreen(const void *buf, int pitch, int x, int y, int w,
@@ -142,6 +143,8 @@ public:
 
 	// Transform point from touchscreen coords into gamescreen coords
 	void transformPoint(touchPosition &point);
+	// Clip point to gamescreen coords
+	void clipPoint(touchPosition &point);
 
 	void setCursorDelta(float deltaX, float deltaY);
 
diff --git a/backends/platform/3ds/sprite.h b/backends/platform/3ds/sprite.h
index a7d8b77..7bb4d36 100644
--- a/backends/platform/3ds/sprite.h
+++ b/backends/platform/3ds/sprite.h
@@ -54,10 +54,10 @@ public:
 	void setPosition(int x, int y);
 	void setOffset(uint16 x, uint16 y);
 	void setScale(float x, float y);
-	float getScaleX(){ return scaleX; }
-	float getScaleY(){ return scaleY; }
-	int getPosX(){ return posX; }
-	int getPosY(){ return posY; }
+	float getScaleX() const { return scaleX; }
+	float getScaleY() const { return scaleY; }
+	int getPosX() const { return posX; }
+	int getPosY() const { return posY; }
 	C3D_Mtx* getMatrix();
 
 	uint16 actualWidth;


Commit: 3558a70ce0dca08b1d62e6489f0083e91418691a
    https://github.com/scummvm/scummvm/commit/3558a70ce0dca08b1d62e6489f0083e91418691a
Author: MrHuu (MrHuu at users.noreply.github.com)
Date: 2019-11-07T11:21:40+01:00

Commit Message:
3DS: Remove 3dstool dependency

This patch alters the way the .cia is build. It removes the need for 3dstool.

Instead of first generating a .romfs file using 3dstool, let makerom generate the romfs while building the .cia.

(cherry picked from commit 3cef5fa46e091febfd04e94fe592389d86b599ab)

Changed paths:
    backends/platform/3ds/3ds.mk
    backends/platform/3ds/README.md
    backends/platform/3ds/app/scummvm.rsf


diff --git a/backends/platform/3ds/3ds.mk b/backends/platform/3ds/3ds.mk
index 52a1b04..136e984 100644
--- a/backends/platform/3ds/3ds.mk
+++ b/backends/platform/3ds/3ds.mk
@@ -24,7 +24,6 @@ clean_3ds:
 	$(RM) $(TARGET).smdh
 	$(RM) $(TARGET).3dsx
 	$(RM) $(TARGET).bnr
-	$(RM) $(TARGET).romfs
 	$(RM) $(TARGET).cia
 	$(RM) -rf romfs
 	$(RM) -rf dist_3ds
@@ -58,12 +57,8 @@ $(TARGET).bnr: $(APP_BANNER_IMAGE) $(APP_BANNER_AUDIO)
 	@bannertool makebanner -o $@ -i $(APP_BANNER_IMAGE) -a $(APP_BANNER_AUDIO)
 	@echo built ... $(notdir $@)
 
-$(TARGET).romfs: romfs
-	@3dstool -cvtf romfs $(TARGET).romfs --romfs-dir romfs
-	@echo built ... $(notdir $@)
-
-$(TARGET).cia: $(EXECUTABLE) $(APP_RSF) $(TARGET).smdh $(TARGET).bnr $(TARGET).romfs
-	@makerom -f cia -target t -exefslogo -o $@ -elf $(EXECUTABLE) -rsf $(APP_RSF) -banner $(TARGET).bnr -icon $(TARGET).smdh -romfs $(TARGET).romfs
+$(TARGET).cia: $(EXECUTABLE) $(APP_RSF) $(TARGET).smdh $(TARGET).bnr romfs
+	@makerom -f cia -target t -exefslogo -o $@ -elf $(EXECUTABLE) -rsf $(APP_RSF) -banner $(TARGET).bnr -icon $(TARGET).smdh -DAPP_ROMFS=romfs/
 	@echo built ... $(notdir $@)
 
 dist_3ds: $(TARGET).cia $(TARGET).3dsx $(DIST_FILES_DOCS)
diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index b933a9f..c566699 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -235,7 +235,7 @@ Additionally compile to specific formats to be used on the 3DS:
 Assuming everything was successful, you'll be able to find the binary
 files in the root of your scummvm folder.
 
-Note: for the CIA format, you will need the '3dstool', 'makerom' and 'bannertool' tools which are
+Note: for the CIA format, you will need the 'makerom' and 'bannertool' tools which are
 not supplied with devkitPro.
 
 4.3) Warning for build sizes
diff --git a/backends/platform/3ds/app/scummvm.rsf b/backends/platform/3ds/app/scummvm.rsf
index a451894..133341c 100644
--- a/backends/platform/3ds/app/scummvm.rsf
+++ b/backends/platform/3ds/app/scummvm.rsf
@@ -7,6 +7,10 @@ TitleInfo:
   Category                : Application
   UniqueId                : 0xFF321
 
+RomFs:
+  # Specifies the root path of the read only file system to include in the ROM.
+  RootPath                : $(APP_ROMFS)
+
 Option:
   UseOnSD                 : true # true if App is to be installed to SD
   FreeProductCode         : true # Removes limitations on ProductCode





More information about the Scummvm-git-logs mailing list